Řídící jednotka pro automatický kotel

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
jenicek_sut
Příspěvky: 8
Registrován: 14 říj 2018, 14:55
Reputation: 0

Řídící jednotka pro automatický kotel

Příspěvek od jenicek_sut » 14 říj 2018, 15:41

Ahoj.
Vzhledem k tomu, že moje současná řídící jednotka dosluhuje, rozhodl jsem se vytvořit jinou pomocí arduina.
Kód který je níže, je funkční a v podstatě by šel už nyní v nouzi použít. Display nepotřebuji, ovládání tlačítky také ne, v podstatě stačí, když bude tupě provádět, co se mu řekne.
Jsem absolutní začátečník, tak prosím neukamenovat

- neumím nastavit hysterezi (tedy nastavímeli teplotu kotle pro sepnutí relé na 60° a hystereze bude 4°, dojde při poklesu teploty pod 60 k cyklům topení do dosažení teploty 64°, mezi teplotami 60-64 se nebude dít nic)

- potřebuji, aby po nastavené době došlo k jednomu cyklu topení v případě, že během nastavené doby kotel netopil (kvůli nebezpeči vyhasnutí)

-potřebuji, aby po nastavené době došlo k odstavení kotle, pokud během této doby nedosáhne požadované teploty (není nezbytné)

Bylo by obtížné posílat výpis ze sériové linky online přes wifi? (při použití desky WemosD1)
Použito UNO a dvojitý relé modul
Uvedený kód je asi hrozný, ale funguje až na výše uvedené.

Děkuji.
Honza

Kód: Vybrat vše

//Řídící jednotka pro automatický kotel
#include <OneWire.h>
#include <DallasTemperature.h>

// nastavení čísla vstupního pinu
const int pinCidlaDS = 4; // vytvoření instance oneWireDS z knihovny OneWire
OneWire oneWireDS(pinCidlaDS); // vytvoření instance senzoryDS z knihovny DallasTemperature
DallasTemperature senzoryDS(&oneWireDS);
int rel1 = 12;        //pin rele ventilatoru
int rel2 = 11;        //pin rele podavace
int HYS = 4;          //hystereze ve °C
int tepVYP = 25;      //pozadovana teplota kotle ve °C (pro vypnuti podavace a ventilatoru)
int tepHAV = 28;      //havarijni teplota kotle ve °C pro odstaveni zarizeni na 10 dni
int presPAL = 5000;   //prestavka v dodavce paliva v ms
int dodPAL = 2000;    //doba dodavky paliva v ms
int dobMER = 1000;    //perioda mereni teploty natopeneho kotle v ms 
int dobPROD = 3600000 //doba prodlevy v ms - po uplynutí této doby se provede 1 cyklus přiložení a profouknutí
                      //pokud nedošlo za uvedenou dobu k cyklu topení
int dobTOP = 3600000  //doba topení v ms - po uplynutí této doby dojde k odstaveni zarizeni na 10 dni
                      //protože kotel nebyl schopen dosáhnout za tuto dobu požadovanou teplotu 
void setup(void)
{
  Serial.begin(9600);
  senzoryDS.begin();
  pinMode(rel1, OUTPUT);
  pinMode(rel2, OUTPUT);
}

void loop(void)
{
  // načtení informací ze všech připojených čidel na daném pinu
  senzoryDS.requestTemperatures();
  // výpis teploty na sériovou linku, při připojení více čidel
  // na jeden pin můžeme postupně načíst všechny teploty
  // pomocí změny čísla v závorce (0) - pořadí dle unikátní adresy čidel
  Serial.print("Teplota kotle je ");
  Serial.print(senzoryDS.getTempCByIndex(0));
  Serial.println("° Celsia");
  Serial.print("Pozadovana teplota je ");
  Serial.print(tepVYP);
  Serial.print("° Celsia");
  Serial.println(" ");
  if    (senzoryDS.getTempCByIndex(0) >= tepHAV)
        {digitalWrite(rel1, HIGH);
        digitalWrite(rel2, HIGH);
        Serial.println ("!!!!!!!!!!!!Pretopeni kotle!!!!!!!!!!!!!!");
        delay (864000000);}
  if    (senzoryDS.getTempCByIndex(0) == -127.00)
        Serial.println ("Chyba čidla");
  if    ((senzoryDS.getTempCByIndex(0) < tepVYP-HYS) && (senzoryDS.getTempCByIndex(0) != -127.00))
        {digitalWrite(rel1, LOW);
        digitalWrite(rel2, HIGH);
        Serial.println ("Topim - ventilator zapnut");
        Serial.println ("Podavac vypnut");
        delay(presPAL); //prestavka v dodavce paliva
        digitalWrite(rel2, LOW);
        Serial.println ("Podavac zapnut");
        delay(dodPAL); //bezi dodavka paliva
        digitalWrite(rel2, HIGH);}
   else {digitalWrite(rel1, HIGH);
        digitalWrite(rel2, HIGH);
        Serial.println ("Netopim");
        delay (dobMER);}
}

martinius96
Příspěvky: 579
Registrován: 01 srp 2017, 19:29
Reputation: 0
Bydliště: Poprad
Kontaktovat uživatele:

Re: Řídící jednotka pro automatický kotel

Příspěvek od martinius96 » 14 říj 2018, 16:03

Ahoj, Honzo.
V prvom rade nevidím nejaký zabezpečovací systém celého Arduina, ktorý by ho dokázal resetovať, ak by ti zamrzlo.
Nevidím taktiež ošetrenie nameranej teploty. Čo ak dallas začne merať nezmyselné údaje 85°C?
Hysterézu tam máš, ale nevieš ju použiť.
Potrebuješ zmerať nastavenu teplotu - nameranu a či je ich rozdiel väčší ako hysteréza...
Overuješ iba koncové stavy. Nie teploty medzi nimi. Ak je teplota medzi, nestaráš sa o to.
Príklad (interiérový termostat):
Nameraná: 21.44°C
Požadovaná 22.00°C
Hysteréza: 0,5°C

Kód: Vybrat vše

if((pozadovana-namerana)>hystereza){ // pozadovana 22.00 - namerana 21.44 = 0.56 >0,5 --> podmienka sa splni 
digitalWrite(reletopeni, HIGH); //alebo low pri rele s opacnou logikou
}else if((pozadovana-namerana)<(-1*hystereza)){ //pozadovana 22.00 namerana napr 23.. 22-23 = -1 a to je menej ako -0,5
digitalWrite(reletopeni, LOW); //alebo high pri rele s opacnou logikou
}
S ostatným ti nepomôžem. Ja používam webovo orientované systémy, kde pracujem s časom webservera, hysterézou a celou logikou systému. Arduino si už iba stiahne ZAP/VYP pre daný výstup a nemusím u neho robiť žiadne prepočty. Ano, po wifi to pošleš, ale až po delayi, alebo pred ním.
Kód si dokážeš oveľa zjednodušiť, ak si najprv overíš, či teplota nie je -127 alebo 85 a ak nie, tak v else si urobíš logiku celého systému, a nemusíš to overovať viac krát.
Môj systém, ktorý som kedysi tvoril je tu na ukážku: https://arduino.php5.sk/autonomne-vykurovanie/
Ak budeš mať záujem, viem ti poslať program pre NodeMCU (Wemos atď...), aby si si to vyskúšal priamo v tom web rozhraní a lepšie tomu pochopil.
Využíva fixnú hysterézu 1°C pre termostat a bez hysterézy pre obehové čerpadlo.

jenicek_sut
Příspěvky: 8
Registrován: 14 říj 2018, 14:55
Reputation: 0

Re: Řídící jednotka pro automatický kotel

Příspěvek od jenicek_sut » 14 říj 2018, 17:58

Moc děkuji.
Funkce proti zamrznutí? Vygooglil jsem watchdog, je to ono?
Hlídání dallasu - současná řídící jednotka také nehlídá - je tam termistor (resp. hlídá pouze funguje/nefunguje), ne jak funguje, asi s tím umím žít.
Tu hysterezi jsem doplnil, ale buď špatně, nebo jsme se nepochopili.
Potřebuji, při hysterezi 4°C a nastavených 27°C aby:
při poklesu teploty v rozmezí 23-27: nic nesepnuto
při poklesu teploty pod 23: topí až do doby dosažení teploty 27°C
Hodnoty teplot a časů jsou pro potřeby testování...
Na stránky jsem se díval, je to pěkné, ale bojím se, že bych se v kódu ztratil, ale třeba ne?

příklad naměřená 22,99 požadovaná 27 =-4.01 a to není větší než HYS zkoušel jsem prohodit namerena-pozadovana, to funguje, ale při dosažení teploty větší než 23 topit přestane.
if((namerana-pozadovana)>hystereza){ //22.00 - 21.44 = 0.56 >0,5 --> podmienka sa splni
digitalWrite(reletopeni, HIGH); //alebo low pri rele s opacnou logikou
}else if((namerana-pozadovana)<(-1*hystereza)){ //nastavena 22.00 namerana napr 23.. 22-23 = -1 a to je menej ako -0,5
digitalWrite(reletopeni, LOW); //alebo high pri rele s opacnou logikou
}
Díky

Kód: Vybrat vše

//Řídící jednotka pro automatický kotel
#include <OneWire.h>
#include <DallasTemperature.h>

// nastavení čísla vstupního pinu
const int pinCidlaDS = 4; // vytvoření instance oneWireDS z knihovny OneWire
OneWire oneWireDS(pinCidlaDS); // vytvoření instance senzoryDS z knihovny DallasTemperature
DallasTemperature senzoryDS(&oneWireDS);
int rel1 = 12;        //pin rele ventilatoru
int rel2 = 11;        //pin rele podavace
int HYS = 4;          //hystereze ve °C
int tepVYP = 27;      //pozadovana teplota kotle ve °C (pro vypnuti podavace a ventilatoru)
int tepHAV = 28;      //havarijni teplota kotle ve °C pro odstaveni zarizeni na 10 dni
int presPAL = 5000;   //prestavka v dodavce paliva v ms
int dodPAL = 2000;    //doba dodavky paliva v ms
int dobMER = 5000;    //perioda mereni teploty natopeneho kotle v ms 
//int dobPROD = 3500000; //doba prodlevy v ms - po uplynutí této doby se provede 1 cyklus přiložení a profouknutí
                      //pokud nedošlo za uvedenou dobu k cyklu topení
