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égigmenjen 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 }