Tak z toho zkuste udělat tu challenge.
---
Princip mého řešení:
Nepoužívám žádné millis(). O veškeré časování se stará delay(10) na konci hlavní smyčky.
Hlavní smyčka tak cykluje 100x za sekundu. To je dostatečně rychlé na vyhodnocování stisku tlačitek.
Odrušení zákmitů řeším jednoduchým delay(50). Po stisku nebo uvolnění tlačítka se program na 50ms zastaví a nechá tlačíko, ať si zakmitá jak potřebuje. Během té doby se prostě netestuje stav digitálního vstupu. Po 50ms už by mělo být tlačítko klidné.
V programu se pak v proměnné "stav_1" udržuje informace o aktuální fázi běhu (popis všech stavů je na začátku programu)
Proměnná "stav_1" se mění na základě stisků, nebo uvolnění tlačítka a v závislosti na předchozím stavu.
Příklad:
stav_1 = 3 znamená, že je program ve fázi, kdy motor běží v automatickém režimu. Když v tomto stavu dojde ke stisku tlačítka, změní proměnná "stav_1" hodnotu na 5, což namená, že byl automat přerušen.
Podprogram motor_1() pak na základě proměnné "stav_1" (a případně proměnné pro automatický odpočet) ovládá motor.
Serial.printy jsou pro chod programu nepodstatné. Zobrazují jen aktuální fáze běhu programu jako textová hlášení.
Při rozšíření programu o další tlačítka a motory stačí zkopírovat podprogramy "tlacitko_1()" a "motor_1()", změnit jim názvy a upravit v nich číslované proměnné (stav_1, pin_out_1, odpocet_pohybu_1 ....).
Nové proměnné je pak nutné přidat do bloku globálních proměnných a v setupu nastavit směr pinů.
Nevýhody řešení:
- Časování není úplně přesné. K delay se přidávají ještě zpoždění pro jednotlivé podprogramy. Při odrušování zákmitů se časování také prodlužuje.
- V programu neřeším eventuality, jako je například držení tlačítka po dobu delší než 655,35 sekund (to je asi 11 minut). Po té době dojde k přetečení proměnné.
- V programu byl použit velice jednoduchý princip odrušení tlačítek. Při hodně špatné kvalitě tlačítkek ale nemusí být účinný.
( viz
viewtopic.php?f=19&t=2886 )
Kód: Vybrat vše
// Zadani: https://forum.hwkitchen.cz/viewtopic.php?f=37&t=2938
//------------------
// Když zmáčknu tlačítko po dobu menší než 2s, tak se sepne relé na 1min.
// V případě že během té 1min opět stačím tlačítko tak se cyklus přeruší.
// Když podržím tlačítko na dobu delší než 2s relé bude seplé po dobu jakou bude stlačené tlačítko.
//-----------------
#define pin_tl_1 5 // pin s tlacitkem proti GND
#define pin_out_1 13 // vystupni pin na motor
#define automat_cas 6000 // trvani automatickeho behu motoru v setinach sekundy
byte stav_1; // 0 = vychozi stav (motor stoji)
// 1 = drzeni tlacitka pri zastavenm motoru - nacitani doby stisku (po 2 sekundach se prechazi do rezimu 4)
// 2 = tlacitko bylo uvolneno, stisk musel byt kratky
// 3 = motor se toci, tlacitko uvolneno (probiha minutovy odpocet)
// 4 = motor se toci, tlacitko stisknuto (beh do doby, nez se tlacitko uvolni)
// 5 = tlacitko stisknuto pri automatickem behu. Pri naslednem uvolneni se prechazi na stav 0
unsigned int delka_stisku_1; // jak dlouho uz trva stisk tlacitka (v setinach sekundy)
unsigned int odpocet_pohybu_1; // jak dlouho ma motor jeste bezet (v setinach sekundy)
//==========================================================================================================
void setup(void)
{
Serial.begin(9600);
pinMode(pin_tl_1 , INPUT_PULLUP);
pinMode(pin_out_1, OUTPUT);
Serial.println("Zacatek programu - zakladni stav se zastavenym motorem");
}
//==========================================================================================================
void loop(void)
{
tlacitko_1(); // vyhodnocovani stavu prvniho tlacitka
motor_1(); // ovladani prvniho motoru
// pripadne rozsireni o dalsi tlacitka a motory
// tlacitko_2(); // vyhodnocovani stavu druheho tlacitka
// motor_2(); // ovladani druheho motoru
delay(10); // zakladni casovani jedne smycky na setinu sekundy
}
//==========================================================================================================
//=========================================================================
//----------------- vyhodnocovani stisku tlacitka --------------------------
void tlacitko_1(void)
{
if (digitalRead(pin_tl_1) == LOW and stav_1 == 0) // Tlacitko bylo stisknuto behem zastaveneho motoru
{
delka_stisku_1 = 0; // delka stisku tlacitka se vynuluje
stav_1 = 1; // drzeni tlacitka pri zastavenem motoru
delay(50); // odruseni zakmitu pri sepnuti (po dobu, kdy zakmitava se procesor zastavi)
Serial.println("prave stisknute tlacitko pri zastavenem motoru");
}
if (digitalRead(pin_tl_1) == LOW and stav_1 == 1) // Tlacitko je drzeno pri zastavenem motoru
{
// tady se zakmity tlacitka neodrusuji, protoze stisk trva
delka_stisku_1 ++; // pocitani doby drzeni v setinach sekundy
if (delka_stisku_1 > 200) // po dvou sekundach drzeni se okamzite spousti motor
{
stav_1 = 4;
Serial.println("dlouhy stisk - RUCNI OVLADANI MOTORU");
}
}
if (digitalRead(pin_tl_1) == HIGH and stav_1 == 1) // Tlacitko bylo uvolneno pri zastavenem motoru (musel to byt kratky stisk, jinak by neplatil stav_1 == 1)
{
delay(50); // odruseni zakmitu pri rozepinani tlacitka
odpocet_pohybu_1 = automat_cas; // casovani pohybu se nastavi na 60 sekund
stav_1 = 3; // spustit motor v automatickem rezimu
Serial.println("kratky stisk - MINUTOVY POHYB");
}
if (digitalRead(pin_tl_1) == HIGH and stav_1 == 4) // Tlacitko bylo uvolneno pri rucne ovladanem motoru
{
delay(50); // odruseni zakmitu pri rozepnuti
stav_1 = 0;
odpocet_pohybu_1 = 0;
Serial.println("preruseni rucniho ovladani");
Serial.println("zakladni stav se zastavenym motorem");
}
if (digitalRead(pin_tl_1) == LOW and stav_1 == 3) // Tlacitko bylo stisknuto pri automaticky bezicim motoru
{
delay(50); // odruseni zakmitu pri sepnuti
stav_1 = 5; // priprava na prechod do zakladniho stavu se zastavenym motorem
odpocet_pohybu_1 = 0; // predcasne preruseni casovani
Serial.println("stisk tlacitka pri behu motoru - STOP");
}
if (digitalRead(pin_tl_1) == HIGH and stav_1 == 5) // Tlacitko bylo uvolneno po predcasnem ukonceni behu
{
delay(50); // odruseni zakmitu pri uvolneni
stav_1 = 0; // prechod do zakladniho stavu se zastavenym motorem
Serial.println("zakladni stav se zastavenym motorem");
}
}
//=========================================================================
//=========================================================================
//----------------- ovladani motoru podle promenne 'stav_1' ----------------
void motor_1(void)
{
if (stav_1 == 3) // motor ma bezet s casovanim
{
if (odpocet_pohybu_1 > 0)
{
digitalWrite(pin_out_1, HIGH); // motor bezi
odpocet_pohybu_1 --; // casovani behu se snizi o setinu sekundy
}
else // odpocet behu vyprsel
{
digitalWrite(pin_out_1, LOW); // motor se zastavi
stav_1 = 0; // prepne se do zakladniho stavu
Serial.println("motor se prave zastavil");
}
}
if (stav_1 == 4) // motor ma bezet s rucnim ovladanim
{
digitalWrite(pin_out_1, HIGH); // motor bezi
}
if (stav_1 == 0 or stav_1 == 5) // motor v zakladnim stavu, nebo pri preruseni automatickeho behu
{
digitalWrite(pin_out_1, LOW); // motor stoji
}
}
//=========================================================================