Stmievač LED pásika - Softvér v. 1.3

Zápisník experimentátora

Hierarchy: Stmievač LED pásika pomocou ATtiny85

V tomto článku vysvetlím princíp činnosti stmievača LED pásikov. Je to štvrtý zo série článkov, na ktorých vám ukážem, ako postupne prebieha vývoj programov a ako diametrálne sa môže líšiť výsledný program. Tento text popisuje aktuálnu verziu kódu 1.3.

V ideálnom svete napíšete ideálny program hneď na prvý raz a nebudú v ňom žiadne chyby a bude robiť presne to, čo ste si predstavovali. A teraz vitajte v reálnom svete, v ktorom som sa pokúsil naprogramovať logiku stmievania tak, aby vyhovovala práci v kuchyni.

Arduino IDE

Kód bol vyvíjaný ešte pre verziu 1.0.6, ale bez problémov ho možno skompilovať aj v 1.6.13 alebo 1.8.2. Zaberá po skompilovaní 3038 (6254 so zapnutým debuggovaním) bajtov. Je nutné mať doinštalovanú podporu pre programovanie ATtiny85.

Programovanie

V tomto programe som sa sústredil na zníženie spotreby energie. Väčšinu času totiž program len čaká na signál zo senzora a na to nepotrebuje veľa strojového času. Preto sa program uspáva na bloky času trvajúce 64 ms, počas ktorých je spotreba mikrokontroléra na minime. Celý vývoj prebiehal na vývojovej doske pre ATtiny85, ktorú som už popisoval v predchádzajúcom článku.

Na uspávanie mikrokontroléra sa obvykle využiva watchdog timer. Aby celé uspávanie fungovalo, je potrebné doplniť do programu nasledovné riadky.

  • Na začiatku programu si pripojíme dva hlavičkové súbory. Tie nám slúžia na získanie podpory pre pohodlné bitové operácie a funkcie na uspávanie mikrokontroléra.
  • Definujeme si enum wdtimer, kde vytvoríme všetky symbolické možnosti pre uspávanie. Aby bol program svižný, budeme používať uspávanie na 64 ms.
  • Vo funkcii setup vypneme ADC, pretože aj to spotrebuje trochu energie a v programe ho nepotrebujeme. Potom ešte nastavíme watchdog timer funkciou setup_watchdog.
  • Vo funkcii LightDark je ukrytá celá logika uspávania. Zavolá sa funkcia system_sleep, ktorá uspí mikrokontrolér. Urobí to vždy, keď nemá signál zo senzora. V praxi strávi mikrokontrolér prakticky všetok čas v tejto funkcii, pretože väčšinu dňa žiadne signály z PIR senzora nebudú prichádzať.
  • Funkcia system_sleep slúži na uspatie mikrokontroléra. Po prebudení sa začne vykonávať kód na konci funkcie, čo je presne to, čo potrebujeme. Prebudíme sa zo spánku, skontrolujeme PIR senzor a ak sa nič nedeje, zase sa uspíme.
  • Funkcia setup_watchdog slúži na nastavenie správnych bitov pre watchdog timer.
  • Prerušenie z watchdog timera v podstate v tomto kóde nepotrebujeme, ale priznávam bez mučenia, že som posledné dve funkcie odniekiaľ prebral a nemal som chuť na tom nič meniť. Ale keby ste na niečo potrebovali aj obsluhu prerušenia, dáva vám signál do premennej 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 sa nachádza na GitHub.


27.06.2017


Menu