//int dobTOP = 3600000;  //doba topení v ms - po uplynutí této doby dojde k odstaveni zarizeni na 10 dni
                      //protože kotel nebyl schopen dosáhnout za tuto dobu požadovanou teplotu 
void setup(void)
{
  Serial.begin(9600);
  senzoryDS.begin();
  pinMode(rel1, OUTPUT);
  pinMode(rel2, OUTPUT);
}

void loop(void)
{
  // načtení informací ze všech připojených čidel na daném pinu
  senzoryDS.requestTemperatures();
  // výpis teploty na sériovou linku, při připojení více čidel
  // na jeden pin můžeme postupně načíst všechny teploty
  // pomocí změny čísla v závorce (0) - pořadí dle unikátní adresy čidel
  Serial.print("Teplota kotle je ");
  Serial.print(senzoryDS.getTempCByIndex(0));
  Serial.println("° Celsia");
  Serial.print("Pozadovana teplota je ");
  Serial.print(tepVYP);
  Serial.print("° Celsia");
  Serial.println(" ");
  if    (senzoryDS.getTempCByIndex(0) >= tepHAV)
        {digitalWrite(rel1, HIGH);
        digitalWrite(rel2, HIGH);
        Serial.println ("!!!!!!!!!!!!Pretopeni kotle!!!!!!!!!!!!!!");
        delay (864000000);}
  if    (senzoryDS.getTempCByIndex(0) == -127.00) 
        Serial.println ("Chyba čidla");
if    ((senzoryDS.getTempCByIndex(0)-tepVYP) > HYS && (senzoryDS.getTempCByIndex(0) != -127.00))
        {digitalWrite(rel1, LOW);
        digitalWrite(rel2, HIGH);
        Serial.println ("Topim - ventilator zapnut");
        Serial.println ("Podavac vypnut");
        delay(presPAL); //prestavka v dodavce paliva
        digitalWrite(rel2, LOW);
        Serial.println ("Podavac zapnut");
        delay(dodPAL); //bezi dodavka paliva
        digitalWrite(rel2, HIGH);}
else if ((senzoryDS.getTempCByIndex(0)-tepVYP)<(-1*HYS) && (senzoryDS.getTempCByIndex(0) != -127.00))
        {digitalWrite(rel1, HIGH);
        digitalWrite(rel2, HIGH);}
   else {digitalWrite(rel1, HIGH);
        digitalWrite(rel2, HIGH);
        Serial.println ("Netopim");
        delay (dobMER);}
}

martinius96
Příspěvky: 579
Registrován: 01 srp 2017, 19:29
Reputation: 0
Bydliště: Poprad
Kontaktovat uživatele:

Re: Řídící jednotka pro automatický kotel

Příspěvek od martinius96 » 15 pro 2018, 18:27

Áno, watchdog je to, čo potrebuješ.
V kódoch pre riadenie hysterézy sa niet kde stratiť.
Tak, ako som písal vtedy, dávaš pozor iba na stav nad hysterézou a pod - (mínus) hysterézou. O stav medzi sa nestaráš.
Urob si v programe globálnu premennú pre teplotu, alebo premennú v loop, bude sa ti s tým lepšie pracovať.
Čiže pre ovládanie v tvojom pripade budeme potrebovať:

Kód: Vybrat vše

int HYS = 2;  //hystereza
float stredteploty = 62;
float aktualnateplota = senzoryDS.getTempCByIndex(0);
//rozhodovacia časť
if((stredteploty-aktualnateplota)>HYS){ //teplota je 64.01 alebo viac - koncovy stav do +
digitalWrite(topeni, LOW); //vypneme
}else if((stredteploty-aktualnateplota)<(-1*HYS)){//teplota je 59.99 alebo menej - koncovy stav do -
digitalWrite(topeni, HIGH); //zapneme
}
//o hodnoty medzi sa nestarame
A čo sa týka najjednoduchšieho watchdogu...
Trebars....

Kód: Vybrat vše

#include <avr\wdt.h> //kniznica watchdogu
void setup(){
wdt_enable(WDTO_8S); //8 sekundovy watchdog - ak sa do 8s neresetne, restartne to Arduino
}
void loop(){
wdt_reset(); //reset watchdogu - volat tak casto, aby sa nepresiahlo 8s. Ak Arduino zamrzne, resetne to.
}
Idem sa pochváliť s rozšírením pre tento rok :-)
Tohto roku som rozširoval systém, ktorý som pred rokom vytvoril, aby bolo možné zvoliť aj riadiaci teplomer, voliteľnú hysterézu pre termostat.
Rovnako tak som doprogramoval i voliteľný teplomer pre riadenie čerpadla bez hysterézy.
Obrázek
Obrázek
Grafická reprezentácia stavu termostatu, čerpadla
0 = OFF
1 = ON
Obrázek

Odpovědět

Kdo je online

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