Našel jsem v internetu knihovnu Tasker jako "vedlejší produkt" při stavbě inteligentního termostatu, uchvátilo mě to natolik že jsem jí musel na něčem vyzkoušet a už teď vím že jí chci použít pro Dobbyho.Knihovna Tasker řeší přesné časování funkcí. Pro vyzkoušení jsem sepsal jednoduché hodinky s nastavením.
#include <SPI.h>
#include <TFT_ST7735.h>
#include "Tasker.h"
/* knihovna tasker je normálně dostupná v Projekt->Přidat knihovnu->Spravovat knihovny vyhledáním knihovny Tasker by Petr Stehlík */
/*
Nastavení pro displej 1.44' SPI 128*128 V2.1 pro Arduino UNO
v knihovně pro ST7735 ve složce _settings v souboru TFT_ST7735_settings.h je potřeba změnit nastavení pro SMALL displej, původně je nastaveno pro displej 128*160
#if !defined (TFT_ST7735_INSTANCES)
//#include "../_display/TFT_ST7735_RED_PCB1.h" // tohle zakomentovat
#include "../_display/TFT_ST7735_RED_PCB_SMALL.h" // tohle odkomentovat
//more to come
#endif
SPI displej UNO Leonardo
--------------------------
SCK SCK 13 prostřední pin v horní řadě ICSP konektoru pokud je USB nahoře
MOSI SDA 11 prostřední pin v dolní řadě ICSP
CS1 CS 10 10
DC AO 9 9
RESET VCC
LED VCC
VCC VCC
GND GND
*/
TFT_ST7735 tft = TFT_ST7735(10,9);// nastavení displeje
Tasker tasker;// kouzelná knihovna tasker
int pres=0; //tlačítko na pinu3 stisknuto ...x100ms
int tla=0; //tlačítko na pinu2 stisknuto ...x100ms
int h=9; //hodiny
int m=58; //minuty
int s=0; //sekundy
int menu=0; //flag neboli vlajka určující kde se nacházím v Menu 0=nejsem v menu 1=nastavuji hodiny 2=nastavuji minuty 3=odchod z menu
bool pressed=false; //příznak stiknutého tlačítka na pinu3
bool tlased=false; //příznak stiknutého tlačítka na pinu2
void task1() { //funkce vykonávaná jednou za 100ms
if (digitalRead(3)==LOW) {//pokud je tlačítko stiknuto počítej jak dlouho je stisknuto a nastav příznak stisknutí na TRUE
pres++;
pressed=true;
} else pressed=false;// jinak nastav příznak stisknutí na FALSE
if (digitalRead(2)==LOW) {
tla++;
tlased=true;
} else tlased=false;
}
void setup() {
tft.begin();//inicializace displeje
pinMode(2,INPUT_PULLUP);//nastavení pinů jako vstupů s PULLUP rezistorem, takže pin je trvale ve stavu HIGH, tlačítko se spojuje s GND a tím pádem je aktivní ve stavu LOW (trochu obrácená logika ale je to výrazně bezpečnější a míň náchylné k rušení)
pinMode(3,INPUT_PULLUP);
tasker.setInterval(task1,100);//kouzelná knihovna Tasker,tady se nastavuje že funkce task1 má být vykonána každých 100ms
tasker.setInterval(cas, 1000);//a funkce cas každých 1000ms tedy jednou za sekundu a běží to dosti přesně
}
void loop() {
tasker.loop(); //opět kouzelná knihovna Tasker, NIKDE v programu nesmí být použito delay()
if (pres>10 && !pressed) {// pokud tlačítko na pinu2 bylo stisknuto déle než 10x100ms a je uvloněno ...
menu++; //posuň se v menu na další položku
displej(); //vykresli displej
pres=0; //vynuluj stav tlačítka
}
if (menu>0) { //pokud je menu aktivní nastav sekundy na nulu a vypni Tasker pro počítání času
s=0;
tasker.cancel(cas);
}
if (menu==1 && pres>0 && !pressed) { //pokud je menu na první položce a zároveň tlačítko na pinu2 bylo stisknuto a uvolněno připočítej hodinu, vykresli displej a vynuluj stav tlačítka
h++;
if (h>23) h=0;
pres=0;
displej();
}
if (menu==1 && tla>0 && !tlased) { //pokud je menu na první položce a zároveň tlačítko na pinu3 bylo stisknuto a uvolněno odečti hodinu, vykresli displej a vynuluj stav tlačítka
h--;
if (h<0) h=23;
tla=0;
displej();
}
if (menu==2 && pres>0 && !pressed) {
m++;
if (m>59) m=0;
pres=0;
displej();
}
if (menu==2 && tla>0 && !tlased) {
m--;
if (m<0) m=59;
tla=0;
displej();
}
if (menu>2) { //pokud opouštíš menu, vynuluj stav stav flagu, nastav tasker pro počítání času,vykresli displej
menu=0;
tasker.setInterval(cas, 1000);
displej();
}
}
void displej(void) {
tft.clearScreen();
tft.setRotation(0);
tft.setTextScale(3);
tft.setCursor(0, 0);
if (menu==1) tft.setTextColor(RED,WHITE);
else tft.setTextColor(WHITE,BLACK);
if (h<10) tft.print(" ");
tft.print(h);
tft.setTextColor(WHITE,BLACK);
tft.print(":");
if (menu==2) tft.setTextColor(RED,WHITE);
else tft.setTextColor(WHITE,BLACK);
if (m<10) tft.print("0");
tft.print(m);
tft.setTextColor(WHITE,BLACK);
tft.print(":");
if (menu==3) tft.setTextColor(RED,WHITE);
else tft.setTextColor(WHITE,BLACK);
if (s<10) tft.print("0");
tft.println(s);
}
void cas(void) {
s++;
if (s>59) {
s=0;
m++;
if (m>59) {
m=0;
h++;
if (h>23) {
h=0;
}
}
}
displej();
}
Celé je postavené právě na knihovně Tasker. V Setupu si nastavím kterou funkci a jak často chci volat a dál se o její načasování nestarám. Pro obsluhu tlačítek je někdy lepší použít přerušení, tady mi bohatě stačí každých 100ms testovat jestli je tlačítko stisknuto a počítat si čas jak dlouho je stisknuto. Neřeším případné zákmity, ptám se jen 10x za sekundu a pokud někdy mezitím tlačítko zakmitá tak je mi to jedno protože mě zajímá jestli v průběhu víc než 100ms bylo dvakrát načteno jako stisknuté. Elegantní, prosté, blbuvzdorné. Jediné negativum je že displej zareaguje až po uvolnění tlačítka, takže když budu magor a budu ho držet půl hodiny, tak půl hodiny se nic dít nebude, prostě ho musím uvolnit a pak se něco stane. Pro ovládání nastavení hodin jsem zvolil jednotlačítkový systém, krátký a dlouhý stisk (<1000 a >1000 ms), který jsem až potom doplnil o druhé tlačítko pro sestupné nastavování. Na displeji si sice pohrávám s barvou ale není problém to přepsat pro LCD displej a použít inverzní zobrazení jako kurzor co právě nastavuji.
Ještě chci nastudovat knihovnu Time.h pro lepší práci s časem. Knihovna Time totiž řeší i dny v týdnu a datum, navíc umí vypočítat UNIX TIME, tedy počet sekund od 1.1.1970. To je stejný čas který používám v databázích a podle kterého se řídí Dobby. Pak možná tenhle příklad doplním o nastavení kolikátého vlastně je.
Odkaz na video