Hodiny z NeoPixel Ring - ovládanie tlačidlami

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.

Schéma

Voči predchádzajúcej schéme sa zmenilo to, že máme namiesto jedného tlačidla tri.

Konfigurácia programu

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:

  • csClock - V tomto stave sa zobrazujú normálne hodiny s hodinami, minútami a sekundami. Tento stav zodpovedá normálnemu behu programu z minulého článku.
  • csHourSet - V tomto stave sa dajú nastavovať hodiny.
  • csMinuteSet - V tomto stave sa dajú nastavovať minúty.

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();
}

Vykreslenie počas nastavovania

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);
}

Ovládanie tlačidlami

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:

  • b_select - Postupne prepína jednotlivé stavy.
  • b_plus - Ak sme v stave csClock, prepína sa zobrazenie milisekúnd. V stave nastavovania pripočítava hodnotu 1 ku hodinám alebo minútam.
  • b_minus - Ak sme v stave csClock, prepína sa zobrazenie milisekúnd. V stave nastavovania odpočítava hodnotu 1 ku hodinám alebo minútam.
// 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;  
    };
  }  
}

Nabudúce

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.



Download

24.08.2015


Menu