programovatelný voltmetr

Wiring, C++, C, Java, ...
Pravidla fóra
Toto subfórum slouží k řešení obecných otázek kolem programování (konstrukce, knihovny, alokace paměti, ...)
Odpovědět
MVE + FVE
Příspěvky: 2
Registrován: 02 dub 2023, 10:29
Reputation: 0

programovatelný voltmetr

Příspěvek od MVE + FVE » 04 dub 2023, 17:47

Zdravím ve spolek,
Prosím o radu jak postupovat dále při programováni. Jedná se o voltmetr který umí při nastaveném napětí zapnout spotřebič a naopak při
nastaveném nižším napětí vypnout spotřebič.
V případě 12V aku by to třeba bylo při 12,5V vypni a při 14,4V zapni. Výstup Arduina ovládá relátko.
Naprogramovat V metr se podařilo ovšem dál jsem se nedostal. Nevím jak udělat aby Arduino četlo správně nastavené hodnoty napětí.
Po dvou dnech jsem si uvědomil, že Arduino neměří třeba 13,8V ale napětí upravené přes dělič. Ale přidáni vzorce do programu taká nepomohlo.
A aby šly hodnoty napětí nastavovat tlačítky do toho jsem se zatím nepouštěl.
Na obrázku, pokud se vložil správně je jak by se mi líbilo mít to udělané.
Arduino V metr.pdf
obr1.
(71.97 KiB) Staženo 59 x
Ukázka programu co jsem si představoval, že by mohlo fungovat:

Kód: Vybrat vše

#include <Wire.h> //knihovna displeje přes I2C
#include <LiquidCrystal_I2C.h> //knihovna displeje přes I2C

float volt, voltage; //proměná desetiného čísla
float val; // moje myšlenka - vytvoření desetiné proměné pro uchování hodnot
LiquidCrystal_I2C lcd(0x27, 16, 2); //adresa a typ disp

void setup() {
lcd.begin(); // aktivace disp
lcd.print("U BAT ="); // tiskni na disp U BAT
pinMode(12,OUTPUT); // pin 12 výstup pro relé

}

void loop() {
  volt= analogRead(A0); // čtení vstupu A0
  voltage =volt* (5.0 * 5 / 1023); // úprava rozsahu měřeného napětí na max 25V
  lcd.setCursor(9, 0); // kurzor na 1 řádek deváté pole
  lcd.print(voltage); //tisknutí čísla napětí
  lcd.print("V");   
val = analogRead(voltage)*(5.0 * 5 / 1023); // moje myšlenka - čti napětí s upraveným rozsahem
 if(val > 14.22){ // moje myšlenka - a pokud je napětí větší než 14,22 
   digitalWrite(12,HIGH); // zapni výstup
   delay(1000); // počkej 1s a zapni výstup
 }

 if(val < 12.55){ // moje myšlenka - pokud je napětí menší jak 12,55
digitalWrite(12,LOW); // vypni výstup
delay(2000); // počkej 2s vypni výstup
}
}


Prosím můžete mi poradit jak postupovat dál. Je to vlastě jako termostat akorát neměří teplotu, ale napětí.
Děkuji

Uživatelský avatar
kiRRow
Příspěvky: 1152
Registrován: 07 kvě 2019, 07:03
Reputation: 0
Bydliště: Opava

Re: programovatelný voltmetr

Příspěvek od kiRRow » 05 dub 2023, 13:48

tady máš už vypočteno napětí v proměnné voltage

Kód: Vybrat vše

  volt= analogRead(A0); // čtení vstupu A0
  voltage =volt* (5.0 * 5 / 1023); // úprava rozsahu měřeného napětí na max 25V
takže toto je naprostý nesmysl, nečteč pin, ale vypočtené napětí ?

Kód: Vybrat vše

val = analogRead(voltage)*(5.0 * 5 / 1023); // moje myšlenka - čti napětí s upraveným rozsahem
mno a pak už jen

Kód: Vybrat vše

 if(voltage > 14.22){ // moje myšlenka - a pokud je napětí větší než 14,22 
   digitalWrite(12,HIGH); // zapni výstup
   delay(1000); // počkej 1s a zapni výstup - btw napsal jsi zapni výstup a pak počkej 1s
 }
  if(voltage< 12.55){ // moje myšlenka - pokud je napětí menší jak 12,55
digitalWrite(12,LOW); // vypni výstup
delay(2000); // počkej 2s vypni výstup - to samé ... vypni výstup a čekej 2s
}
a digitalWrite a delay maj prohozenou pozici v programu pokud chceš aby to počkalo a pak něco udělalo

AstroMiK
Příspěvky: 592
Registrován: 08 pro 2017, 19:05
Reputation: 0

Re: programovatelný voltmetr

Příspěvek od AstroMiK » 05 dub 2023, 18:10

Přikládám porgram.

Displej jsem neřešil - tam by snad neměl být žádný problém.
Jeho obsluhu si vlož někam místo toho bloku, kde vypisuji debugovací hodnoty do sériové linky.


