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

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. Bude to prvý 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. Postupne prejdeme zdrojové kódy programu od verzie 1.0 po verziu 1.3.

Tento text popisuje zastaranú verziu kódu. V čase písania článku bola aktuálna verzia kódu 1.3. Táto verzia je tu analyzovaná preto, aby ste si mohli pozrieť, ako prebieha vývoj programov metódou postupného približovania.

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.1. Zaberá po skompilovaní 1830 bajtov. Je nutné mať doinštalovanú podporu pre programovanie ATtiny85.

Programovanie

V tomto programe som sa sústredil na základné činnosti programu. Celý vývoj prebiehal na vývojovej doske pre ATtiny85, ktorú som už popisoval v predchádzajúcom článku.

Najprv som si zadefinoval premenné. Kvôli optimalizácii prekladača je väčšina premenných s modifikátorom const. Premenná pot_value má hodnotu 2000, čo je čas v milisekundách, ktorý je potrebný na rozsvietenie LED pásika. Premenná hold_value má hodnotu 30000, čo predstavuje 30 sekúnd udržania plného svietenia LED pásika a to bez ohľadu na to, či infračervený senzor zaznamenal nejaký pohyb.

// pin definitions
const int led = 0;
const int dig = 1;
// base ON period
const unsigned long pot_value = 2000;
unsigned long dig_last;
// base hold period
const unsigned long hold_value = 30*1000;

Vo funkcii setup sa nastavia piny, ktoré na stmievanie potrebujem. Pin led ovláda stmievanie pásika a pin dig číta hodnotu z infračerveného senzora.

void setup() {                
  pinMode(led, OUTPUT); 
  pinMode(dig, INPUT); 
}

Funkcia LightOn zabezpečuje postupné rozsvietenie LED pásika. Robí to tak, že sleduje čas od začiatku funkcie a mapuje ho na hodnotu 0-255. Túto hodnotu potom nastavuje na pine pomocou PWM, čo vytvára efekt postupného rozsvietenia. Akonáhle uplynie 2000 ms, funkcia nastaví plné svietenie a ukončí sa.

void LightOn() {
int v=0;
unsigned long ms=millis();
unsigned long m=0;
unsigned long m2=pot_value;
while(m<m2)
  {
  analogWrite(led,map(m,0,m2,0,255)); 
   m=millis()-ms; 
  }
digitalWrite(led, HIGH);  
}

Funkcia LightHold udržuje plné osvetlenie. Udržuje ho minimálne 30 sekúnd. Ak medzitým dostane ďalší signál z infračerveného senzora, posunie si konečnú hodnotu času zase o 30 sekúnd neskôr. Tým reaguje na to, že sa pohybujete v miestnosti pred senzorom. Pokiaľ sa hýbete, svetlo bude svietiť.

void LightHold() {
while(millis()<dig_last)
  {
  int p=digitalRead(dig);
  if(p) // still ON
    dig_last=millis()+hold_value;
  }
}

Funkcia LightOff zabezpečuje postupné zhasnutie svetla. Zhasnutie má dvojnásobnú dĺžku ako rozsvietenie. trvá teda 4000 ms. A funguje presne naopak. Mapuje hodnotu času od začiatku funkcie na hodnotu 255-0. Akonáhle uplynie 4000 ms, funkcia vypne svietenie a ukončí sa.

void LightOff() {
unsigned long ms=millis();
unsigned long m=0;
unsigned long m2=pot_value*2; // 2x on period
while(m<m2)
  {
  analogWrite(led,map(m,0,m2,255,0)); 
   m=millis()-ms; 
  }
digitalWrite(led, LOW);  
}

Celú logiku zastrešuje funkcia loop. Pokiaľ nedostane signál z infračerveného senzora, nič sa nedeje. Keď dostane signál, postupne zavolá všetky tri funkcie. Predtým ešte nastaví čas vypnutia. Ak sa na poradie volania dobre pozriete, uvidíte, že čas plného svietenia v skutočnosti bude 30000-2000 ms. Lebo som nezohľadnil to, že prvá funkcia trvá 2000 ms. Aj takéto veci sa stávajú, ale na výsledku to prakticky nevidno a tak to nie je chyba, ale dajme tomu nedokonalosť.

void loop() {
  int p=digitalRead(dig);
  if(p) {
    dig_last=millis()+hold_value;
    LightOn(); 
    LightHold();
    LightOff();
  }
}

Na komentovanom kóde vidíte, že logika stmievania nie je vôbec zložitá. Jednoduchosť je ale vyvážená mnohými nedokonalosťami.

  • Akonáhle sa začne stmievať, už sa to nedá prerušiť.
  • Stmievanie sa deje lineárne z pohľadu výpočtu, ale ľudské oko tak nefunguje a výsledkom je prudké rozsvietenie so skoro nepostrehnuteľným začiatkom a rovnako vyzerá aj zhasnutie. Na malej LED dióde z vývojovej dosky to nebolo také okaté, ale reálne nasadenie ukázalo všetky drobné nedokonalosti.
  • Aj počas úplného zhasnutia spotrebuje mikrokontrolér niekoľko miliampérov. Napriek tomu, že nič nerobí.

Všetky tieto nedokonalosti sa pokúsime v nasledujúcich verziách zdrojového textu odstrániť.

Zdrojový kód

Zdrojový kód sa nachádza na GitHub.


30.01.2017


Menu