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.
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.
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.
Všetky tieto nedokonalosti sa pokúsime v nasledujúcich verziách zdrojového textu odstrániť.
Zdrojový kód sa nachádza na GitHub.
30.01.2017