Tlačítka jsou trochu nedodělaná (1 klik je přidání nebo ubrání jedničky).
Takže při nutnosti větší změny se uživatel může klikáním unavit :-).
Neměl by být problém tam dopnit třeba autorepeat při delším držení stisknutého tlačítka.

Nastavené hodnoty úrovní se ukládají do EEPROM, takže při vypnutí napájení se nezapomenou.

Kód: Vybrat vše

// nastaveni pinu
#define pin_napeti              A0
#define pin_rele                12

#define pin_tl_rozepnout_plus   11
#define pin_tl_rozepnout_minus  10
#define pin_tl_sepnout_plus      9
#define pin_tl_sepnout_minus     8
#define pin_tl_trvale            7


// nastaveni casovacu
#define casovac_sepnuti     1000              // cas v ms pred sepnutim rele
#define casovac_rozepnuti   2000              // cas v ms pred rozepnutim rele


#define SEPNUTO              HIGH             // LOW  = tlacitka spinaji proti GND a jsou pripojene vnitrni Pull-Upy
                                              // HIGH = tlacitka spinaji proti Vcc a jsou vnejsimi odpory stazene ke GND
#include <EEPROM.h>

float kalibrace = 0.0244;                     // upravit podle skutecne prevodni konstanta delice pri plnem rozsahu (25[V] / 1023)


int spinaci_uroven;                           // spinaci uroven v rozsahu 0 az 1023
int rozpinaci_uroven;                         // rozpinaci uroven v rozsahu 0 az 1023
int napeti;                                   // aktualni hodnota napeti (v cislech z A/D prevodniku) na pinu A0 v rozsahu 0 az 1023
float volty;                                  //       pro prepocet na volty je nutne vynasobit hodnotu promenne 'napeti' kalibracni konstantou

boolean stav_rele;                            // nepovinne - jen kvuli vypisu

unsigned long znacka_startu_casovace;         // sem se uklada aktualni cas pri prekroceni nebo podlezeni urovni - start casovace

byte casovani;                                // 0 ... zadne casovani nebezi (napeti je v pasmu 1 mezi nastavenymi urovnemi)
                                              // 1 ... spustilo se casovani pred rozepnutim
                                              // 2 ... spustilo se casovani pred sepnutim

byte pasmo;                                   // 0 ... napeti je pod nastavenou rozpinaci urovni
                                              // 1 ... napeti je mezi nastavenymi urovnemi
                                              // 2 ... napeti je nad nastavenou spinaci urovni


boolean   byla_spinaci_zmena;                 // do EEPROM se nove nastavene hodnoty ukladaji jen pri zmene urovne
boolean   byla_rozpinaci_zmena;               // do EEPROM se nove nastavene hodnoty ukladaji jen pri zmene urovne
unsigned long casovac_EEPROM;                 // do EEPROM se uklada az se zpozdenim (po nekolika sekundach necinnosti)


//=============================================================================================================
void setup(void)
  {
    Serial.begin(9600);

    if (SEPNUTO == LOW)                                               // zpusob zapojeni tlacitek
      {
        pinMode(pin_tl_trvale          ,INPUT_PULLUP);                // vnitrni Pull-Up spina se proti GND
        pinMode(pin_tl_sepnout_plus    ,INPUT_PULLUP);                // vnitrni Pull-Up spina se proti GND
        pinMode(pin_tl_sepnout_minus   ,INPUT_PULLUP);                // vnitrni Pull-Up spina se proti GND
        pinMode(pin_tl_rozepnout_plus  ,INPUT_PULLUP);                // vnitrni Pull-Up spina se proti GND
        pinMode(pin_tl_rozepnout_minus ,INPUT_PULLUP);                // vnitrni Pull-Up spina se proti GND
      }
    else
      {
        pinMode(pin_tl_trvale          ,INPUT);                       // zvenku pritazeno odpory k zemi, spina se proti Vcc
        pinMode(pin_tl_sepnout_plus    ,INPUT);                       // zvenku pritazeno odpory k zemi, spina se proti Vcc
        pinMode(pin_tl_sepnout_minus   ,INPUT);                       // zvenku pritazeno odpory k zemi, spina se proti Vcc    
        pinMode(pin_tl_rozepnout_plus  ,INPUT);                       // zvenku pritazeno odpory k zemi, spina se proti Vcc
        pinMode(pin_tl_rozepnout_minus ,INPUT);                       // zvenku pritazeno odpory k zemi, spina se proti Vcc    
      }
    
    pinMode(pin_rele ,OUTPUT);

    rozpinaci_uroven = (EEPROM.read(0) * 256) + EEPROM.read(1);       // na adresach 0 a 1 v EEPROM je ulozena rozpinaci uroven (MSB, LSB)
    spinaci_uroven   = (EEPROM.read(2) * 256) + EEPROM.read(3);       // na adresach 2 a 3 v EEPROM je ulozena spinaci uroven (MSB, LSB)

    //-----------------------
    // Tenhle blok se vyuzije jen pri prvnim spusteni.
    // Kdyz je v EEPROM nejaky nesmysl, nastavi se do EEPROM defaultni hodnoty obou urovni (12,5V a 14,4V).
    if (spinaci_uroven   > 1023  )         nastav_defaulty();
    if (rozpinaci_uroven > 1023  )         nastav_defaulty();
    if (rozpinaci_uroven > spinaci_uroven) nastav_defaulty();
    //-----------------------
        
  }


