Nedodržel jsem číslování pinů a logiku spínání tlačítek, ale to už by neměl být problém upravit.
Mám to tak, že tlačítka jsou proti GND. Takže aktivní dává signál LOW.
Logika signálu se kopíruje na LED, takže aby LED svítila při LOW, musí být připojena proti Vcc.
Program si pamatuje sekvenci 20 stisků pro 4 tlačítka.
Změna velikosti bufferu je možná přes úpravu konstanty "MAX_BUFFER".
Pro čtení tlačítek využívám vnitřní registr PIND, který zjistí stav všech 4 vstupů najednou.
Odrušení zákmitů provádím přes delay(50).
V krátkosti princip:
Program v hlavní smyčce testuje změny stavu tlačítek.
Když k nějaké změně dojde (a není to uvolnění), zapíše se aktuální stav tlačítek jako bajt do pole pamet[] na pozici, na kterou ukazuje ukazatel.
Při zápisu se zvětší ukazatel do toho pole o 1.
Když se pole zaplní, zahlásí se do sériové linky "PREPLNENI BUFFERU!"
V druhé části programu se testuje stisk vyčítacího tlačítka.
Když se zjistí, že je stisknuté, vezme se nejstarší záznam z pole (index 0) a jeho jednotlivé bity se převedou na výstupní piny.
Hned potom se celý buffer (celé pole) přesype o jeden index níž (z indexu 1 se stane index 0, z indexu 2 se stane index 1 ..... až do indexu 20).
Ukazatel do pole se sníží o 1.
Když ukazatel doběhne do 0, zahlásí se "BUFFER PRAZDNY".
Dokud je vyčítací tlačítko stisknuté, program čeká ve smyčce.
Po uvolnění tlačítka se běh programu vrací do hlavní smyčky na další testování vstupních tlačítek.
Tady je video:
https://youtu.be/TfgsgVNLhCw
kód:
Kód: Vybrat vše
// Vstupy 2, 3, 4, 5 (Tlacitka proti GND. V rozepnutem stavu jsou v HIGH)
// Vystupy 9, 10, 11, 12 (LED proti Vcc. Aktivni LED jsou v '0')
// Cteci pin 6 (Tlacitko proti GND. V rozepnutem stavu je v HIGH)
#define MAX_BUFFER 20 // maximalni pocet zapamatovatelnych stavu
byte pamet[MAX_BUFFER]; // buffer, kam se bude ukladat postupny stav vstupu
byte ukazatel; // ukazatel do bufferu, kam se bude ukladat posledni stav
byte posledni_stav_vstupu; // slouzi ke zjistovani zmen na vstupech
//------------------------------------------
void setup(void)
{
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
pinMode(6, INPUT_PULLUP);
Serial.begin(9600); // Seriovy vystup jen pro debugovani
for (byte i = 0; i < MAX_BUFFER; i++) // vynulovani pameti (vsechny vystupy do neaktivniho HIGH)
{
pamet[i] = 0b11111111;
}
}
//------------------------------------------
void loop(void)
{
testuj_zmeny(); // testovani, jestli doslo k nejake zmene na vstupech a pripadny zapis do bufferu
testuj_vycitani(); // testovani, jestli prichazi impulzy na ctecim pinu a pripadne cteni bufferu a ovladani vystupu
}
//------------------------------------------
void testuj_zmeny(void)
{
byte stav_vstupu = (PIND & 0b00111100); // precteni vsech 4 vstupu najednou D2 az D5 (odpovida to bitum 2 az 5 v registru PIND)
if (stav_vstupu == 0b00111100) // zadne tlacitko neni stisknute
{
posledni_stav_vstupu = stav_vstupu; // v tomto podprogramu se nic dit nebude a normalne se vypadne
}
if (stav_vstupu == posledni_stav_vstupu) // od minule nenastala zadne zmena, nebo jsou vsechna vstupni tlacitka rozepnuta
{
delay(50); // odruseni zakmitu pred vypadnutim z podprogramu
return;
}
posledni_stav_vstupu = stav_vstupu; // zapamatovat si posledni stisknute tlacitko (aby se v dalsi smycce tento stav ignoroval)
pamet[ukazatel] = stav_vstupu;
ukazatel ++;
if (ukazatel > 20)
{
Serial.println("PREPLNENI BUFFERU!");
ukazatel = 20;
}
delay(50); // odruseni zakmitu pri uvolnovani vstupnich tlacitek
}
//------------------------------------------
void testuj_vycitani(void)
{
if (digitalRead(6) == LOW) // vycitaci tlacitko sepnuto
{
digitalWrite( 9,bitRead(pamet[0],2)); // D2 se prepisuje na D9
digitalWrite(10,bitRead(pamet[0],3)); // D3 se prepisuje na D10
digitalWrite(11,bitRead(pamet[0],4)); // D4 se prepisuje na D11
digitalWrite(12,bitRead(pamet[0],5)); // D5 se prepisuje na D12
for (byte i = 1 ; i < MAX_BUFFER ; i++) // posunuti celeho bufferu o jednu polozku dolu
{
pamet[i-1] = pamet[i];
}
if (ukazatel > 0) ukazatel --; // ukazatel do pameti se o 1 snizi (nesmi ale podlezt pod 0)
else Serial.println("BUFFER PRAZDNY");
}
while (digitalRead(6) == LOW) // dokud je vycitaci tlacitko stisknute
{
delay(10); // program stoji v teto smycce
}
delay(50); // pripadne odruseni zakmitu
digitalWrite( 9,HIGH); // vsechny LED zhasnout
digitalWrite(10,HIGH);
digitalWrite(11,HIGH);
digitalWrite(12,HIGH);
}