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);
}