//=============================================================================================================
void loop(void)
  {
    napeti = analogRead(pin_napeti);                                                // napeti se cte jako hodnota v rozsahu 0 az 1023
    volty = kalibrace * napeti;                                                     // prepocet z digitalnich hodnot (0 az 1023) na napeti (0 az 25V)


    // -------------------  vyhodnoceni pasem --------------------------------
    if (napeti <  rozpinaci_uroven )                                pasmo = 0;      // napeti je pod rozpinaci urovni
    if (napeti >= rozpinaci_uroven and napeti <= spinaci_uroven)    pasmo = 1;      // napeti je mezi urovnemi
    if (napeti >  spinaci_uroven )                                  pasmo = 2;      // napeti je nad spinaci urovni


    if (digitalRead(pin_tl_trvale) == SEPNUTO)                      pasmo = 2;      // pri sepnutem spinaci pro "trvale sepnuti" se skutecne napeti igoruje 
                                                                                    //   a pasmo se nastavi natvrdo jakoby bylo napeti nad spinaci urovni


    // ------------------- zapinani casovacu pri prekroceni / podlezeni urovni -------------------
    if (pasmo == 0 and (casovani == 0 or casovani == 2))                            // napeti prave pokleslo pod rozpinaci uroven (a casovani odpoctu zatim nebezi)
      {
        znacka_startu_casovace = millis();                                          // aktualni cas se zaznamena
        casovani = 1;
      }

    if (pasmo == 2 and (casovani == 0 or casovani == 1) )                           // napeti prave prekrocilo spinaci uroven (a casovani odpoctu zatim nebezi)
      {
        znacka_startu_casovace = millis();                                          // aktualni cas se zaznamena
        casovani = 2;
      }

    if (pasmo == 1)                                                                 // kdyz je napeti mezi nastavenymi urovnemi, casovani se zastavuje
      {
        casovani = 0;
      }



    // ----------------  ovladani rele po dobehnuti casovace ----------------------
    if ((millis() - znacka_startu_casovace) > casovac_sepnuti and casovani == 2)    // odpocet sepnuti dobehnul do konce, rele se sepne a casovac se vypne
      {
        digitalWrite(pin_rele, HIGH);
        stav_rele = true;                                                           // nepovinne - jen kvuli vypisu
      }

    if ((millis() - znacka_startu_casovace) > casovac_rozepnuti and casovani == 1)  // odpocet rozepnuti dobehnul do konce, rele se rozepne a casovac se vypne
      {
        digitalWrite(pin_rele, LOW);
        stav_rele = false;                                                          // nepovinne - jen kvuli vypisu
      }




    // ----------------  vyhodnoceni tlacitek ----------------------
    //  Tohle by chtelo jeste vylepsit - treba autorepeatem pri dlouhem drzeni tlacitek
    if (digitalRead(pin_tl_sepnout_plus) == SEPNUTO)                                // tacitko "zapinani plus" stisknuto
      {
        spinaci_uroven ++;                                                          // spinaci uroven se o 1 zvysi
        byla_spinaci_zmena = true;                                                  // aby se do EEPROM neukladaly hodnoty pri kazdem pruchodu, ale jen pri pri zmene
        casovac_EEPROM = millis();                                                  // do EEPROM se bude zmena ukladat jeste po urcitem obdobi necinnosti 
        if (spinaci_uroven > 1023)  spinaci_uroven = 1023;                          // zarazka na maximalni hodnote, kterou nelze prelezt
        delay(50);                                                                  // odruseni zakmitu pri stisku
        while (digitalRead(pin_tl_sepnout_plus) == SEPNUTO)  ;                      // cekani na uvolneni tlacitka
        delay(50);                                                                  // odruseni zakmitu pri uvolneni
      }

    if (digitalRead(pin_tl_sepnout_minus) == SEPNUTO)                               // tacitko "zapinani minus" stisknuto
      {
        spinaci_uroven --;                                                          // spinaci uroven se o 1 snizi
        byla_spinaci_zmena = true;                                                  // aby se do EEPROM neukladaly hodnoty pri kazdem pruchodu, ale jen pri pri zmene
        casovac_EEPROM = millis();                                                  // do EEPROM se bude zmena ukladat jeste po urcitem obdobi necinnosti 
        if (spinaci_uroven < rozpinaci_uroven)  spinaci_uroven = rozpinaci_uroven;  // zarazka na minimalni hodnote
        delay(50);                                                                  // odruseni zakmitu pri stisku
        while (digitalRead(pin_tl_sepnout_minus) == SEPNUTO)  ;                     // cekani na uvolneni tlacitka
        delay(50);                                                                  // odruseni zakmitu pri uvolneni
      }

    if (digitalRead(pin_tl_rozepnout_plus) == SEPNUTO)                              // tacitko "rozepinani plus" stisknuto
      {
        rozpinaci_uroven ++;                                                        // spinaci uroven se o 1 zvysi
        byla_rozpinaci_zmena = true;                                                // aby se do EEPROM neukladaly hodnoty pri kazdem pruchodu, ale jen pri pri zmene
        casovac_EEPROM = millis();                                                  // do EEPROM se bude zmena ukladat jeste po urcitem obdobi necinnosti 
        if (rozpinaci_uroven > spinaci_uroven)  rozpinaci_uroven = spinaci_uroven;  // zarazka na maximalni hodnote, kterou nelze prelezt
        delay(50);                                                                  // odruseni zakmitu pri stisku
        while (digitalRead(pin_tl_rozepnout_plus) == SEPNUTO)  ;                    // cekani na uvolneni tlacitka
        delay(50);                                                                  // odruseni zakmitu pri uvolneni
      }

    if (digitalRead(pin_tl_rozepnout_minus) == SEPNUTO)                             // tacitko "rozepinani minus" stisknuto
      {
        rozpinaci_uroven --;                                                        // rozepinaci uroven se o 1 snizi
        byla_rozpinaci_zmena = true;                                                // aby se do EEPROM neukladaly hodnoty pri kazdem pruchodu, ale jen pri pri zmene
        casovac_EEPROM = millis();                                                  // do EEPROM se bude zmena ukladat jeste po urcitem obdobi necinnosti 
        if (rozpinaci_uroven < 0)  rozpinaci_uroven = 0;                            // zarazka na minimalni hodnote (nulu nelze podlezt)
        delay(50);                                                                  // odruseni zakmitu pri stisku
        while (digitalRead(pin_tl_rozepnout_minus) == SEPNUTO)  ;                   // cekani na uvolneni tlacitka
        delay(50);                                                                  // odruseni zakmitu pri uvolneni
      }



   //----------------------------
   // ukladani nastavenych hodnot do EEPROM - ale jen v pripade, ze doslo k manipulaci s tlacitky a ted uz se nekolik (10) sekund na tlacitka nesahlo
   if (byla_rozpinaci_zmena == true and (millis() - casovac_EEPROM) > 10000)        // casovac necinnosti po nastaveni nove rozpinaci urovne vyprsel
      {
        byla_rozpinaci_zmena = false;                                               // priste uz se ukladat nebude
        EEPROM.write(0, rozpinaci_uroven/256);                                      // ted se ale zapis do EEPROM provede
        EEPROM.write(1, rozpinaci_uroven%256);
        Serial.println("EEPROM: zapis rozpinaci urovne");
      }
   
   if (byla_spinaci_zmena == true and (millis() - casovac_EEPROM) > 10000)          // casovac necinnosti po nastaveni nove spinaci urovne vyprsel
      {
        byla_spinaci_zmena = false;                                                 // priste uz se ukladat nebude
        EEPROM.write(2, spinaci_uroven/256);                                        // ted se ale zapis do EEPROM provede
        EEPROM.write(3, spinaci_uroven%256);
        Serial.println("EEPROM: zapis spinaci urovne");
      }
   //----------------------------


   //----------------------------
   // tady zobrazovat hodnoty na displeji 

      Serial.print("Vstup A0:");
      Serial.print(napeti);
      Serial.print(" ( = ");
      Serial.print(volty , 3);
      Serial.print(" V)   pasmo:");
      Serial.print(pasmo);
      Serial.print("   casovani:");
      Serial.print(casovani); 
      Serial.print("   rozpinaci:");
      Serial.print(rozpinaci_uroven);
      Serial.print("  ( = ");
      Serial.print(rozpinaci_uroven * kalibrace , 3);              
      Serial.print(" V)     spinaci:");
      Serial.print(spinaci_uroven); 
      Serial.print("  ( = ");
      Serial.print(spinaci_uroven * kalibrace , 3);
      Serial.print(" V)     RELE:");
      Serial.println(stav_rele);
      
      delay(100);                                                            // tohle je jen aby se vypis dal pohodlne cist. Pri pouziti displeje zrusit!
   //----------------------------

    
  }  // konec hlavni smycky

