Zápisník experimentátora
Hierarchy: WS2812
Vo štvrtom článku rozvinieme ovládanie tlačidlami. Použijeme tri tlačidlá a naprogramujeme si stavový automat, ktorý umožní prepínanie medzi behom hodín a ich nastavovaním. Táto verzia programu sa už bude blížiť výslednému kódu.
Voči predchádzajúcej schéme sa zmenilo to, že máme namiesto jedného tlačidla tri.
Konfigurácia sa nám rozrástla, ale voči minulému článku to nepredstavuje zložitú zmenu. Iba nám pribudli ďalšie premenné. V súbore clockdefs.h máme definície stavov, ktoré môže program nadobúdať. Používame tri stavy, ktoré sa ukladajú v premennej cs:
A pribudli nám aj premenné hour a minute, aby sme mohli tlačidlami upravovať ich hodnotu.
#include "clockdefs.h"
///
/// Program configuration
///
struct Configuration
{
ClockState cs;
bool show_millis;
int hour;
int minute;
Configuration()
: show_millis(SHOWMILLIS), cs(csClock), hour(STARTHOUR), minute(STARTMINUTE) {}
};
Configuration cfg;
///
/// Set all colors
///
void NeoClock::Draw()
{
Clear();
switch(cfg.cs)
{
case csClock:
DrawClock();
break;
case csHourSet:
DrawHour();
break;
case csMinuteSet:
DrawMinute();
break;
};
strip.show();
}
Ak sa nachádzame v stave csHourSet, vykresľujeme iba hodinovú ručičku. Pretože používame NeoPixel s 12 LED, vykresľujeme aktuálnu hodinu iba na konkrétnom bode.
Ak sa nachádzame v stave csMinuteSet, musíme nejakým spôsobom vykresliť 60 hodnôt na 12 LED. Preto používame algoritmus, ktorý počiatočný bod vykresľuje na pozícii minute/5 a ku tomu vykresľuje chvostík zo zvyšného modula minút minute%5. Podľa toho vieme ľahko odpočítať koľko máme nastavených minút.
///
/// Draw hours during setup
///
void NeoClock::DrawHour()
{
AddColor((hour+MOVE) % CNT, hour_color );
}
///
/// Draw minutes during setup
///
void NeoClock::DrawMinute()
{
// position/5
AddColor((minute+MOVE) % CNT, minute_color);
// tail as modulo 5
uint32_t m=millis()+60000L*cfg.minute+3600000L*cfg.hour;
int mm = (m/60000) % 60;
int mmm = mm % 5;
for(int i=0;i<mmm;i++)
AddColor((minute+MOVE-i-1) % CNT, minute_color);
}
Aby sme mohli nastavovať hodiny a minúty, používame tri tlačidlá. Ich význam sa mení podľa stavu, v ktorom sa program nachádza. Keďže používame stavový automat, je výsledný kód ľahko pochopiteľný. Treba si len uvedomiť význam jednotlivých tlačidiel:
// button, 25 ms debounce, no repeat, internal pull_up
Button b_select(SELECTPIN,ButtonActionSelect,25,0,true);
// button, 25 ms debounce, repeat 100 ms, internal pull_up
Button b_plus(PLUSPIN,ButtonActionPlus,25,100,true);
Button b_minus(MINUSPIN,ButtonActionMinus,25,100,true);
///
/// When button is pressed
///
void ButtonActionSelect(Button *b)
{
if(b->pressed)
{
switch(cfg.cs)
{
case csClock:
cfg.cs=csHourSet;
break;
case csHourSet:
cfg.cs=csMinuteSet;
break;
case csMinuteSet:
cfg.cs=csClock;
break;
};
}
}
void ButtonActionPlus(Button *b)
{
if(b->pressed)
{
switch(cfg.cs)
{
case csClock:
cfg.show_millis=!cfg.show_millis;
break;
case csHourSet:
cfg.hour++;
if(cfg.hour>23)
cfg.hour=0;
break;
case csMinuteSet:
cfg.minute++;
if(cfg.minute>59)
cfg.minute=0;
break;
};
}
}
void ButtonActionMinus(Button *b)
{
if(b->pressed)
{
switch(cfg.cs)
{
case csClock:
cfg.show_millis=!cfg.show_millis;
break;
case csHourSet:
cfg.hour--;
if(cfg.hour<0)
cfg.hour=23;
break;
case csMinuteSet:
cfg.minute--;
if(cfg.minute<0)
cfg.minute=59;
break;
};
}
}
V budúcom článku pripojíme ku obvodu hodiny reálneho času. Kto chce študovať zapojenie obvodu DS1307, môže tak urobiť v samostatnom článku už teraz.
24.08.2015