Tartalom:
- Nyomógombbal vezérelhető ledvilágítás ki és bekapcsolása többszöri lenyomás hatására
- Fényerő fokozatosan növekszik illetve csökken be és kikapcsoláskor
- Fényerő beállítás a nyomógomb folyamatos nyomva tartásával (megjegyzi)
- Teljes forráskód a fenti funkciókkal, példaprogram
————————————————————————————–
Ezt a függvényt azért írtam, mert olyan fali kapcsolóra volt szükségem, amivel fel lehet kapcsolni a világítást, és ugyanazzal a kapcsolóval a fényerőt is lehet szabályozni. Valójában a lakásunk világítás vezérlő programját írtam meg először, ami teljesen jól működik, de már én sem látom át a működését annyira bonyolult lett. Annak forrását is megtalálod, azzal 6 szobát lehet egyszerre vezérelni, és setup funkciókkal is meg lett spékelve. Beállíthatod a fel és le fényerő szabályozási időket stb. és ezt ugyanarról a nyomógombról. Túl sokat tud, ezért azt a programot leegyszerűsítettem és jó alaposan felkommenteztem, hogy más programokban is tudjam használni. Esetleg valaki másnak is hasznos lehet jelen állapotában.
Ennek a programnak (függvénynek) a funkciói:
- rövid gombnyomással fel illetve lekapcsolja a világítást.
- Felkapcsoláskor a fényerő fokozatosan növekszik 0-tól a legutoljára beállított szintre
- Lekapcsoláskor fokozatosan csökken a fényerő minimum értékre, majd minimumon világít beállítható időre és csak ennek leteltekor kapcsol ki teljesen a fény. A nyomógomb megnyomásakor egy rövidet villan a világítás, hogy látható legyen, megindult a fényerő csökkentés.
- Ha nincs bekapcsolva a világítás, akkor kapcsoló folyamatos nyomva tartásával bekapcsolódik a világítás minimum fényerőn, és folyamatosan növekszik a fényerő. Az elengedés pillanatában érvényes fényerőn világít tovább, és ez lesz a beállított fényerő.
- Ha a világítás be van kapcsolva, a kapcsoló folyamatos nyomva tartásával a fényerő növekedni (vagy csökkenni) kezd, ha maximumra ér, akkor villan egyet, hogy lássuk elértük a maximumot. Bármikor elengedjük a kapcsolót, a fényerőt megjegyzi, és az lesz a beállított fényerő, aminél megáll a fényerő növekedés a következő felkapcsoláskor.
- A következő folyamatos nyomva tartáskor a fényerő ellentétes irányba változik, mint az előző folyamatos nyomva tartáskor. Növelés után egy rövid kapcsoló elengedés és újbóli nyomva tartás csökkenteni fog.
A minta program tartalmazza a lampa_on_off_fenyero() függvényt, ami a fentebb leírt funkciókat megcsinálja. Ha ezt használni akarod, akkor elég sok globális változót kell deklarálni a program elején, ezek részei a függvénynek. Nagy előnye a függvénynek, hogy nem tartalmaz időzítést, így nem lassítja jelentősen a loop működését. Tetszőleges egyéb programrészek helyezhetők el a loop-ban. Természetesen azok sem tartalmazhatnak időzítést, különben ez sem fog tudni működni. Annyira gyors a működés, hogy akár egyszerre több nyomógombot is ki tud szolgálni, de ekkor a függvényből többet kell csinálni különböző neveken, különböző névvel megduplikálni a változókat is, vagy lehet egy függvényt, és tömböket használni az egyes világítások változóihoz. Utóbbi esetben a függvény belsejét még egy for ciklusba kell helyezni, hogy minden egyes világításon végig menjen minden meghíváskor. Ezzel a technikával dolgozik az említett világítás vezérlésem.
/****************************************************************************
* azok a változók, paraméterek melyek közvetlenül befolyásolják a működést *
****************************************************************************/
int tartasi_ido=3000; //ennyi milisec-ig tartja minimumon a fényerőt a lekapcsolás után
int klikk_ido=400; //ennyi idő után tartjuk benyomottnak a nyomógombot, és elkezdjük a fényerő szabályozást
byte min_fenyero=10; //lekapcsoláskor a minimális fényerő értéke. Ezen a fényerőn tartjuk a lámpát teljes kikapcsolásig
int fenyero=255; //lámpa fényereje 5..255-ig. Felkapcsoláskor az ebben tárolt fényerőre kapcsolja be a lámpát.
//Nyomvatartáskor ennek az értékét változtatja a program. Azért int, hogy kihasználhassuk a
//max fényerőt (255), mert ha 255-höz adunk hozzá 1-et növeléskor, abból 0 lenne ha byte.
byte valtozasi_sebesseg=8; //ennyi milisekondumonként változtatjuk a fényerőt nyomva tartott nyomógombnál, minél kissebb,
//annál gyorsabb a változás. A teljes fényerő intervallum végig növelése 10msec esetén: 8msec*255=2 másodperc
byte fel_le_valt_sebesseg=5; //ennyi milisekondumonként változtatjuk a fényerőt fel és lekapcsoláskor, minél kisebb,
//annál gyorsabb a változás. A teljes fényerő intervallum végig növelése 10msec esetén: 5msec*255=1,27 másodperc
/****************************************************************************
* Kapcsoló és lámpa állapotok és egyéb futás közbeni változók *
****************************************************************************/
byte lamp_on=0; //lámpa bekapcsolt állapota esetén 1, kikapcsolva 0
byte sw_on=0; //kapcsoló nyomva tartás alatt értéke 1
byte nyomvatart=0; //jelzi, hogy nyomva tarjuk a nyomógombot, amig nyomjuk értéke 1
byte valtozas_fel_le=1; //a fényerő változás iránya nyomva tartáskor 1-fel 0-le
/****************************************************************************
* segéd változók, melyek a működéshez kellenek *
****************************************************************************/
byte sw_prell=0; //kapcsoló prell figyeléshez
long sw_time=0; //kapcsoló lenyomás prell figyeléshez eltelt idő az első kontaktus óta
byte sw_prev_stat=0; //kapcsoló előző ciklusbani állapotát tárolja. Kapcsoló lenyomás és elengedés érzékeléséhez kell
int fenyero_tmp=0; //a fényerő fel és le úsztatáskor az éppen aktuális fényerő értéke
long fenyero_nov_time2=0; //fényerő növelés során segédváltozó időméréshez
byte lamp_on_prev_stat=0; //lámpa előző állapota bekapcsolt állapota esetén 1, kikapcsolva 0
long fenyero_nov_time=0; //a fényerő növelésnél az időzítés segédváltozója
byte nyomvatart_prev_stat=0;//nyomva tartás végének észrevételéhez segédváltozó
long sw_tart_time=0; //kapcsoló lenyomás és elengedés közötti időmérés segéd változója. Első lenyomáskor
//indul az időmérés, és ha egy ideig nem engedjük el, akkor lenyomottnak tekintjük
//a nyomógombot, ami fényerőszabályozást eredményez
byte villan=0; //ha elérte a fényerő maximumot a fényerő növelés, akkor villan a lámpa,
//ezt engedélyezi, alapértelmezetten 1 mert alapértelmezett változási irány a növelés
byte lekapcs_eng=1; //nyomva tartott nyomógomb esetén elengedéskor nem engedjük kikapcsolni a lámpát, hiszen fényerőszabályozás volt
//ilyenkor értéke 0. Ha csak megnyomtuk a nyomógombot és lehet lekapcsolni a lámpát, akkor értéke 1.
void setup() {
pinMode(3,INPUT); //nyomógomb bemenet
digitalWrite(3,HIGH); //felhúzó ellenállás bekapcsolása a bemeneten
pinMode(11,OUTPUT); //erre kötjük a led-et
}
void loop()
{
/*
* Ez a függvény egy nyomógombot és egy PWM kimenetet kezel
* Bemenő paraméter sorrendje: bemenet, PWM kimenet
*/
lampa_on_off_fenyero(3,11);
}
void lampa_on_off_fenyero(byte bemenet, byte kimenet)
/*********************************************************************************************************************
* Ez a függvény egy nyomógomb megnyomásait figyeli és egy PWM képes kimeneten fel és lekapcsol egy led-et (lámpát). *
* Felkapcsoláskor a fényerő lassan kúszik fel egy beállított fényerőre. Lekapcsoláskor a fényerő lassan csökken *
* egy beállított minimumra, és egy beállítható ideig minimumom tartja a fényerőt, hogy ne aludjon ki egy darabig *
* a fény, ne kelljen sötétben botorkálni. Mivel a lekapcsolás lassan indul meg, és szeretnénk biztosak lenni abban, *
* hogy megtörtént, egy villanással jelzi a fényerő csökkenés megkezdését. *
* A nyomógomb hosszan nyomvatartva változtatja a fényerőt. Elengedve és újra hosszan nyomva tártva a fényerő *
* ellentétes irányba változik. Ha változtatás közben a fényerő maximumra ért, akkor a lámpa villan egy rövidet, *
* jelezve, hogy nem érdemes tovább nyomva tartani. *
* Bekapcsolás után (reset) nem lehet fényerőt szabályozni, egyszer ki és be kell kapcsolni, nem tudom a hiba okát *
*********************************************************************************************************************/
{
/*******************************************************************************************************************************
* Ez a programrész a nyomógomb prellmentesítését végzi, valamint figyeli azt, hogy mennyi ideje tartjuk nyomva a nyomógombot *
* Ha a nyomva tartási idő hosszabb mint az előre beállított konstans klikk_ido változóban megadott érték, akkor úgy tekinti *
* hogy nyomva tartjuk a nyomógombot, vagyis fényerőt akarunk szabályozni. Ha a megnyomás kezdetén még nem világított a led, *
* akkor növelni kell a fényerőt (és bekapcsolni a lámpát), de ha már világított, akkor a fel le változást is ki kell jelölni *
* a program későbbi részeiben. *
*******************************************************************************************************************************/
if (sw_on==0 and digitalRead(bemenet)==LOW and sw_prell==0) //első lenyomás érzékelése sw_prell=1 jelzi, hogy már volt egy kontaktus,
{sw_prell=1;sw_time=millis();} //és 50msec múlva már biztosan megállt a prell a kontaktuson. sw_time
//tárolja az első kontaktus időpontját az 50msec méréséhez
if (sw_on==0 and digitalRead(bemenet)==LOW and sw_prell==1 and millis()>sw_time+50) // már 50msecv óta nyomva van, most már biztos, hogy lenyomták és nem prellezik
{sw_on=1;sw_prell=0;} //sw_prell=0, mert már biztosan nem prelles
//sw_on=1, mert a kapcsoló meg lett nyomva (épp nyomva van)
if (sw_on==1 and digitalRead(bemenet)==HIGH and sw_prell==0) //első elengedés érzékelése, itt is figyelni kell,
{sw_prell=1;sw_time=millis();} //hogy prellezik-e a nyomógomb, sw_time tárolja az elengedés pillanatát, amikortól
//kezdődik a prellezés, tehát sw_prell=1
if (sw_on==1 and digitalRead(bemenet)==HIGH and sw_prell==1 and millis()>sw_time+50)//már 50msecv óta elengedte a nyomógombot, most már biztos, hogy nincs prell
{sw_on=0;sw_prell=0;} //sw_on=0 jelzi, hogy nincs nyomva nyomógomb, sw_prell=0 jelzi, hogy már nincs prell
if (sw_on==1 and sw_prev_stat==0) //a kapcsoló előző állapota 0, és most megnyomták, tehát felfutó él érkezett
{sw_tart_time=millis();} //sw_tart_time tárolja a benyomás időpontját, és innen figyeljük, hogy 500msec-en
//elengedi-e a nyomógombot.
if (sw_on==0 and sw_prev_stat==1 and nyomvatart==0) //nem nyomva tartott állapotban engedtük el a nyomógombot (lefutó él)
{ //lehet a lámpát fel vagy lekapcsolni
if (lamp_on==0) {lamp_on=1;} //lámpa nem volt bekapcsolva, lámpa bekapcsolása,
else {lamp_on=0;} //lámpa fel volt kapcsolva, lámpa lekapcsol
lekapcs_eng=1; //jelezzük a későbbi programrészeknek, hogy lekapcsolható a lámpa
}
if (sw_on==0 and sw_prev_stat==1 and nyomvatart==1) //nyomva tartott állapotban engedtük el a nxomógombot (lefutó él)
{nyomvatart=0;lekapcs_eng=0;} //lámpa felkapcsolva marad beállított fényerőn, mert lekapcs_eng=0
//a következő ciklusban tudnunk kell a nyomógomb előző állapotát,
//hogy detektálni tudjuk a nyomógomb bekapcsolását, és ez csak egyszer
//következzen be. Ehhez használjuk a sw_prev_stat változót.
if (sw_on==1 and sw_prev_stat==1 and millis()>sw_tart_time+klikk_ido) //benyomva a nyomógomb és telik az idő. Ha klikk_ido eltelt, akkor nyomvatartottnak
{ //vesszük, ami fényerőszabályozást eredményez
nyomvatart=1; //a nyomvatart változó jelzi, hogy nyomva van a nyomógomb
if (lamp_on==0) //ha még nincs bekapcsolva a lámpa, akkor bekapcsoljuk (nyomvatartással is bekapcsolható
{lamp_on=1;fenyero=min_fenyero;valtozas_fel_le=1;villan=1; //ha nyomva tartassal kapcsoltuk fel, akkor minimum fényerőről indul a szabályozás
fenyero_nov_time2=millis();lekapcs_eng=0;} //valtozas_fel_le=1 jelzi, hogy növelni kell a fényerőt, engedélyezük a villanást is max fényerőnél
} //fenyero_nov_time2 megjegyzi a növelés elkezdésének időpontját
sw_prev_stat=sw_on; //megjegyezzük a nyomógomb előző állapotát, hogy a következő ciklusban észre vegyük a változást
/******************************************************************************************************
* Ezek a programrészek a nyomvatortott nyomógomb esetén növelik vagy csökkentik a fényerőt, valamint *
* nyomvatartás után elengedett nyomógomb esetén váltják a csökkentés vagy növelés irányát *
******************************************************************************************************/
if (fenyero<min_fenyero+1) //fényerő minimumra értünk.
{fenyero=min_fenyero+2;} //Azért állunk meg előtte egy értékkel, mert így kikapcsoláskor lesz segédfény
if (fenyero>255) //fényerő maximumhoz értünk
{fenyero=255;} //255 fölé nem nőhet a fényerő
if (valtozas_fel_le==1 and nyomvatart==1 and millis()>fenyero_nov_time+valtozasi_sebesseg)//nyomvatartjuk a gombot és növeljuk a fényerőt maximumig
{
if (fenyero<255){fenyero=fenyero+1;} //ha még kisebb a fényerő mint 255, akkor növelünk
fenyero_nov_time=millis(); //a fenyerő növelés következő lépéséhez megjegyezzük a pillanatnyi időpontot
}
if (fenyero_tmp==255 and nyomvatart==1 and villan==1) //nyomva tartjuk a kapcsolót és elértük a maximumot megvillantjuk
{analogWrite(kimenet,128);fenyero_nov_time2=millis();villan=0;} //a lámpát rövid fényerő csökkentéssel, de a további villanásokat tiltjuk
if (fenyero_tmp==255 and nyomvatart==1 and millis()>fenyero_nov_time2+200) //200msec múlva visszakapcsoljuk a fényt maximumra (nyomvatartja a
{analogWrite(kimenet,255);} //kapcsolót és elértük a maximumot, villanás vége, újra max fényerő)
if (valtozas_fel_le==0 and nyomvatart==1 and millis()>fenyero_nov_time+valtozasi_sebesseg) // nyomva tartjuk a gombot és csökkentjük a fényerőt
{fenyero=fenyero-1;fenyero_nov_time=millis();}
if (nyomvatart==0 and nyomvatart_prev_stat==1) //nyomva tartás után elengedtük a nyomógombot
{
if (valtozas_fel_le==1) {valtozas_fel_le=0;} //ha eddig "fel" irány volt, akkor most "le" jön
else {valtozas_fel_le=1;villan=1;} //ha eddig "le" irány volt, akkor most "fel" jön. Engedélyezzük a villanást is
} //arra az esetre, ha a következő növeléskor elérte a maximumot a fényerő
nyomvatart_prev_stat=nyomvatart; //Ha a nyomógombot nyomva tartottuk, akkor a következő ciklusban
//tudnunk kell az előző ciklus állapotát, hogy felfedezzük a változást, mert következő
//nyomvatartáskor meg kell változtatni a fényerő növelés vagy csökkentés irányát
/******************************************************************************************************************************
* Ez a programrész figyeli a lamp_on változó értékét. Ha 1, vagyis bekapcsoltuk a lámpát, akkor a fényerőt mindig beállítja *
* a fenyero nevű változó értékéhez, de ezt lassan csinálj azzal, hogy valójában egy fenyerp_tmp nevű változó határozza meg *
* a fényerőt, és ennek értékét fokozatosan növeli vagy csökkenti fenyero változó értékére. *
******************************************************************************************************************************/
if (lamp_on==1 and millis()>fenyero_nov_time2+fel_le_valt_sebesseg) //Ha felkapcsoltuk a lámpát akkor a fenyero változóig növeljuk a fényerőt,
//ehhez minden ciklusban megnézzük eltel-e már fel_le_valt_sebesseg változóban
//megadott konstans idő. Ha igen, akkor megnézzük, hogy fenyero_tmp és fenyero
//változók között van-e különbség. Ha igen, akkor változtatjuk fenyero_tmp értékét.
//Így a fenyero_tmp változó csak követi fenyero változó érteket, a fel_le_valt_sebesseg
//változóban beállított sebességgel. A nyomógombbal fenyero változó értékét változtatjuk,
//illetve bekapcsoláskor ez 255, kikapcsoláskor 0. Ezért kúszik fel és le a fényerő.
{
if (fenyero_tmp>=255) {fenyero_tmp=255;} //fenyero_tmp nem nőhet 255 fölé, mert az a max. fényerő, de ez a programban máshol előfordulhat, ezért kell figyelni
if (fenyero_tmp<fenyero) //még nem értük el a szükséges fényerőt a fenyero változóban meghatározott fényerőt
{fenyero_tmp=fenyero_tmp+1; //növeljük fenyero_tmp értékét
fenyero_nov_time2=millis(); //tároljuk fenyero_nov_time2-ben az aktuálisidőt, mert ehhez hasonlít következő ciklusban
analogWrite(kimenet,fenyero_tmp);} //beállítjuk a fényerőt fenyero_tmp értékére
if (fenyero_tmp>fenyero) //ha a fényerő nagyobb mint a beállított fényerő, akkor elkezdjük csökkenteni
{fenyero_tmp=fenyero_tmp-1; //csökkentjük fenyero_tmp értékét, mert a fenyero változóban megszabott fenyerőnél nagyobb afényerő
fenyero_nov_time2=millis(); //tároljuk fenyero_nov_time2-ben az aktuálisidőt, mert ehhez hasonlít következő ciklusban
analogWrite(kimenet,fenyero_tmp);} //beállítjuk a fényerőt fenyero_tmp értékére
}
/******************************************************************************************************************************
* Ez a programrész figyeli a lamp_on változó értékét. Ha 0, vagyis lekapcsoltuk a lámpát, akkor a fényerőt 0-ra állítja *
* de ezt lassan csinálj azzal, hogy valójában egy fenyero_tmp nevű változó értékét csökkenti időnként. Ha egy beállított *
* minimumra ért a fenyero_tmp értéke, akkor egy időre megáll a csökkentéssel (tartasi_ido változó), és csak aztán kapcsolja *
* le teljesen a fényerőt. Amikor érzékeljük, hogy lekapcsoltuk a lámpát, egy rövid időre lecsökkentjük a fényerőt 0-ra, *
1. * És ezzel jelezzük, hogy megindult a lekapcsolási folyamat *
******************************************************************************************************************************/
if (lamp_on==0 and millis()>fenyero_nov_time2+fel_le_valt_sebesseg and lekapcs_eng==1) //lekapcsoltuk a lámpát, csökkenteni kell a fénmyerőt 0-ig
{ //ebbe minden fel_le_valt_sebesseg értékével meghatározott időnként bele megy
if (fenyero_tmp==min_fenyero and millis()>fenyero_nov_time2+tartasi_ido) //Ha már minimum fényerőn van, akkor még tartasi_ido értékig tartja a min fényerőt
{analogWrite(kimenet,0);fenyero_tmp=0;}
if (fenyero_tmp>min_fenyero) //még nem értük a el a minimum fényerőt
{fenyero_tmp=fenyero_tmp-1;fenyero_nov_time2=millis();analogWrite(kimenet,fenyero_tmp);} //csökkentjük a fényerőt, megjegyezzük a pillanatnyi időt a köv. csökkentéshez
}
if (lamp_on==0 and lamp_on_prev_stat==1) //lámpa lekapcsoláskor csökkenteni fogjuk a fenyerőt egy rövid időre,
{analogWrite(kimenet,0);fenyero_nov_time2=millis()+70;} //hogy lássuk, elkezdődött a lekapcsolás
lamp_on_prev_stat=lamp_on; //led állapotának tárolása a változás megállapításához
}