//=============================================================================================================


// Tento podprogram probehne jen 1x pri prvnim spusteni programu, kdyz jsou v EEPROM nesmyslne hodnoty
void nastav_defaulty(void)
  {
    Serial.println("V EEPROM jsou nesmysly, nastavuji defaultni meze 200 a 800");
    rozpinaci_uroven = 512;                                                  //  512 = 12.5V / kalibracni konstanta
    spinaci_uroven = 590;                                                    //  590 = 14.4V / kalibracni konstanta
    EEPROM.write(0, rozpinaci_uroven/256);
    EEPROM.write(1, rozpinaci_uroven%256);
    EEPROM.write(2, spinaci_uroven/256);
    EEPROM.write(3, spinaci_uroven%256);    
  }

terminal.gif

MVE + FVE
Příspěvky: 2
Registrován: 02 dub 2023, 10:29
Reputation: 0

Re: programovatelný voltmetr

Příspěvek od MVE + FVE » 05 dub 2023, 19:08

Dík za odpovědi a detailní popis v programu.
Mohlo mě také napadnout nejdřív počkej a pak něco udělej.
Uložení nastavených hodnot do EEPROM je dobrý nápad hned mě to také nenapadlo.
V programování jsem začátečník tohle bych fakt nedal.
Naštuduji, vyzkouším a ozvu se.
Děkuji

