Stmívač LED pásku - Software v. 1.3

Zápisník experimentátora

Hierarchy: Stmievač LED pásika pomocou ATtiny85

V tomto článku vysvětlím princip činnosti stmívače LED pásků. Je to čtvrtý ze série článků, na kterých vám ukážu, jak postupně probíhá vývoj programů a jak diametrálně se může lišit výsledný program. Tento text popisuje aktuální verzi kódu 1.3.

V ideálním světě napíšete ideální program hned napoprvé a nebudou v něm žádné chyby a bude dělat přesně to, co jste si představovali. A teď vítejte v reálném světě, ve kterém jsem se pokusil naprogramovat logiku stmívání tak, aby vyhovovala práci v kuchyni.

Arduino IDE

Kód byl vyvíjen ještě pro verzi 1.0.6, ale bez problémů jej lze zkompilovat i v 1.6.13 nebo 1.8.2. Zabírá po zkompilovaný 3038 (6254 se zapnutým debuggování) bajtů. Je nutné mít nainstalovanou podporu pro programování ATtiny85.

Programování

V tomto programu jsem se soustředil na snížení spotřeby energie. Většinu času totiž program jen čeká na signál ze senzoru a na to nepotřebuje mnoho strojového času. Proto se program uspává na bloky času trvající 64 ms, během kterých je spotřeba mikrokontroléru na minimu. Celý vývoj probíhal na vývojové desce pro ATtiny85, kterou jsem již popisoval v předchozím článku.

Na uspávání mikrokontroléru se obvykle využívá watchdog timer. Aby celé uspávání fungovalo, je třeba doplnit do programu následující řádky.

  • Na začátku programu si připojíme dva hlavičkové soubory. Ty nám slouží k získání podpory pro pohodlné bitové operace a funkce na uspávání mikrokontroléru.
  • Definujeme si enum wdtimer, kde vytvoříme všechny symbolické možnosti pro uspávání. Aby byl program svižný, budeme používat uspávání na 64 ms.
  • Ve funkci setup vypneme ADC, protože i to spotřebuje trochu energie a v programu ho nepotřebujeme. Potom ještě nastavíme watchdog timer funkcí setup_watchdog.
  • Ve funkci LightDark je ukryta celá logika uspávání. Zavolá se funkce system_sleep, která uspí mikrokontrolér. Udělá to vždy, když nemá signál ze senzoru. V praxi stráví mikrokontrolér prakticky veškerý čas v této funkci, protože většinu dne žádné signály z PIR senzoru nebudou přicházet.
  • Funkce system_sleep slouží na uspání mikrokontroléru. Po probuzení se začne provádět kód na konci funkce, což je přesně to, co potřebujeme. Probudíme se ze spánku, zkontrolujeme PIR senzor a pokud se nic neděje, zase se uspíme.
  • Funkce setup_watchdog slouží k nastavení správných bitů pro watchdog timer.
  • Přerušení z watchdog timeru v podstatě v tomto kódu nepotřebujeme, ale přiznávám bez mučení, že jsem poslední dvě funkce odněkud přebral a neměl jsem chuť na tom nic měnit. Ale kdybyste na něco potřebovali i obsluhu přerušení, dává vám signál do proměnné signal_wdt.
#include "wiring_private.h"
#include <avr/sleep.h>

enum wdtimer {wdt16ms=0, wdt32ms, wdt64ms, wdt128ms, wdt250ms, wdt500ms, wdt1s, wdt2s, wdt4s, wdt8s};
volatile boolean signal_wdt = 1;

void setup() {               
  // disable adc
  cbi(ADCSRA, ADEN);
  setup_watchdog(wdt64ms);
 ...
}

void LightDark() {
  int p=digitalRead(dig);
  if(p)
    state=stOn;
  else
    system_sleep();
}

void system_sleep() {
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
  sleep_enable();
  sleep_mode();                        // System sleeps here
  sleep_disable();                     // System continues execution here when watchdog timed out
}

void setup_watchdog(byte t) {
  byte bb;
  int ww;
  if(t>wdt8s)
    t=wdt8s;
  bb=t&7; // WDP[2:0]
  if(t>wdt2s)
    sbi(bb,WDP3);
  sbi(bb,WDCE);
  ww=bb;

  cbi(MCUSR,WDRF);
  // start timed sequence
  WDTCR |= (1<<WDCE) | (1<<WDE);
  // set new watchdog timeout value
  WDTCR = bb;
  sbi(WDTCR,WDIE);
}

ISR(WDT_vect) {
  signal_wdt=1;  // set global flag
}

Zdrojový kód

Zdrojový kód se nachází na GitHub.


27.06.2017


Menu