Fényerő szabályozó kapcsoló

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
}

Mennyire volt hasznos amit olvastál? Értékelés után szövegesen is leírhatod megjegyzéseidet és véleményedet!

Kattints egy csillagra az értékeléshez!

Szövegesen is leírhatod véleményedet! Ha kérdésed van, ne felejtsd el megadni az email címedet!