AstroMiK
Příspěvky: 592
Registrován: 08 pro 2017, 19:05
Reputation: 0

Re: programovatelný voltmetr

Příspěvek od AstroMiK » 06 dub 2023, 20:47

Doplnil jsem tam ten autorepeat a opravil jednu dost zásadní chybu:
Když byla při prvním spuštění programu v EEPROM uložena hodnota větší než 32767 (například 0xFFFF), převedla se tato hodnota kvůli "int" rozsahu proměnných jako záporné číslo. Takovýhle stav ale musí program vyhodnotit jako chybu a nahrát defaultní hodnoty.

Kód: Vybrat vše



// Verze 2
// - oprava prvniho zapnuti (kdyz je v EEPROM pri zapnuti ulozena hodnota vyssi nez 32767, nacte se to jako zaporna hodnota.
//      Tento stav musi byt vyhodnocen jako chyba nasledovana ulozenim defaultnich hodnot do EEPROM)
// - doplneni autorepeatu


//-------------------------------------------------------------------------
// nastaveni pinu
#define pin_napeti              A0
#define pin_rele                12

#define pin_tl_rozepnout_plus   11
#define pin_tl_rozepnout_minus  10
#define pin_tl_sepnout_plus      9
#define pin_tl_sepnout_minus     8
#define pin_tl_trvale            7

// nastaveni casovacu
#define casovac_sepnuti     1000              // cas v ms pred sepnutim rele
#define casovac_rozepnuti   2000              // cas v ms pred rozepnutim rele


#define SEPNUTO              HIGH             // LOW  = tlacitka spinaji proti GND a jsou pripojene vnitrni Pull-Upy
                                              // HIGH = tlacitka spinaji proti Vcc a jsou vnejsimi odpory stazene ke GND
#include <EEPROM.h>

float kalibrace = 0.0244;                     // upravit podle skutecne prevodni konstanty delice - pri plnem rozsahu (25[V] / 1023)


int spinaci_uroven;                           // spinaci uroven v rozsahu 0 az 1023
int rozpinaci_uroven;                         // rozpinaci uroven v rozsahu 0 az 1023
int napeti;                                   // aktualni hodnota napeti (v cislech z A/D prevodniku) na pinu A0 v rozsahu 0 az 1023
float volty;                                  //       pro prepocet na volty je nutne vynasobit hodnotu promenne 'napeti' kalibracni konstantou

boolean stav_rele;                            // nepovinne - jen kvuli vypisu

unsigned long znacka_startu_casovace;         // sem se uklada aktualni cas pri prekroceni nebo podlezeni urovni - start casovace

byte casovani;                                // 0 ... zadne casovani nebezi (napeti je v pasmu 1 mezi nastavenymi urovnemi)
                                              // 1 ... spustilo se casovani pred rozepnutim
                                              // 2 ... spustilo se casovani pred sepnutim

byte pasmo;                                   // 0 ... napeti je pod nastavenou rozpinaci urovni
                                              // 1 ... napeti je mezi nastavenymi urovnemi
                                              // 2 ... napeti je nad nastavenou spinaci urovni


boolean   byla_spinaci_zmena;                 // do EEPROM se nove nastavene hodnoty ukladaji jen pri zmene urovne
boolean   byla_rozpinaci_zmena;               // do EEPROM se nove nastavene hodnoty ukladaji jen pri zmene urovne
unsigned long casovac_EEPROM;                 // do EEPROM se uklda az se zpozdenim (po nekolika sekundach necinnosti)


boolean stav_autorepeat = false;              // dlouhy stisk tlacitka umoznuje automaticke pridavani / ubirani hodnoty
unsigned long autorepeat_start;               // casu, kdy ma dojit k automatickemu uvolneni dlouze stisknuteho tlacitka
#define prodleva_autorepeat        200        // pauza mezi opakovanim pri autorepeatu v ms (200 znamena opakovani asi 5x za sekundu)
#define dlouhy_stisk              2000        // po jak dlouhem stisku tlacitek se spousti autorepeat v ms

//=============================================================================================================
void setup(void)
  {
    Serial.begin(9600);

    if (SEPNUTO == LOW)                                               // zpusob zapojeni tlacitek
      {
        pinMode(pin_tl_trvale          ,INPUT_PULLUP);                // vnitrni Pull-Up spina se proti GND
        pinMode(pin_tl_sepnout_plus    ,INPUT_PULLUP);                // vnitrni Pull-Up spina se proti GND
        pinMode(pin_tl_sepnout_minus   ,INPUT_PULLUP);                // vnitrni Pull-Up spina se proti GND
        pinMode(pin_tl_rozepnout_plus  ,INPUT_PULLUP);                // vnitrni Pull-Up spina se proti GND
        pinMode(pin_tl_rozepnout_minus ,INPUT_PULLUP);                // vnitrni Pull-Up spina se proti GND
      }
    else
      {
        pinMode(pin_tl_trvale          ,INPUT);                       // zvenku pritazeno odpory k zemi, spina se proti Vcc
        pinMode(pin_tl_sepnout_plus    ,INPUT);                       // zvenku pritazeno odpory k zemi, spina se proti Vcc
        pinMode(pin_tl_sepnout_minus   ,INPUT);                       // zvenku pritazeno odpory k zemi, spina se proti Vcc    
        pinMode(pin_tl_rozepnout_plus  ,INPUT);                       // zvenku pritazeno odpory k zemi, spina se proti Vcc
        pinMode(pin_tl_rozepnout_minus ,INPUT);                       // zvenku pritazeno odpory k zemi, spina se proti Vcc    
      }
    
    pinMode(pin_rele ,OUTPUT);

    rozpinaci_uroven = (EEPROM.read(0) * 256) + EEPROM.read(1);       // na adresach 0 a 1 v EEPROM je ulozena rozpinaci uroven (MSB, LSB)
    spinaci_uroven   = (EEPROM.read(2) * 256) + EEPROM.read(3);       // na adresach 2 a 3 v EEPROM je ulozena spinaci uroven (MSB, LSB)

    //-----------------------
    // Tenhle blok se vyuzije jen pri prvnim spusteni.
    // Kdyz je v EEPROM nejaky nesmysl, nastavi se do EEPROM defaultni hodnoty obou urovni (12,5V a 14,4V).
    if (spinaci_uroven   > 1023  )         nastav_defaulty();
    if (rozpinaci_uroven > 1023  )         nastav_defaulty();
    if (spinaci_uroven   < 0     )         nastav_defaulty();                       // kvuli "int" rozsahu promennych se mohou z EEPROM cist i zaporna cisla (to je taky nesmysl)
    if (rozpinaci_uroven < 0     )         nastav_defaulty();                       // kvuli "int" rozsahu promennych se mohou z EEPROM cist i zaporna cisla (to je taky nesmysl)
    if (rozpinaci_uroven > spinaci_uroven) nastav_defaulty();
    //-----------------------
        
  }


//=============================================================================================================
void loop(void)
  {
    napeti = analogRead(pin_napeti);                                                // napeti se cte jako hodnota v rozsahu 0 az 1023
    volty = kalibrace * napeti;                                                     // prepocet z digitalnich hodnot (0 az 1023) na napeti (0 az 25V)


    // -------------------  vyhodnoceni pasem --------------------------------
    if (napeti <  rozpinaci_uroven )                                pasmo = 0;      // napeti je pod rozpinaci urovni
    if (napeti >= rozpinaci_uroven and napeti <= spinaci_uroven)    pasmo = 1;      // napeti je mezi urovnemi
    if (napeti >  spinaci_uroven )                                  pasmo = 2;      // napeti je nad spinaci urovni


    if (digitalRead(pin_tl_trvale) == SEPNUTO)                      pasmo = 2;      // pri sepnutem spinaci pro "trvale sepnuti" se skutecne napeti igoruje 
                                                                                    //   a pasmo se nastavi natvrdo jakoby bylo napeti nad spinaci urovni


    // ------------------- zapinani casovacu pri prekroceni / podlezeni urovni -------------------
    if (pasmo == 0 and (casovani == 0 or casovani == 2))                            // napeti prave pokleslo pod rozpinaci uroven (a casovani odpoctu zatim nebezi)
      {
        znacka_startu_casovace = millis();                                          // aktualni cas se zaznamena
        casovani = 1;
      }

    if (pasmo == 2 and (casovani == 0 or casovani == 1) )                           // napeti prave prekrocilo spinaci uroven (a casovani odpoctu zatim nebezi)
      {
        znacka_startu_casovace = millis();                                          // aktualni cas se zaznamena
        casovani = 2;
      }

    if (pasmo == 1)                                                                 // kdyz je napeti mezi nastavenymi urovnemi, casovani se zastavuje
      {
        casovani = 0;
      }



    // ----------------  ovladani rele po dobehnuti casovace ----------------------
    if ((millis() - znacka_startu_casovace) > casovac_sepnuti and casovani == 2)    // odpocet sepnuti dobehnul do konce, rele se sepne
      {
        digitalWrite(pin_rele, HIGH);
        stav_rele = true;                                                           // nepovinne - jen kvuli vypisu
      }

    if ((millis() - znacka_startu_casovace) > casovac_rozepnuti and casovani == 1)  // odpocet rozepnuti dobehnul do konce, rele se rozepne
      {
        digitalWrite(pin_rele, LOW);
        stav_rele = false;                                                          // nepovinne - jen kvuli vypisu
      }




    // ----------------  vyhodnoceni tlacitek ----------------------
    //  Tohle by chtelo jeste vylepsit - treba autorepeatem pri dlouhem drzeni tlacitek
    if (digitalRead(pin_tl_sepnout_plus) == SEPNUTO)                                // tacitko "zapinani plus" stisknuto
      {
        spinaci_uroven ++;                                                          // spinaci uroven se o 1 zvysi
        byla_spinaci_zmena = true;                                                  // aby se do EEPROM neukladaly hodnoty pri kazdem pruchodu, ale jen pri pri zmene
        casovac_EEPROM = millis();                                                  // do EEPROM se bude zmena ukladat jeste po urcitem obdobi necinnosti 
        if (spinaci_uroven > 1023)  spinaci_uroven = 1023;                          // zarazka na maximalni hodnote, kterou nelze prelezt
        delay(50);                                                                  // odruseni zakmitu pri stisku
        if (stav_autorepeat == false)         
          {
            autorepeat_start = millis() + dlouhy_stisk;                             // casova znacka, kdy se ma tlacitko automaticky zopakovat
            stav_autorepeat = true;                                                 // zapnuti autorepeatu
          }
        while (digitalRead(pin_tl_sepnout_plus) == SEPNUTO and (millis() < autorepeat_start)) ;  // cekani na uvolneni tlacitka, nebo vyprseni casovani autorepeatu
        autorepeat_start = autorepeat_start + prodleva_autorepeat;                  // dalsi automaticky stisk se nastavi o "prodlevu" pozdeji
        delay(50);                                                                  // odruseni zakmitu pri uvolneni
      }

    if (digitalRead(pin_tl_sepnout_minus) == SEPNUTO)                               // tacitko "zapinani minus" stisknuto
      {
        spinaci_uroven --;                                                          // spinaci uroven se o 1 snizi
        byla_spinaci_zmena = true;                                                  // aby se do EEPROM neukladaly hodnoty pri kazdem pruchodu, ale jen pri pri zmene
        casovac_EEPROM = millis();                                                  // do EEPROM se bude zmena ukladat jeste po urcitem obdobi necinnosti 
        if (spinaci_uroven < rozpinaci_uroven)  spinaci_uroven = rozpinaci_uroven;  // zarazka na minimalni hodnote
        delay(50);                                                                  // odruseni zakmitu pri stisku
        if (stav_autorepeat == false)         
          {
            autorepeat_start = millis() + dlouhy_stisk;                             // casova znacka, kdy se ma tlacitko automaticky zopakovat
            stav_autorepeat = true;                                                 // zapnuti autorepeatu
          }
        while (digitalRead(pin_tl_sepnout_minus) == SEPNUTO and (millis() < autorepeat_start)) ;  // cekani na uvolneni tlacitka, nebo vyprseni casovani autorepeatu
        autorepeat_start = autorepeat_start + prodleva_autorepeat;                  // dalsi automaticky stisk se nastavi o "prodlevu" pozdeji
        delay(50);                                                                  // odruseni zakmitu pri uvolneni
      }

    if (digitalRead(pin_tl_rozepnout_plus) == SEPNUTO)                              // tacitko "rozepinani plus" stisknuto
      {
        rozpinaci_uroven ++;                                                        // spinaci uroven se o 1 zvysi
        byla_rozpinaci_zmena = true;                                                // aby se do EEPROM neukladaly hodnoty pri kazdem pruchodu, ale jen pri pri zmene
        casovac_EEPROM = millis();                                                  // do EEPROM se bude zmena ukladat jeste po urcitem obdobi necinnosti 
        if (rozpinaci_uroven > spinaci_uroven)  rozpinaci_uroven = spinaci_uroven;  // zarazka na maximalni hodnote, kterou nelze prelezt
        delay(50);                                                                  // odruseni zakmitu pri stisku
        if (stav_autorepeat == false)         
          {
            autorepeat_start = millis() + dlouhy_stisk;                             // casova znacka, kdy se ma tlacitko automaticky zopakovat
            stav_autorepeat = true;                                                 // zapnuti autorepeatu
          }
        while (digitalRead(pin_tl_rozepnout_plus) == SEPNUTO and (millis() < autorepeat_start)) ;  // cekani na uvolneni tlacitka, nebo vyprseni casovani autorepeatu
        autorepeat_start = autorepeat_start + prodleva_autorepeat;                  // dalsi automaticky stisk se nastavi o "prodlevu" pozdeji
        delay(50);                                                                  // odruseni zakmitu pri uvolneni
      }

    if (digitalRead(pin_tl_rozepnout_minus) == SEPNUTO)                             // tacitko "rozepinani minus" stisknuto
      {
        rozpinaci_uroven --;                                                        // rozepinaci uroven se o 1 snizi
        byla_rozpinaci_zmena = true;                                                // aby se do EEPROM neukladaly hodnoty pri kazdem pruchodu, ale jen pri pri zmene
        casovac_EEPROM = millis();                                                  // do EEPROM se bude zmena ukladat jeste po urcitem obdobi necinnosti 
        if (rozpinaci_uroven < 0)  rozpinaci_uroven = 0;                            // zarazka na minimalni hodnote (nulu nelze podlezt)
        delay(50);                                                                  // odruseni zakmitu pri stisku
        if (stav_autorepeat == false)         
          {
            autorepeat_start = millis() + dlouhy_stisk;                             // casova znacka, kdy se ma tlacitko automaticky zopakovat
            stav_autorepeat = true;                                                 // zapnuti autorepeatu
          }
        while (digitalRead(pin_tl_rozepnout_minus) == SEPNUTO and (millis() < autorepeat_start)) ;  // cekani na uvolneni tlacitka, nebo vyprseni casovani autorepeatu
        autorepeat_start = autorepeat_start + prodleva_autorepeat;                  // dalsi automaticky stisk se nastavi o "prodlevu" pozdeji
        delay(50);                                                                  // odruseni zakmitu pri uvolneni
      }


    if (digitalRead(pin_tl_sepnout_plus)    != SEPNUTO and 
        digitalRead(pin_tl_sepnout_minus)   != SEPNUTO and
        digitalRead(pin_tl_rozepnout_plus)  != SEPNUTO and 
        digitalRead(pin_tl_rozepnout_minus) != SEPNUTO)                              // kdyz jsou vsechna 4 tlacitka uvolnena ... 
          {
            stav_autorepeat = false;                                                 // ... autorepeat se rusi
          }



   //----------------------------
   // ukladani nastavenych hodnot do EEPROM - ale jen v pripade, ze doslo k manipulaci s tlacitky a ted uz se nekolik (10) sekund na tlacitka nesahlo
   if (byla_rozpinaci_zmena == true and (millis() - casovac_EEPROM) > 10000)        // casovac necinnosti po nastaveni nove rozpinaci urovne vyprsel
      {
        byla_rozpinaci_zmena = false;                                               // priste uz se ukladat nebude
        EEPROM.write(0, rozpinaci_uroven/256);                                      // ted se ale zapis do EEPROM provede
        EEPROM.write(1, rozpinaci_uroven%256);
        Serial.println("EEPROM: zapis rozpinaci urovne");
      }
   
   if (byla_spinaci_zmena == true and (millis() - casovac_EEPROM) > 10000)          // casovac necinnosti po nastaveni nove spinaci urovne vyprsel
      {
        byla_spinaci_zmena = false;                                                 // priste uz se ukladat nebude
        EEPROM.write(2, spinaci_uroven/256);                                        // ted se ale zapis do EEPROM provede
        EEPROM.write(3, spinaci_uroven%256);
        Serial.println("EEPROM: zapis spinaci urovne");
      }
   //----------------------------


   //----------------------------
   // tady zobrazovat hodnoty na displeji 

      Serial.print("Vstup A0:");
      Serial.print(napeti);
      Serial.print(" ( = ");
      Serial.print(volty , 3);
      Serial.print(" V)   pasmo:");
      Serial.print(pasmo);
      Serial.print("   casovani:");
      Serial.print(casovani); 
      Serial.print("   rozpinaci:");
      Serial.print(rozpinaci_uroven);
      Serial.print("  ( = ");
      Serial.print(rozpinaci_uroven * kalibrace , 3);              
      Serial.print(" V)     spinaci:");
      Serial.print(spinaci_uroven); 
      Serial.print("  ( = ");
      Serial.print(spinaci_uroven * kalibrace , 3);
      Serial.print(" V)     RELE:");
      Serial.println(stav_rele);
      delay(10);      
   //----------------------------

    
  }  // konec hlavni smycky

//=============================================================================================================


// Tento podprogram probehne jen 1x pri prvnim spusteni programu, kdyz jsou v EEPROM nesmyslne hodnoty
void nastav_defaulty(void)
  {
    Serial.println("V EEPROM jsou nesmysly, nastavuji defaultni meze 512 a 590");
    rozpinaci_uroven = 512;                                                  //  512 = 12.5V / kalibracni konstanta
    spinaci_uroven = 590;                                                    //  590 = 14.4V / kalibracni konstanta
    EEPROM.write(0, rozpinaci_uroven/256);
    EEPROM.write(1, rozpinaci_uroven%256);
    EEPROM.write(2, spinaci_uroven/256);
    EEPROM.write(3, spinaci_uroven%256);    
  }

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 15 hostů