1

Тема: Терморегулятор с тремя реле

Разработка

D2 вход 18b20

http://forum.rcl-radio.ru/uploads/images/2021/12/8029118d87a2df75a759f4f8ba6df6aa.png
http://forum.rcl-radio.ru/uploads/images/2021/12/e74895d40cd429ffc3f3bbfe98f20cd4.png
http://forum.rcl-radio.ru/uploads/images/2021/12/7eb0db7dd850be29c0f8065f5e563f6b.png
http://forum.rcl-radio.ru/uploads/images/2021/12/f2d537434d93f00d540d91ec34105518.png
http://forum.rcl-radio.ru/uploads/images/2021/12/df535a854fba53a978f7e22f7470ebcc.png

http://forum.rcl-radio.ru/uploads/images/2021/12/52cd9d1271bdc1622e3780a0b9d1bbb6.png

Датчик уровня воды замкнут если погружен в воду, датчик перегрева KSD301 замкнут пока температура ниже 95 гр.
Цельсия.

Если на главном экране появится надпись ERR, то сработал датчик уровня воды или датчик перегрева, все реле при этом отключаются.

#include <LiquidCrystal_I2C.h>  // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
#include <OneWire.h>            // http://rcl-radio.ru/wp-content/uploads/2018/07/OneWire.zip
#include <Wire.h>
#include <Encoder.h>            // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip       
#include <EEPROM.h>
#include <MsTimer2.h>           // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip 
 LiquidCrystal_I2C lcd(0x27,16,2);
 Encoder myEnc(8, 9);// DT, CLK
 OneWire  ds(2); // Вход датчика 18b20
 byte v1[8] = {0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07};
 byte v2[8] = {0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00};      
 byte v3[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F};
 byte v4[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x1F,0x1F};
 byte v5[8] = {0x1C,0x1C,0x00,0x00,0x00,0x00,0x1C,0x1C};
 byte v6[8] = {0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C};
 byte v7[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07};
 byte v8[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00};
 byte d1,d2,d3,d4,d5,d6,e1,e2,e3;
 int a[6],x,menu,t_ds;
 int reg_t1,reg_t2,reg_t3,gis;
 unsigned long times,times1,oldPosition  = -999,newPosition;
 bool w,nagrev1,nagrev2,nagrev3,err;

 void setup(){
  Wire.begin();lcd.init();lcd.backlight();Serial.begin(9600);
  MsTimer2::set(1, to_Timer);MsTimer2::start();
  if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}// очистка памяти при первом включении
  lcd.createChar(1, v1);lcd.createChar(2, v2);lcd.createChar(3, v3);lcd.createChar(4, v4);
  lcd.createChar(5, v5);lcd.createChar(6, v6);lcd.createChar(7, v7);lcd.createChar(8, v8);
   
  pinMode(10,INPUT);       // кнопка SW ENCODER 
  pinMode(3,INPUT_PULLUP); // KSD301 (второй вывод KSD301 на GND)
  pinMode(4,INPUT_PULLUP); // геркон (второй вывод геркона на GND)
  pinMode(5,OUTPUT);       // выход реле 1
  pinMode(6,OUTPUT);       // выход реле 2
  pinMode(7,OUTPUT);       // выход реле 3
  
  reg_t1 = EEPROM.read(0);reg_t2 = EEPROM.read(1);reg_t3 = EEPROM.read(2);gis = EEPROM.read(3);
  digitalWrite(5,LOW);digitalWrite(6,LOW);digitalWrite(7,LOW);
  } 
  

void loop(){
///////// BUTTON ////////////////////////  
  if(digitalRead(10)==LOW){menu++;if(menu>4){menu=0;}times1=millis();w=1;lcd.clear();delay(300);}
  
///////// READ TEMP /////////////////////////////////////////////
 if(millis()-times>1000){times=millis();t_ds = dsRead(0)*10;}// Измерять температуру 1 раз в секунду
///////// LCD BIG ///////////////////////////////////////////////
 if(menu==0){
     a[0]=t_ds/1000;
     a[1]=t_ds/100%10;
     a[2]=t_ds/10%10;
     a[3]=t_ds%10;
     if(t_ds<1000){a[0]=10;}
     if(t_ds<100){a[1]=10;}
   for(x=0;x<4;x++){
    switch(x){
        case 0: e1=0;e2=0,e3=1;break;
        case 1: e1=2,e2=3,e3=4;break;
        case 2: e1=5,e2=6,e3=7;break;
        case 3: e1=9,e2=10,e3=11;break;
   }digit();}
   lcd.setCursor(8,1);lcd.print(".");
   lcd.setCursor(12,1);lcd.print(char(223)); lcd.print("C"); 
   if(err==0){
   if(nagrev1==1){lcd.setCursor(13,0);lcd.print("H");}else{lcd.setCursor(13,0);lcd.print("L");}
   if(nagrev2==1){lcd.setCursor(14,0);lcd.print("H");}else{lcd.setCursor(14,0);lcd.print("L");}
   if(nagrev3==1){lcd.setCursor(15,0);lcd.print("H");}else{lcd.setCursor(15,0);lcd.print("L");}
   }else{lcd.setCursor(13,0);lcd.print("ERR");}
    }
/////// MENU 1 ////////////////////////////////////////////////////////////
  if(menu==1){
    if(newPosition != oldPosition){oldPosition = newPosition;reg_t1=reg_t1+newPosition;myEnc.write(0);
    newPosition=0;times1=millis();;w=1;if(reg_t1>125){reg_t1=125;}if(reg_t1<0){reg_t1=0;}}

     a[0]=reg_t1/100;
     a[1]=reg_t1/10%10;
     a[2]=reg_t1%10;
     if(reg_t1<100){a[0]=10;}
     if(reg_t1<10){a[1]=10;}
   for(x=0;x<3;x++){
    switch(x){
        case 0: e1=0;e2=1,e3=2;break;
        case 1: e1=3,e2=4,e3=5;break;
        case 2: e1=6,e2=7,e3=8;break;
   }digit();}
   lcd.setCursor(12,0);lcd.print("T_1"); 
   lcd.setCursor(9,1);lcd.print(char(223)); lcd.print("C"); 
   }  
/////// MENU 2 ////////////////////////////////////////////////////////////
  if(menu==2){
    if(newPosition != oldPosition){oldPosition = newPosition;reg_t2=reg_t2+newPosition;myEnc.write(0);
    newPosition=0;times1=millis();;w=1;if(reg_t2>125){reg_t2=125;}if(reg_t2<0){reg_t2=0;}}

     a[0]=reg_t2/100;
     a[1]=reg_t2/10%10;
     a[2]=reg_t2%10;
     if(reg_t2<100){a[0]=10;}
     if(reg_t2<10){a[1]=10;}
   for(x=0;x<3;x++){
    switch(x){
        case 0: e1=0;e2=1,e3=2;break;
        case 1: e1=3,e2=4,e3=5;break;
        case 2: e1=6,e2=7,e3=8;break;
   }digit();}
   lcd.setCursor(12,0);lcd.print("T_2"); 
   lcd.setCursor(9,1);lcd.print(char(223)); lcd.print("C"); 
   }    
/////// MENU 3 ////////////////////////////////////////////////////////////
  if(menu==3){
    if(newPosition != oldPosition){oldPosition = newPosition;reg_t3=reg_t3+newPosition;myEnc.write(0);
    newPosition=0;times1=millis();;w=1;if(reg_t3>125){reg_t3=125;}if(reg_t3<0){reg_t3=0;}}

     a[0]=reg_t3/100;
     a[1]=reg_t3/10%10;
     a[2]=reg_t3%10;
     if(reg_t3<100){a[0]=10;}
     if(reg_t3<10){a[1]=10;}
   for(x=0;x<3;x++){
    switch(x){
        case 0: e1=0;e2=1,e3=2;break;
        case 1: e1=3,e2=4,e3=5;break;
        case 2: e1=6,e2=7,e3=8;break;
   }digit();}
   lcd.setCursor(12,0);lcd.print("T_3"); 
   lcd.setCursor(9,1);lcd.print(char(223)); lcd.print("C"); 
   } 
///////////// hysteresis ///////////////////////////////   
  if(menu==4){
    if(newPosition != oldPosition){oldPosition = newPosition;gis=gis+newPosition;myEnc.write(0);
    newPosition=0;times1=millis();w=1;if(gis<0){gis=0;}if(gis>30){gis=30;}}
    lcd.setCursor(3,0);lcd.print("hysteresis ");
    lcd.setCursor(5,1);lcd.print((float)gis/10,1);
    lcd.print(char(223)); lcd.print("C"); 
  }  
///////// EEPROM ////////////////////////////////////////////////
  if(millis()-times1>10000 && w==1){
   EEPROM.update(0,reg_t1);EEPROM.update(1,reg_t2);EEPROM.update(2,reg_t3);EEPROM.update(3,gis);
   menu=0;w=0;lcd.clear();} 
///////////////////////////////////////////////////////////////////
  if(digitalRead(4)==LOW&&digitalRead(3)==LOW){
  err=0;  
  if(reg_t1*10 >= t_ds + gis){digitalWrite(5,HIGH);nagrev1=1;}
  if(reg_t1*10 <= t_ds - gis){digitalWrite(5,LOW);nagrev1=0;}   

  if(reg_t2*10 >= t_ds + gis){digitalWrite(6,HIGH);nagrev2=1;}
  if(reg_t2*10 <= t_ds - gis){digitalWrite(6,LOW);nagrev2=0;} 

  if(reg_t3*10 >= t_ds + gis){digitalWrite(7,HIGH);nagrev3=1;}
  if(reg_t3*10 <= t_ds - gis){digitalWrite(7,LOW);nagrev3=0;}
  }
  else{digitalWrite(5,LOW);digitalWrite(6,LOW);digitalWrite(7,LOW);err=1;}
  Serial.print(reg_t1*10);  Serial.print(" ");  Serial.print(t_ds);  Serial.print(" ");  Serial.print(gis);  Serial.print(" ");  Serial.println(err);               
}// end loop

void digit(){
  switch(a[x]){
    case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
    case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
    case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
    case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
    case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
    case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
    case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
    case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
    case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    case 10:d1=150,d2=150,d3=150,d4=150,d5=150,d6=150;break;
    }
if(x>0){lcd.setCursor(e1,0);lcd.write((uint8_t)d1);}
lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);lcd.setCursor(e1,1);
lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);} 

float dsRead(byte x) {
  byte data[2], addr[8][8], kol = 0;
  while (ds.search(addr[kol])) {  // поиск датчиков, определение адреса и кол-ва датчиков
    kol++;
  } 
  ds.reset_search();  // Сброс поиска датчика
  ds.reset();         // Инициализация, выполняется сброс шины
  ds.select(addr[x]); // Обращение к датчику по адресу
  ds.write(0x44, 0);  // Измерение температуры с переносом данных в память
  ds.reset();         // Инициализация, выполняется сброс шины
  ds.select(addr[x]); // Обращение к датчику по адресу
  ds.write(0xBE);     // Обращение памяти
  data[0] = ds.read();// Чтение памяти byte low
  data[1] = ds.read();// Чтение памяти byte high
  float value = ((data[1] << 8) | data[0]) / 16.0; return (float)value; // Расчет температуры и вывод
}   

void to_Timer(){newPosition = myEnc.read()/4;}     

2

Re: Терморегулятор с тремя реле

Кнопочное управление

http://forum.rcl-radio.ru/uploads/images/2021/12/1107a8196204606624e34ba75321cf2e.png

#include <LiquidCrystal_I2C.h>  // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
#include <OneWire.h>            // http://rcl-radio.ru/wp-content/uploads/2018/07/OneWire.zip
#include <Wire.h>     
#include <EEPROM.h>

 LiquidCrystal_I2C lcd(0x27,16,2);
 OneWire  ds(2); // Вход датчика 18b20
 byte v1[8] = {0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07};
 byte v2[8] = {0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00};      
 byte v3[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F};
 byte v4[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x1F,0x1F};
 byte v5[8] = {0x1C,0x1C,0x00,0x00,0x00,0x00,0x1C,0x1C};
 byte v6[8] = {0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C};
 byte v7[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07};
 byte v8[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00};
 byte d1,d2,d3,d4,d5,d6,e1,e2,e3;
 int a[6],x,menu,t_ds;
 int reg_t1,reg_t2,reg_t3,gis;
 unsigned long times,times1;
 bool w,nagrev1,nagrev2,nagrev3,err;

 void setup(){
  Wire.begin();lcd.init();lcd.backlight();Serial.begin(9600);
  if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}// очистка памяти при первом включении
  lcd.createChar(1, v1);lcd.createChar(2, v2);lcd.createChar(3, v3);lcd.createChar(4, v4);
  lcd.createChar(5, v5);lcd.createChar(6, v6);lcd.createChar(7, v7);lcd.createChar(8, v8);
   
  pinMode(10,INPUT_PULLUP);       // кнопка MENU
  pinMode(9,INPUT_PULLUP);        // кнопка UP
  pinMode(8,INPUT_PULLUP);        // кнопка DOWN
  pinMode(3,INPUT_PULLUP); // KSD301 (второй вывод KSD301 на GND)
  pinMode(4,INPUT_PULLUP); // геркон (второй вывод геркона на GND)
  pinMode(5,OUTPUT);       // выход реле 1
  pinMode(6,OUTPUT);       // выход реле 2
  pinMode(7,OUTPUT);       // выход реле 3
  
  reg_t1 = EEPROM.read(0);reg_t2 = EEPROM.read(1);reg_t3 = EEPROM.read(2);gis = EEPROM.read(3);
  digitalWrite(5,LOW);digitalWrite(6,LOW);digitalWrite(7,LOW);
  } 
  

void loop(){
///////// BUTTON ////////////////////////  
  if(digitalRead(10)==LOW){menu++;if(menu>4){menu=0;}times1=millis();w=1;lcd.clear();delay(300);}
  
///////// READ TEMP /////////////////////////////////////////////
 if(millis()-times>1000){times=millis();t_ds = dsRead(0)*10;}// Измерять температуру 1 раз в секунду
///////// LCD BIG ///////////////////////////////////////////////
 if(menu==0){
     a[0]=t_ds/1000;
     a[1]=t_ds/100%10;
     a[2]=t_ds/10%10;
     a[3]=t_ds%10;
     if(t_ds<1000){a[0]=10;}
     if(t_ds<100){a[1]=10;}
   for(x=0;x<4;x++){
    switch(x){
        case 0: e1=0;e2=0,e3=1;break;
        case 1: e1=2,e2=3,e3=4;break;
        case 2: e1=5,e2=6,e3=7;break;
        case 3: e1=9,e2=10,e3=11;break;
   }digit();}
   lcd.setCursor(8,1);lcd.print(".");
   lcd.setCursor(12,1);lcd.print(char(223)); lcd.print("C"); 
   if(err==0){
   if(nagrev1==1){lcd.setCursor(13,0);lcd.print("H");}else{lcd.setCursor(13,0);lcd.print("L");}
   if(nagrev2==1){lcd.setCursor(14,0);lcd.print("H");}else{lcd.setCursor(14,0);lcd.print("L");}
   if(nagrev3==1){lcd.setCursor(15,0);lcd.print("H");}else{lcd.setCursor(15,0);lcd.print("L");}
   }else{lcd.setCursor(13,0);lcd.print("ERR");}
    }
/////// MENU 1 ////////////////////////////////////////////////////////////
  if(menu==1){
   if(digitalRead(9)==LOW){reg_t1++;times1=millis();;w=1;if(reg_t1>125){reg_t1=125;}if(reg_t1<0){reg_t1=0;}delay(300);}
   if(digitalRead(8)==LOW){reg_t1--;times1=millis();;w=1;if(reg_t1>125){reg_t1=125;}if(reg_t1<0){reg_t1=0;}delay(300);}
     a[0]=reg_t1/100;
     a[1]=reg_t1/10%10;
     a[2]=reg_t1%10;
     if(reg_t1<100){a[0]=10;}
     if(reg_t1<10){a[1]=10;}
   for(x=0;x<3;x++){
    switch(x){
        case 0: e1=0;e2=1,e3=2;break;
        case 1: e1=3,e2=4,e3=5;break;
        case 2: e1=6,e2=7,e3=8;break;
   }digit();}
   lcd.setCursor(12,0);lcd.print("T_1"); 
   lcd.setCursor(9,1);lcd.print(char(223)); lcd.print("C"); 
   }  
/////// MENU 2 ////////////////////////////////////////////////////////////
  if(menu==2){
   if(digitalRead(9)==LOW){reg_t2++;times1=millis();;w=1;if(reg_t2>125){reg_t2=125;}if(reg_t2<0){reg_t2=0;}delay(300);}
   if(digitalRead(8)==LOW){reg_t2--;times1=millis();;w=1;if(reg_t2>125){reg_t2=125;}if(reg_t2<0){reg_t2=0;}delay(300);}

     a[0]=reg_t2/100;
     a[1]=reg_t2/10%10;
     a[2]=reg_t2%10;
     if(reg_t2<100){a[0]=10;}
     if(reg_t2<10){a[1]=10;}
   for(x=0;x<3;x++){
    switch(x){
        case 0: e1=0;e2=1,e3=2;break;
        case 1: e1=3,e2=4,e3=5;break;
        case 2: e1=6,e2=7,e3=8;break;
   }digit();}
   lcd.setCursor(12,0);lcd.print("T_2"); 
   lcd.setCursor(9,1);lcd.print(char(223)); lcd.print("C"); 
   }    
/////// MENU 3 ////////////////////////////////////////////////////////////
  if(menu==3){
   if(digitalRead(9)==LOW){reg_t3++;times1=millis();;w=1;if(reg_t3>125){reg_t3=125;}if(reg_t3<0){reg_t3=0;}delay(300);}
   if(digitalRead(8)==LOW){reg_t3--;times1=millis();;w=1;if(reg_t3>125){reg_t3=125;}if(reg_t3<0){reg_t3=0;}delay(300);}

     a[0]=reg_t3/100;
     a[1]=reg_t3/10%10;
     a[2]=reg_t3%10;
     if(reg_t3<100){a[0]=10;}
     if(reg_t3<10){a[1]=10;}
   for(x=0;x<3;x++){
    switch(x){
        case 0: e1=0;e2=1,e3=2;break;
        case 1: e1=3,e2=4,e3=5;break;
        case 2: e1=6,e2=7,e3=8;break;
   }digit();}
   lcd.setCursor(12,0);lcd.print("T_3"); 
   lcd.setCursor(9,1);lcd.print(char(223)); lcd.print("C"); 
   } 
///////////// hysteresis ///////////////////////////////   
  if(menu==4){
   if(digitalRead(9)==LOW){gis++;times1=millis();;w=1;if(gis<0){gis=0;}if(gis>30){gis=30;}delay(300);}
   if(digitalRead(8)==LOW){gis--;times1=millis();;w=1;if(gis<0){gis=0;}if(gis>30){gis=30;}delay(300);}
    lcd.setCursor(3,0);lcd.print("hysteresis ");
    lcd.setCursor(5,1);lcd.print((float)gis/10,1);
    lcd.print(char(223)); lcd.print("C"); 
  }  
///////// EEPROM ////////////////////////////////////////////////
  if(millis()-times1>10000 && w==1){
   EEPROM.update(0,reg_t1);EEPROM.update(1,reg_t2);EEPROM.update(2,reg_t3);EEPROM.update(3,gis);
   menu=0;w=0;lcd.clear();} 
///////////////////////////////////////////////////////////////////
  if(digitalRead(4)==LOW&&digitalRead(3)==LOW){
  err=0;  
  if(reg_t1*10 >= t_ds + gis){digitalWrite(5,HIGH);nagrev1=1;}
  if(reg_t1*10 <= t_ds - gis){digitalWrite(5,LOW);nagrev1=0;}   

  if(reg_t2*10 >= t_ds + gis){digitalWrite(6,HIGH);nagrev2=1;}
  if(reg_t2*10 <= t_ds - gis){digitalWrite(6,LOW);nagrev2=0;} 

  if(reg_t3*10 >= t_ds + gis){digitalWrite(7,HIGH);nagrev3=1;}
  if(reg_t3*10 <= t_ds - gis){digitalWrite(7,LOW);nagrev3=0;}
  }
  else{digitalWrite(5,LOW);digitalWrite(6,LOW);digitalWrite(7,LOW);err=1;}
  Serial.print(reg_t1*10);Serial.print(" ");Serial.print(t_ds);Serial.print(" ");
  Serial.print(gis);Serial.print(" ");Serial.println(err);               
}// end loop

void digit(){
  switch(a[x]){
    case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
    case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
    case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
    case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
    case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
    case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
    case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
    case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
    case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    case 10:d1=150,d2=150,d3=150,d4=150,d5=150,d6=150;break;
    }
if(x>0){lcd.setCursor(e1,0);lcd.write((uint8_t)d1);}
lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);lcd.setCursor(e1,1);
lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);} 

float dsRead(byte x) {
  byte data[2], addr[8][8], kol = 0;
  while (ds.search(addr[kol])) {  // поиск датчиков, определение адреса и кол-ва датчиков
    kol++;
  } 
  ds.reset_search();  // Сброс поиска датчика
  ds.reset();         // Инициализация, выполняется сброс шины
  ds.select(addr[x]); // Обращение к датчику по адресу
  ds.write(0x44, 0);  // Измерение температуры с переносом данных в память
  ds.reset();         // Инициализация, выполняется сброс шины
  ds.select(addr[x]); // Обращение к датчику по адресу
  ds.write(0xBE);     // Обращение памяти
  data[0] = ds.read();// Чтение памяти byte low
  data[1] = ds.read();// Чтение памяти byte high
  float value = ((data[1] << 8) | data[0]) / 16.0; return (float)value; // Расчет температуры и вывод
}   
   

3

Re: Терморегулятор с тремя реле

Смена работы реле и тэна каждые 12 часов

#include <LiquidCrystal_I2C.h>  // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
#include <OneWire.h>            // http://rcl-radio.ru/wp-content/uploads/2018/07/OneWire.zip
#include <Wire.h>
#include <Encoder.h>            // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip       
#include <EEPROM.h>
#include <MsTimer2.h>           // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip 
 LiquidCrystal_I2C lcd(0x27,16,2);
 Encoder myEnc(8, 9);// DT, CLK
 OneWire  ds(2); // Вход датчика 18b20
 byte v1[8] = {0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07};
 byte v2[8] = {0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00};      
 byte v3[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F};
 byte v4[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x1F,0x1F};
 byte v5[8] = {0x1C,0x1C,0x00,0x00,0x00,0x00,0x1C,0x1C};
 byte v6[8] = {0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C};
 byte v7[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07};
 byte v8[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00};
 byte d1,d2,d3,d4,d5,d6,e1,e2,e3;
 int a[6],x,menu,t_ds;
 int reg_t1,reg_t2,reg_t3,gis,sec,min;
 unsigned long times,times1,oldPosition  = -999,newPosition,times_12;
 bool w,nagrev1,nagrev2,nagrev3,err;
 byte out1 = 5, out2 = 6, out3 = 7; 

 void setup(){
  Wire.begin();lcd.init();lcd.backlight();Serial.begin(9600);
  MsTimer2::set(1, to_Timer);MsTimer2::start();
  if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}// очистка памяти при первом включении
  lcd.createChar(1, v1);lcd.createChar(2, v2);lcd.createChar(3, v3);lcd.createChar(4, v4);
  lcd.createChar(5, v5);lcd.createChar(6, v6);lcd.createChar(7, v7);lcd.createChar(8, v8);
   
  pinMode(10,INPUT);       // кнопка SW ENCODER 
  pinMode(3,INPUT_PULLUP); // KSD301 (второй вывод KSD301 на GND)
  pinMode(4,INPUT_PULLUP); // геркон (второй вывод геркона на GND)
  pinMode(out1,OUTPUT);       // выход реле 1
  pinMode(out2,OUTPUT);       // выход реле 2
  pinMode(out3,OUTPUT);       // выход реле 3
  
  reg_t1 = EEPROM.read(0);reg_t2 = EEPROM.read(1);reg_t3 = EEPROM.read(2);gis = EEPROM.read(3);
  digitalWrite(5,LOW);digitalWrite(6,LOW);digitalWrite(7,LOW);
  } 
  

void loop(){
///////// BUTTON ////////////////////////  
  if(digitalRead(10)==LOW){menu++;if(menu>4){menu=0;}times1=millis();w=1;lcd.clear();delay(300);}
  
///////// READ TEMP /////////////////////////////////////////////
 if(millis()-times>1000){times=millis();t_ds = dsRead(0)*10;}// Измерять температуру 1 раз в секунду
///////// LCD BIG ///////////////////////////////////////////////
 if(menu==0){
     a[0]=t_ds/1000;
     a[1]=t_ds/100%10;
     a[2]=t_ds/10%10;
     a[3]=t_ds%10;
     if(t_ds<1000){a[0]=10;}
     if(t_ds<100){a[1]=10;}
   for(x=0;x<4;x++){
    switch(x){
        case 0: e1=0;e2=0,e3=1;break;
        case 1: e1=2,e2=3,e3=4;break;
        case 2: e1=5,e2=6,e3=7;break;
        case 3: e1=9,e2=10,e3=11;break;
   }digit();}
   lcd.setCursor(8,1);lcd.print(".");
   lcd.setCursor(12,1);lcd.print(char(223)); lcd.print("C"); 
   if(err==0){
   if(nagrev1==1){lcd.setCursor(13,0);lcd.print("H");}else{lcd.setCursor(13,0);lcd.print("L");}
   if(nagrev2==1){lcd.setCursor(14,0);lcd.print("H");}else{lcd.setCursor(14,0);lcd.print("L");}
   if(nagrev3==1){lcd.setCursor(15,0);lcd.print("H");}else{lcd.setCursor(15,0);lcd.print("L");}
   }else{lcd.setCursor(13,0);lcd.print("ERR");}
    }
/////// MENU 1 ////////////////////////////////////////////////////////////
  if(menu==1){
    if(newPosition != oldPosition){oldPosition = newPosition;reg_t1=reg_t1+newPosition;myEnc.write(0);
    newPosition=0;times1=millis();;w=1;if(reg_t1>125){reg_t1=125;}if(reg_t1<0){reg_t1=0;}}

     a[0]=reg_t1/100;
     a[1]=reg_t1/10%10;
     a[2]=reg_t1%10;
     if(reg_t1<100){a[0]=10;}
     if(reg_t1<10){a[1]=10;}
   for(x=0;x<3;x++){
    switch(x){
        case 0: e1=0;e2=1,e3=2;break;
        case 1: e1=3,e2=4,e3=5;break;
        case 2: e1=6,e2=7,e3=8;break;
   }digit();}
   lcd.setCursor(12,0);lcd.print("T_1"); 
   lcd.setCursor(9,1);lcd.print(char(223)); lcd.print("C"); 
   }  
/////// MENU 2 ////////////////////////////////////////////////////////////
  if(menu==2){
    if(newPosition != oldPosition){oldPosition = newPosition;reg_t2=reg_t2+newPosition;myEnc.write(0);
    newPosition=0;times1=millis();;w=1;if(reg_t2>125){reg_t2=125;}if(reg_t2<0){reg_t2=0;}}

     a[0]=reg_t2/100;
     a[1]=reg_t2/10%10;
     a[2]=reg_t2%10;
     if(reg_t2<100){a[0]=10;}
     if(reg_t2<10){a[1]=10;}
   for(x=0;x<3;x++){
    switch(x){
        case 0: e1=0;e2=1,e3=2;break;
        case 1: e1=3,e2=4,e3=5;break;
        case 2: e1=6,e2=7,e3=8;break;
   }digit();}
   lcd.setCursor(12,0);lcd.print("T_2"); 
   lcd.setCursor(9,1);lcd.print(char(223)); lcd.print("C"); 
   }    
/////// MENU 3 ////////////////////////////////////////////////////////////
  if(menu==3){
    if(newPosition != oldPosition){oldPosition = newPosition;reg_t3=reg_t3+newPosition;myEnc.write(0);
    newPosition=0;times1=millis();;w=1;if(reg_t3>125){reg_t3=125;}if(reg_t3<0){reg_t3=0;}}

     a[0]=reg_t3/100;
     a[1]=reg_t3/10%10;
     a[2]=reg_t3%10;
     if(reg_t3<100){a[0]=10;}
     if(reg_t3<10){a[1]=10;}
   for(x=0;x<3;x++){
    switch(x){
        case 0: e1=0;e2=1,e3=2;break;
        case 1: e1=3,e2=4,e3=5;break;
        case 2: e1=6,e2=7,e3=8;break;
   }digit();}
   lcd.setCursor(12,0);lcd.print("T_3"); 
   lcd.setCursor(9,1);lcd.print(char(223)); lcd.print("C"); 
   } 
///////////// hysteresis ///////////////////////////////   
  if(menu==4){
    if(newPosition != oldPosition){oldPosition = newPosition;gis=gis+newPosition;myEnc.write(0);
    newPosition=0;times1=millis();w=1;if(gis<0){gis=0;}if(gis>30){gis=30;}}
    lcd.setCursor(3,0);lcd.print("hysteresis ");
    lcd.setCursor(5,1);lcd.print((float)gis/10,1);
    lcd.print(char(223)); lcd.print("C"); 
  }  
///////// EEPROM ////////////////////////////////////////////////
  if(millis()-times1>10000 && w==1){
   EEPROM.update(0,reg_t1);EEPROM.update(1,reg_t2);EEPROM.update(2,reg_t3);EEPROM.update(3,gis);
   menu=0;w=0;lcd.clear();} 
///////////////////////////////////////////////////////////////////
  if(millis()-times_12>1000){sec++;times_12=millis();if(sec>59){sec=0;min++;}}
  if(min<=720){
  out1 = 5;
  out2 = 6;
  out3 = 7;
  }
  if(min>720&&min<=1440){
  out1 = 6;
  out2 = 7;
  out3 = 5;
  }
  if(min>1440&&min<=2160){
  out1 = 7;
  out2 = 5;
  out3 = 6;
  }
  if(min>2160){min=0;}
///////////////////////////////////////////////////////////////////
  if(digitalRead(4)==LOW&&digitalRead(3)==LOW){
  err=0;  
  if(reg_t1*10 >= t_ds + gis){digitalWrite(out1,HIGH);nagrev1=1;}
  if(reg_t1*10 <= t_ds - gis){digitalWrite(out1,LOW);nagrev1=0;}   

  if(reg_t2*10 >= t_ds + gis){digitalWrite(out2,HIGH);nagrev2=1;}
  if(reg_t2*10 <= t_ds - gis){digitalWrite(out2,LOW);nagrev2=0;} 

  if(reg_t3*10 >= t_ds + gis){digitalWrite(out3,HIGH);nagrev3=1;}
  if(reg_t3*10 <= t_ds - gis){digitalWrite(out3,LOW);nagrev3=0;}
  }
  else{digitalWrite(out1,LOW);digitalWrite(out2,LOW);digitalWrite(out3,LOW);err=1;}
  Serial.print(reg_t1*10);  Serial.print(" ");  Serial.print(t_ds);  Serial.print(" ");  Serial.print(gis);  Serial.print(" ");  Serial.println(err);               
}// end loop

void digit(){
  switch(a[x]){
    case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
    case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
    case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
    case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
    case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
    case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
    case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
    case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
    case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    case 10:d1=150,d2=150,d3=150,d4=150,d5=150,d6=150;break;
    }
if(x>0){lcd.setCursor(e1,0);lcd.write((uint8_t)d1);}
lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);lcd.setCursor(e1,1);
lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);} 

float dsRead(byte x) {
  byte data[2], addr[8][8], kol = 0;
  while (ds.search(addr[kol])) {  // поиск датчиков, определение адреса и кол-ва датчиков
    kol++;
  } 
  ds.reset_search();  // Сброс поиска датчика
  ds.reset();         // Инициализация, выполняется сброс шины
  ds.select(addr[x]); // Обращение к датчику по адресу
  ds.write(0x44, 0);  // Измерение температуры с переносом данных в память
  ds.reset();         // Инициализация, выполняется сброс шины
  ds.select(addr[x]); // Обращение к датчику по адресу
  ds.write(0xBE);     // Обращение памяти
  data[0] = ds.read();// Чтение памяти byte low
  data[1] = ds.read();// Чтение памяти byte high
  float value = ((data[1] << 8) | data[0]) / 16.0; return (float)value; // Расчет температуры и вывод
}   

void to_Timer(){newPosition = myEnc.read()/4;}     

4

Re: Терморегулятор с тремя реле

Добавлены часы DS1302

Нажать на кнопку SET_TIME один раз для корректировки часов, два раза для корректировки минут

Часы начинают показывать после 20 секунд не активности органов управления.

На индикатор выводятся часы минуты и секунды, а так же текущая температура

http://forum.rcl-radio.ru/uploads/images/2022/01/fb4400f9c87c3cc1726ba976bb59c9b1.png


http://forum.rcl-radio.ru/uploads/images/2021/12/3cde620034d914be1d76f6761aff379a.png


#include <LiquidCrystal_I2C.h>  // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
#include <OneWire.h>            // http://rcl-radio.ru/wp-content/uploads/2018/07/OneWire.zip
#include <Wire.h>
#include <Encoder.h>            // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip       
#include <EEPROM.h>
#include <MsTimer2.h>           // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip 
#include <iarduino_RTC.h>       // http://rcl-radio.ru/wp-content/uploads/2019/10/iarduino_RTC.zip
 LiquidCrystal_I2C lcd(0x27,16,2);
 Encoder myEnc(8, 9);// DT, CLK
 OneWire  ds(2); // Вход датчика 18b20
 iarduino_RTC time(RTC_DS1302, 11, 12, 13); // RST, CLK, DAT
 byte v1[8] = {0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07};
 byte v2[8] = {0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00};      
 byte v3[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F};
 byte v4[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x1F,0x1F};
 byte v5[8] = {0x1C,0x1C,0x00,0x00,0x00,0x00,0x1C,0x1C};
 byte v6[8] = {0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C};
 byte v7[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07};
 byte v8[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00};
 byte d1,d2,d3,d4,d5,d6,e1,e2,e3;
 int a[6],x,menu,t_ds;
 int reg_t1,reg_t2,reg_t3,gis,sec,min,set_time;
 unsigned long times,times1,oldPosition  = -999,newPosition,times_12, times_tim;
 bool w,nagrev1,nagrev2,nagrev3,err,w1;
 byte out1 = 5, out2 = 6, out3 = 7; 
 int hh,mm;

 void setup(){
  Wire.begin();lcd.init();lcd.backlight();Serial.begin(9600); time.begin();
  MsTimer2::set(1, to_Timer);MsTimer2::start();
  if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}// очистка памяти при первом включении
  lcd.createChar(1, v1);lcd.createChar(2, v2);lcd.createChar(3, v3);lcd.createChar(4, v4);
  lcd.createChar(5, v5);lcd.createChar(6, v6);lcd.createChar(7, v7);lcd.createChar(8, v8);
  // time.settime(0,51,20,28,12,21,2); // Записываем время в модуль: сек, мин, час, дата, месяц, год (2019 = 19), день недели (пон = 1).
  pinMode(10,INPUT);       // кнопка SW ENCODER 
  pinMode(3,INPUT_PULLUP); // KSD301 (второй вывод KSD301 на GND)
  pinMode(4,INPUT_PULLUP); // геркон (второй вывод геркона на GND)
  pinMode(A0,INPUT_PULLUP);// SET - настройка часов
  pinMode(out1,OUTPUT);       // выход реле 1
  pinMode(out2,OUTPUT);       // выход реле 2
  pinMode(out3,OUTPUT);       // выход реле 3
  
  reg_t1 = EEPROM.read(0);reg_t2 = EEPROM.read(1);reg_t3 = EEPROM.read(2);gis = EEPROM.read(3);
  digitalWrite(5,LOW);digitalWrite(6,LOW);digitalWrite(7,LOW);
  } 
  

void loop(){
  time.gettime(); 
//////////// SET TIME ////////////////////////////////////////////////////////////////////// 
  if(digitalRead(A0)==LOW){set_time++;menu=6;if(set_time>2){set_time=0;menu=0;}times1=millis();times_tim=millis();w=1;lcd.clear();delay(300);}
  if(menu==6){
    if(set_time==1){
     hh = time.Hours;
     mm = time.minutes;
     if(newPosition != oldPosition){oldPosition = newPosition;hh=hh+newPosition;myEnc.write(0);w1=1;
     newPosition=0;times1=millis();times_tim=millis();w=1;if(hh>23){hh=00;}if(hh<0){hh=0;}}
     if(w1==1){time.settime(0,mm,hh,28,12,21,2);w1=0;}
     lcd.setCursor(3,0);lcd.print("SET TIME HH"); 
     lcd.setCursor(6,1);lcd.print(hh/10);lcd.print(hh%10);lcd.print(":");lcd.print(mm/10);lcd.print(mm%10);     
     } 
    if(set_time==2){
     hh = time.Hours;
     mm = time.minutes;
     if(newPosition != oldPosition){oldPosition = newPosition;mm=mm+newPosition;myEnc.write(0);w1=1;
     newPosition=0;times1=millis();times_tim=millis();w=1;if(mm>59){mm=59;}if(mm<0){mm=0;}}
     if(w1==1){time.settime(0,mm,hh,28,12,21,2);w1=0;}
     lcd.setCursor(3,0);lcd.print("SET TIME MM"); 
     lcd.setCursor(6,1);;lcd.print(hh/10);lcd.print(hh%10);lcd.print(":");lcd.print(mm/10);lcd.print(mm%10);  
     }  
    }
 
////////////  TIME /////////////////////////////////////////////////////////////////////////    
    if(millis()-times_tim>20000){menu=5;times_tim=millis();} 
    if(menu==5){
     a[0]=time.Hours/10;
     a[1]=time.Hours%10;
     a[2]=time.minutes/10;
     a[3]=time.minutes%10;
   for(x=0;x<4;x++){
    switch(x){
        case 0: e1=0;e2=1,e3=2;break;
        case 1: e1=3,e2=4,e3=5;break;
        case 2: e1=7,e2=8,e3=9;break;
        case 3: e1=10,e2=11,e3=12;break;
   }digit();}
   lcd.setCursor(6,0);lcd.print(".");lcd.setCursor(6,1);lcd.print(".");
   lcd.setCursor(13,1);lcd.print(" ");lcd.print(time.seconds / 10);lcd.setCursor(15,1);lcd.print(time.seconds % 10);
   lcd.setCursor(13,0);lcd.print(" ");lcd.print(t_ds/100);lcd.setCursor(15,0);lcd.print(t_ds/10%10);
   }  
      
///////// BUTTON ////////////////////////  
  if(digitalRead(10)==LOW){menu++;if(menu>4){menu=0;}times1=millis();times_tim=millis();w=1;lcd.clear();delay(300);}
  
///////// READ TEMP /////////////////////////////////////////////
 if(millis()-times>1000){times=millis();t_ds = dsRead(0)*10;}// Измерять температуру 1 раз в секунду
///////// LCD BIG ///////////////////////////////////////////////
 if(menu==0){
     a[0]=t_ds/1000;
     a[1]=t_ds/100%10;
     a[2]=t_ds/10%10;
     a[3]=t_ds%10;
     if(t_ds<1000){a[0]=10;}
     if(t_ds<100){a[1]=10;}
   for(x=0;x<4;x++){
    switch(x){
        case 0: e1=0;e2=0,e3=1;break;
        case 1: e1=2,e2=3,e3=4;break;
        case 2: e1=5,e2=6,e3=7;break;
        case 3: e1=9,e2=10,e3=11;break;
   }digit();}
   lcd.setCursor(8,1);lcd.print(".");
   lcd.setCursor(12,1);lcd.print(char(223)); lcd.print("C"); 
   if(err==0){
   if(nagrev1==1){lcd.setCursor(13,0);lcd.print("H");}else{lcd.setCursor(13,0);lcd.print("L");}
   if(nagrev2==1){lcd.setCursor(14,0);lcd.print("H");}else{lcd.setCursor(14,0);lcd.print("L");}
   if(nagrev3==1){lcd.setCursor(15,0);lcd.print("H");}else{lcd.setCursor(15,0);lcd.print("L");}
   }else{lcd.setCursor(13,0);lcd.print("ERR");}
    }
/////// MENU 1 ////////////////////////////////////////////////////////////
  if(menu==1){
    if(newPosition != oldPosition){oldPosition = newPosition;reg_t1=reg_t1+newPosition;myEnc.write(0);
    newPosition=0;times1=millis();times_tim=millis();w=1;if(reg_t1>125){reg_t1=125;}if(reg_t1<0){reg_t1=0;}}

     a[0]=reg_t1/100;
     a[1]=reg_t1/10%10;
     a[2]=reg_t1%10;
     if(reg_t1<100){a[0]=10;}
     if(reg_t1<10){a[1]=10;}
   for(x=0;x<3;x++){
    switch(x){
        case 0: e1=0;e2=1,e3=2;break;
        case 1: e1=3,e2=4,e3=5;break;
        case 2: e1=6,e2=7,e3=8;break;
   }digit();}
   lcd.setCursor(12,0);lcd.print("T_1"); 
   lcd.setCursor(9,1);lcd.print(char(223)); lcd.print("C"); 
   }  
/////// MENU 2 ////////////////////////////////////////////////////////////
  if(menu==2){
    if(newPosition != oldPosition){oldPosition = newPosition;reg_t2=reg_t2+newPosition;myEnc.write(0);
    newPosition=0;times1=millis();times_tim=millis();w=1;if(reg_t2>125){reg_t2=125;}if(reg_t2<0){reg_t2=0;}}

     a[0]=reg_t2/100;
     a[1]=reg_t2/10%10;
     a[2]=reg_t2%10;
     if(reg_t2<100){a[0]=10;}
     if(reg_t2<10){a[1]=10;}
   for(x=0;x<3;x++){
    switch(x){
        case 0: e1=0;e2=1,e3=2;break;
        case 1: e1=3,e2=4,e3=5;break;
        case 2: e1=6,e2=7,e3=8;break;
   }digit();}
   lcd.setCursor(12,0);lcd.print("T_2"); 
   lcd.setCursor(9,1);lcd.print(char(223)); lcd.print("C"); 
   }    
/////// MENU 3 ////////////////////////////////////////////////////////////
  if(menu==3){
    if(newPosition != oldPosition){oldPosition = newPosition;reg_t3=reg_t3+newPosition;myEnc.write(0);
    newPosition=0;times1=millis();times_tim=millis();w=1;if(reg_t3>125){reg_t3=125;}if(reg_t3<0){reg_t3=0;}}

     a[0]=reg_t3/100;
     a[1]=reg_t3/10%10;
     a[2]=reg_t3%10;
     if(reg_t3<100){a[0]=10;}
     if(reg_t3<10){a[1]=10;}
   for(x=0;x<3;x++){
    switch(x){
        case 0: e1=0;e2=1,e3=2;break;
        case 1: e1=3,e2=4,e3=5;break;
        case 2: e1=6,e2=7,e3=8;break;
   }digit();}
   lcd.setCursor(12,0);lcd.print("T_3"); 
   lcd.setCursor(9,1);lcd.print(char(223)); lcd.print("C"); 
   } 
///////////// hysteresis ///////////////////////////////   
  if(menu==4){
    if(newPosition != oldPosition){oldPosition = newPosition;gis=gis+newPosition;myEnc.write(0);
    newPosition=0;times1=millis();w=1;if(gis<0){gis=0;}if(gis>30){gis=30;}}
    lcd.setCursor(3,0);lcd.print("hysteresis ");
    lcd.setCursor(5,1);lcd.print((float)gis/10,1);
    lcd.print(char(223)); lcd.print("C"); 
  }  
///////// EEPROM ////////////////////////////////////////////////
  if(millis()-times1>10000 && w==1){
   EEPROM.update(0,reg_t1);EEPROM.update(1,reg_t2);EEPROM.update(2,reg_t3);EEPROM.update(3,gis);
   menu=0;w=0;lcd.clear();} 
   
///////////////////////////////////////////////////////////////////
  if(millis()-times_12>1000){sec++;times_12=millis();if(sec>59){sec=0;min++;}}
  if(min<=720){
  out1 = 5;
  out2 = 6;
  out3 = 7;
  }
  if(min>720&&min<=1440){
  out1 = 6;
  out2 = 7;
  out3 = 5;
  }
  if(min>1440&&min<=2160){
  out1 = 7;
  out2 = 5;
  out3 = 6;
  }
  if(min>2160){min=0;}
///////////////////////////////////////////////////////////////////
  if(digitalRead(4)==LOW&&digitalRead(3)==LOW){
  err=0;  
  if(reg_t1*10 >= t_ds + gis){digitalWrite(out1,HIGH);nagrev1=1;}
  if(reg_t1*10 <= t_ds - gis){digitalWrite(out1,LOW);nagrev1=0;}   

  if(reg_t2*10 >= t_ds + gis){digitalWrite(out2,HIGH);nagrev2=1;}
  if(reg_t2*10 <= t_ds - gis){digitalWrite(out2,LOW);nagrev2=0;} 

  if(reg_t3*10 >= t_ds + gis){digitalWrite(out3,HIGH);nagrev3=1;}
  if(reg_t3*10 <= t_ds - gis){digitalWrite(out3,LOW);nagrev3=0;}
  }
  else{digitalWrite(out1,LOW);digitalWrite(out2,LOW);digitalWrite(out3,LOW);err=1;}
 // Serial.print(reg_t1*10);  Serial.print(" ");  Serial.print(t_ds);  Serial.print(" ");  Serial.print(gis);  Serial.print(" ");  Serial.println(err);               
}// end loop

void digit(){
  switch(a[x]){
    case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
    case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
    case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
    case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
    case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
    case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
    case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
    case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
    case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    case 10:d1=150,d2=150,d3=150,d4=150,d5=150,d6=150;break;
    }
lcd.setCursor(e1,0);lcd.write((uint8_t)d1);
lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);lcd.setCursor(e1,1);
lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);} 

float dsRead(byte x) {
  byte data[2], addr[8][8], kol = 0;
  while (ds.search(addr[kol])) {  // поиск датчиков, определение адреса и кол-ва датчиков
    kol++;
  } 
  ds.reset_search();  // Сброс поиска датчика
  ds.reset();         // Инициализация, выполняется сброс шины
  ds.select(addr[x]); // Обращение к датчику по адресу
  ds.write(0x44, 0);  // Измерение температуры с переносом данных в память
  ds.reset();         // Инициализация, выполняется сброс шины
  ds.select(addr[x]); // Обращение к датчику по адресу
  ds.write(0xBE);     // Обращение памяти
  data[0] = ds.read();// Чтение памяти byte low
  data[1] = ds.read();// Чтение памяти byte high
  float value = ((data[1] << 8) | data[0]) / 16.0; return (float)value; // Расчет температуры и вывод
}   

void to_Timer(){newPosition = myEnc.read()/4;}     

5

Re: Терморегулятор с тремя реле

http://forum.rcl-radio.ru/uploads/images/2022/01/170c616d9a5b26fa6e1a8a5d5605be05.png


#include <LiquidCrystal_I2C.h>  // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
#include <OneWire.h>            // http://rcl-radio.ru/wp-content/uploads/2018/07/OneWire.zip
#include <Wire.h>
#include <Encoder.h>            // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip       
#include <EEPROM.h>
#include <MsTimer2.h>           // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip 
#include <iarduino_RTC.h>       // http://rcl-radio.ru/wp-content/uploads/2019/10/iarduino_RTC.zip
 LiquidCrystal_I2C lcd(0x27,16,2);
 Encoder myEnc(8, 9);// DT, CLK
 OneWire  ds(2); // Вход датчика 18b20
 iarduino_RTC time(RTC_DS1302, 11, 12, 13); // RST, CLK, DAT
 byte v1[8] = {0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07};
 byte v2[8] = {0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00};      
 byte v3[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F};
 byte v4[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x1F,0x1F};
 byte v5[8] = {0x1C,0x1C,0x00,0x00,0x00,0x00,0x1C,0x1C};
 byte v6[8] = {0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C};
 byte v7[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07};
 byte v8[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00};
 byte d1,d2,d3,d4,d5,d6,e1,e2,e3;
 int a[6],x,menu,t_ds;
 int reg_t1,reg_t2,reg_t3,gis,sec,min,set_time;
 unsigned long times,times1,oldPosition  = -999,newPosition,times_12, times_tim;
 bool w,nagrev1,nagrev2,nagrev3,err,w1;
 byte out1 = 5, out2 = 6, out3 = 7; 
 int hh,mm;

 void setup(){
  Wire.begin();lcd.init();lcd.backlight();Serial.begin(9600); time.begin();
  MsTimer2::set(1, to_Timer);MsTimer2::start();
  if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}// очистка памяти при первом включении
  lcd.createChar(1, v1);lcd.createChar(2, v2);lcd.createChar(3, v3);lcd.createChar(4, v4);
  lcd.createChar(5, v5);lcd.createChar(6, v6);lcd.createChar(7, v7);lcd.createChar(8, v8);
  // time.settime(0,51,20,28,12,21,2); // Записываем время в модуль: сек, мин, час, дата, месяц, год (2019 = 19), день недели (пон = 1).
  pinMode(10,INPUT);       // кнопка SW ENCODER 
  pinMode(3,INPUT_PULLUP); // KSD301 (второй вывод KSD301 на GND)
  pinMode(4,INPUT_PULLUP); // геркон (второй вывод геркона на GND)
  pinMode(A0,INPUT_PULLUP);// SET - настройка часов
  pinMode(out1,OUTPUT);       // выход реле 1
  pinMode(out2,OUTPUT);       // выход реле 2
  pinMode(out3,OUTPUT);       // выход реле 3
  pinMode(A1,OUTPUT);  // BUZZER
  
  reg_t1 = EEPROM.read(0);reg_t2 = EEPROM.read(1);reg_t3 = EEPROM.read(2);gis = EEPROM.read(3);
  digitalWrite(5,LOW);digitalWrite(6,LOW);digitalWrite(7,LOW);
  } 
  

void loop(){
  time.gettime(); 
//////////// SET TIME ////////////////////////////////////////////////////////////////////// 
  if(digitalRead(A0)==LOW){set_time++;menu=6;if(set_time>2){set_time=0;menu=0;}times1=millis();times_tim=millis();w=1;lcd.clear();delay(300);}
  if(menu==6){
    if(set_time==1){
     hh = time.Hours;
     mm = time.minutes;
     if(newPosition != oldPosition){oldPosition = newPosition;hh=hh+newPosition;myEnc.write(0);w1=1;
     newPosition=0;times1=millis();times_tim=millis();w=1;if(hh>23){hh=00;}if(hh<0){hh=0;}}
     if(w1==1){time.settime(0,mm,hh,28,12,21,2);w1=0;}
     lcd.setCursor(3,0);lcd.print("SET TIME HH"); 
     lcd.setCursor(6,1);lcd.print(hh/10);lcd.print(hh%10);lcd.print(":");lcd.print(mm/10);lcd.print(mm%10);     
     } 
    if(set_time==2){
     hh = time.Hours;
     mm = time.minutes;
     if(newPosition != oldPosition){oldPosition = newPosition;mm=mm+newPosition;myEnc.write(0);w1=1;
     newPosition=0;times1=millis();times_tim=millis();w=1;if(mm>59){mm=59;}if(mm<0){mm=0;}}
     if(w1==1){time.settime(0,mm,hh,28,12,21,2);w1=0;}
     lcd.setCursor(3,0);lcd.print("SET TIME MM"); 
     lcd.setCursor(6,1);;lcd.print(hh/10);lcd.print(hh%10);lcd.print(":");lcd.print(mm/10);lcd.print(mm%10);  
     }  
    }
 
////////////  TIME /////////////////////////////////////////////////////////////////////////    
    if(millis()-times_tim>20000){menu=5;times_tim=millis();} 
    if(menu==5){
     a[0]=time.Hours/10;
     a[1]=time.Hours%10;
     a[2]=time.minutes/10;
     a[3]=time.minutes%10;
   for(x=0;x<4;x++){
    switch(x){
        case 0: e1=0;e2=1,e3=2;break;
        case 1: e1=3,e2=4,e3=5;break;
        case 2: e1=7,e2=8,e3=9;break;
        case 3: e1=10,e2=11,e3=12;break;
   }digit();}
   lcd.setCursor(6,0);lcd.print(".");lcd.setCursor(6,1);lcd.print(".");
   lcd.setCursor(13,1);lcd.print(" ");lcd.print(time.seconds / 10);lcd.setCursor(15,1);lcd.print(time.seconds % 10);
   lcd.setCursor(13,0);lcd.print(" ");lcd.print(t_ds/100);lcd.setCursor(15,0);lcd.print(t_ds/10%10);
   }  
      
///////// BUTTON ////////////////////////  
  if(digitalRead(10)==LOW){menu++;if(menu>4){menu=0;}times1=millis();times_tim=millis();w=1;lcd.clear();delay(300);}
  
///////// READ TEMP /////////////////////////////////////////////
 if(millis()-times>1000){times=millis();t_ds = dsRead(0)*10;}// Измерять температуру 1 раз в секунду
///////// LCD BIG ///////////////////////////////////////////////
 if(menu==0){
     a[0]=t_ds/1000;
     a[1]=t_ds/100%10;
     a[2]=t_ds/10%10;
     a[3]=t_ds%10;
     if(t_ds<1000){a[0]=10;}
     if(t_ds<100){a[1]=10;}
   for(x=0;x<4;x++){
    switch(x){
        case 0: e1=0;e2=0,e3=1;break;
        case 1: e1=2,e2=3,e3=4;break;
        case 2: e1=5,e2=6,e3=7;break;
        case 3: e1=9,e2=10,e3=11;break;
   }digit();}
   lcd.setCursor(8,1);lcd.print(".");
   lcd.setCursor(12,1);lcd.print(char(223)); lcd.print("C"); 
   if(err==0){
   if(nagrev1==1){lcd.setCursor(13,0);lcd.print("H");}else{lcd.setCursor(13,0);lcd.print("L");}
   if(nagrev2==1){lcd.setCursor(14,0);lcd.print("H");}else{lcd.setCursor(14,0);lcd.print("L");}
   if(nagrev3==1){lcd.setCursor(15,0);lcd.print("H");}else{lcd.setCursor(15,0);lcd.print("L");}
   }else{lcd.setCursor(13,0);lcd.print("ERR");}
    }
/////// MENU 1 ////////////////////////////////////////////////////////////
  if(menu==1){
    if(newPosition != oldPosition){oldPosition = newPosition;reg_t1=reg_t1+newPosition;myEnc.write(0);
    newPosition=0;times1=millis();times_tim=millis();w=1;if(reg_t1>125){reg_t1=125;}if(reg_t1<0){reg_t1=0;}}

     a[0]=reg_t1/100;
     a[1]=reg_t1/10%10;
     a[2]=reg_t1%10;
     if(reg_t1<100){a[0]=10;}
     if(reg_t1<10){a[1]=10;}
   for(x=0;x<3;x++){
    switch(x){
        case 0: e1=0;e2=1,e3=2;break;
        case 1: e1=3,e2=4,e3=5;break;
        case 2: e1=6,e2=7,e3=8;break;
   }digit();}
   lcd.setCursor(12,0);lcd.print("T_1"); 
   lcd.setCursor(9,1);lcd.print(char(223)); lcd.print("C"); 
   }  
/////// MENU 2 ////////////////////////////////////////////////////////////
  if(menu==2){
    if(newPosition != oldPosition){oldPosition = newPosition;reg_t2=reg_t2+newPosition;myEnc.write(0);
    newPosition=0;times1=millis();times_tim=millis();w=1;if(reg_t2>125){reg_t2=125;}if(reg_t2<0){reg_t2=0;}}

     a[0]=reg_t2/100;
     a[1]=reg_t2/10%10;
     a[2]=reg_t2%10;
     if(reg_t2<100){a[0]=10;}
     if(reg_t2<10){a[1]=10;}
   for(x=0;x<3;x++){
    switch(x){
        case 0: e1=0;e2=1,e3=2;break;
        case 1: e1=3,e2=4,e3=5;break;
        case 2: e1=6,e2=7,e3=8;break;
   }digit();}
   lcd.setCursor(12,0);lcd.print("T_2"); 
   lcd.setCursor(9,1);lcd.print(char(223)); lcd.print("C"); 
   }    
/////// MENU 3 ////////////////////////////////////////////////////////////
  if(menu==3){
    if(newPosition != oldPosition){oldPosition = newPosition;reg_t3=reg_t3+newPosition;myEnc.write(0);
    newPosition=0;times1=millis();times_tim=millis();w=1;if(reg_t3>125){reg_t3=125;}if(reg_t3<0){reg_t3=0;}}

     a[0]=reg_t3/100;
     a[1]=reg_t3/10%10;
     a[2]=reg_t3%10;
     if(reg_t3<100){a[0]=10;}
     if(reg_t3<10){a[1]=10;}
   for(x=0;x<3;x++){
    switch(x){
        case 0: e1=0;e2=1,e3=2;break;
        case 1: e1=3,e2=4,e3=5;break;
        case 2: e1=6,e2=7,e3=8;break;
   }digit();}
   lcd.setCursor(12,0);lcd.print("T_3"); 
   lcd.setCursor(9,1);lcd.print(char(223)); lcd.print("C"); 
   } 
///////////// hysteresis ///////////////////////////////   
  if(menu==4){
    if(newPosition != oldPosition){oldPosition = newPosition;gis=gis+newPosition;myEnc.write(0);
    newPosition=0;times1=millis();w=1;if(gis<0){gis=0;}if(gis>30){gis=30;}}
    lcd.setCursor(3,0);lcd.print("hysteresis ");
    lcd.setCursor(5,1);lcd.print((float)gis/10,1);
    lcd.print(char(223)); lcd.print("C"); 
  }  
///////// EEPROM ////////////////////////////////////////////////
  if(millis()-times1>10000 && w==1){
   EEPROM.update(0,reg_t1);EEPROM.update(1,reg_t2);EEPROM.update(2,reg_t3);EEPROM.update(3,gis);
   menu=0;w=0;lcd.clear();} 
   
///////////////////////////////////////////////////////////////////
  if(millis()-times_12>1000){sec++;times_12=millis();if(sec>59){sec=0;min++;}}
  if(min<=720){
  out1 = 5;
  out2 = 6;
  out3 = 7;
  }
  if(min>720&&min<=1440){
  out1 = 6;
  out2 = 7;
  out3 = 5;
  }
  if(min>1440&&min<=2160){
  out1 = 7;
  out2 = 5;
  out3 = 6;
  }
  if(min>2160){min=0;}
///////////////////////////////////////////////////////////////////
  if(digitalRead(4)==LOW&&digitalRead(3)==LOW){
  err=0;  
  if(reg_t1*10 >= t_ds + gis){digitalWrite(out1,HIGH);nagrev1=1;}
  if(reg_t1*10 <= t_ds - gis){digitalWrite(out1,LOW);nagrev1=0;}   

  if(reg_t2*10 >= t_ds + gis){digitalWrite(out2,HIGH);nagrev2=1;}
  if(reg_t2*10 <= t_ds - gis){digitalWrite(out2,LOW);nagrev2=0;} 

  if(reg_t3*10 >= t_ds + gis){digitalWrite(out3,HIGH);nagrev3=1;}
  if(reg_t3*10 <= t_ds - gis){digitalWrite(out3,LOW);nagrev3=0;}
  }
  else{digitalWrite(out1,LOW);digitalWrite(out2,LOW);digitalWrite(out3,LOW);err=1;
  buzzer();}
 // Serial.print(reg_t1*10);  Serial.print(" ");  Serial.print(t_ds);  Serial.print(" ");  Serial.print(gis);  Serial.print(" ");  Serial.println(err);               
}// end loop

void buzzer(){
  for(int buz=0;buz<500;buz++){
  digitalWrite(A1,HIGH);
  delayMicroseconds(500);
  digitalWrite(A1,LOW);
  delayMicroseconds(500);}
  delay(100);
  }

void digit(){
  switch(a[x]){
    case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
    case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
    case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
    case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
    case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
    case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
    case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
    case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
    case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    case 10:d1=150,d2=150,d3=150,d4=150,d5=150,d6=150;break;
    }
lcd.setCursor(e1,0);lcd.write((uint8_t)d1);
lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);lcd.setCursor(e1,1);
lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);} 

float dsRead(byte x) {
  byte data[2], addr[8][8], kol = 0;
  while (ds.search(addr[kol])) {  // поиск датчиков, определение адреса и кол-ва датчиков
    kol++;
  } 
  ds.reset_search();  // Сброс поиска датчика
  ds.reset();         // Инициализация, выполняется сброс шины
  ds.select(addr[x]); // Обращение к датчику по адресу
  ds.write(0x44, 0);  // Измерение температуры с переносом данных в память
  ds.reset();         // Инициализация, выполняется сброс шины
  ds.select(addr[x]); // Обращение к датчику по адресу
  ds.write(0xBE);     // Обращение памяти
  data[0] = ds.read();// Чтение памяти byte low
  data[1] = ds.read();// Чтение памяти byte high
  float value = ((data[1] << 8) | data[0]) / 16.0; return (float)value; // Расчет температуры и вывод
}   

void to_Timer(){newPosition = myEnc.read()/4;}   

6

Re: Терморегулятор с тремя реле

Александр доброго дня, вопрос по схеме с первого поста, возможно ли убрать датчики d3, d4., а на их место добавить ещё по одному 18b20, то есть в схеме будет 3 датчика температуры и три реле, каждое реле от своего датчика температуры?

7

Re: Терморегулятор с тремя реле

Все три датчика температуры можно подключить к одному пину. Датчики на пинах D3 D4 являются элементами защиты.

8 (2023-07-22 14:04:21 отредактировано peregar78)

Re: Терморегулятор с тремя реле

. Доброго дня, дело в том, что каждый датчик должен отвечать за свое реле., эта установка реализовывается под тёплый пол сразу в трех комнатах

9

Re: Терморегулятор с тремя реле

Как выводить показания трех датчиков, большие цифры не подойдут.

10

Re: Терморегулятор с тремя реле

1.temp=26.        T. on=20.      T. of=42.
2.temp=25
3.temp=25.        T. on=20.      T. of=42.
Примерно так, если поставить 2004 дисплей с i2s переходником.

11

Re: Терморегулятор с тремя реле

Протестируйте регулировку и показания датчиков температуры, реле пока не активны

LCD2004

#include <LiquidCrystal_I2C.h>  // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
#include <OneWire.h>            // http://rcl-radio.ru/wp-content/uploads/2018/07/OneWire.zip
#include <Wire.h>
#include <Encoder.h>            // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip       
#include <EEPROM.h>
#include <MsTimer2.h>           // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip 
 LiquidCrystal_I2C lcd(0x27,20,4);
 Encoder myEnc(9, 8);// DT, CLK
 OneWire  ds1(2); // Вход датчика 18b20
 OneWire  ds2(3); // Вход датчика 18b20
 OneWire  ds3(4); // Вход датчика 18b20

 int reg_t1,reg_t2,reg_t3,gis;
 unsigned long times,times1,oldPosition  = -999,newPosition;
 bool w,nagrev1,nagrev2,nagrev3,err;
 
 byte mesto2[8]={8,14,8,14,8,14,8,14};
 byte mesto3[8]={0,0,1,1,2,2,3,3};
 int menu1,t1_reg_on,t1_reg_of,t2_reg_on,t2_reg_of,t3_reg_on,t3_reg_of,t_reg;
 float t_ds1,t_ds2,t_ds3;

 void setup(){
  Wire.begin();lcd.init();lcd.backlight();Serial.begin(9600);
  MsTimer2::set(1, to_Timer);MsTimer2::start();
  if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}// очистка памяти при первом включении
  pinMode(10,INPUT);       // кнопка SW ENCODER 
  pinMode(5,OUTPUT);       // выход реле 1
  pinMode(6,OUTPUT);       // выход реле 2
  pinMode(7,OUTPUT);       // выход реле 3
   byte a1[8] = {0b00000,0b10101,0b10101,0b10101,0b10101,0b10101,0b10101,0b00000};
   byte a2[8] = {0b00000,0b10100,0b10100,0b10100,0b10100,0b10100,0b10100,0b00000};
   byte a3[8] = {0b00000,0b10000,0b10000,0b10000,0b10000,0b10000,0b10000,0b00000}; 
   byte a4[8] = {0b10000,0b11000,0b11100,0b11110,0b11100,0b11000,0b10000,0b00000}; //>
   byte a5[8] = {0b00000,0b00000,0b00000,0b00000,0b00000,0b00000,0b00000,0b00000};
   lcd.createChar(0,a1);lcd.createChar(1,a2);lcd.createChar(2,a3);lcd.createChar(3,a4);lcd.createChar(4,a5);
  
  t1_reg_on = EEPROM.read(0);t1_reg_of = EEPROM.read(1);
  t2_reg_on = EEPROM.read(2);t2_reg_of = EEPROM.read(3);
  t3_reg_on = EEPROM.read(4);t3_reg_of = EEPROM.read(5);
  
  digitalWrite(5,LOW);digitalWrite(6,LOW);digitalWrite(7,LOW);
  } 
  

void loop(){
///////// BUTTON ////////////////////////  
  if(digitalRead(10)==LOW){menu1++;if(menu1>6){menu1=0;}times1=millis();w=1;delay(300);}
 // t_ds1 = 22.567;
 // t_ds2 = 28.567;
 // t_ds3 = 23.567;
///////// READ TEMP /////////////////////////////////////////////
 if(millis()-times>1000){times=millis();t_ds1 = dsRead1(0);t_ds2 = dsRead2(0);t_ds3 = dsRead3(0);}// Измерять температуру 1 раз в секунду
///////// LCD BIG ///////////////////////////////////////////////
   switch(menu1){
      case 0: t_reg = t1_reg_on;break;
      case 1: t_reg = t1_reg_of;break;
      case 2: t_reg = t2_reg_on;break;
      case 3: t_reg = t2_reg_of;break;
      case 4: t_reg = t3_reg_on;break;
      case 5: t_reg = t3_reg_of;break;
      }
   
 if(newPosition!=oldPosition){oldPosition=newPosition;t_reg=t_reg+newPosition;myEnc.write(0);newPosition=0;times1=millis();w=1;if(t_reg>99){t_reg=99;}if(t_reg<0){t_reg=0;}}

  switch(menu1){
      case 0: t1_reg_on = t_reg;break;
      case 1: t1_reg_of = t_reg;break;
      case 2: t2_reg_on = t_reg;break;
      case 3: t2_reg_of = t_reg;break;      
      case 4: t3_reg_on  = t_reg;break;
      case 5: t3_reg_of  = t_reg;break;
      }

  lcd.setCursor(0,0);lcd.print("T1=");lcd.print(t_ds1,1);
  lcd.setCursor(0,1);lcd.print("T2=");lcd.print(t_ds2,1);
  lcd.setCursor(0,2);lcd.print("T3=");lcd.print(t_ds3,1);
  for(int i=0;i<8;i++){if(menu1==i){lcd.setCursor(mesto2[i],mesto3[i]);lcd.write((uint8_t)3);}else{lcd.setCursor(mesto2[i],mesto3[i]);lcd.print(" ");}}
  lcd.setCursor(9,0);lcd.print("on=");lcd.print(t1_reg_on);lcd.setCursor(15,0);lcd.print("of=");lcd.print(t1_reg_of);
  lcd.setCursor(9,1);lcd.print("on=");lcd.print(t2_reg_on);lcd.setCursor(15,1);lcd.print("of=");lcd.print(t2_reg_of);
  lcd.setCursor(9,2);lcd.print("on=");lcd.print(t3_reg_on);lcd.setCursor(15,2);lcd.print("of=");lcd.print(t3_reg_of);
  
  
    


///////// EEPROM ////////////////////////////////////////////////
  if(millis()-times1>10000 && w==1){
   EEPROM.update(0,t1_reg_on);EEPROM.update(1,t1_reg_of);
   EEPROM.update(2,t2_reg_on);EEPROM.update(3,t2_reg_of);
   EEPROM.update(4,t3_reg_on);EEPROM.update(5,t3_reg_of);
   w=0;lcd.clear();} 
///////////////////////////////////////////////////////////////////
 

  if(reg_t1*10 >= t_ds1 + gis){digitalWrite(5,HIGH);nagrev1=1;}
  if(reg_t1*10 <= t_ds1 - gis){digitalWrite(5,LOW);nagrev1=0;}   

  if(reg_t2*10 >= t_ds2 + gis){digitalWrite(6,HIGH);nagrev2=1;}
  if(reg_t2*10 <= t_ds2 - gis){digitalWrite(6,LOW);nagrev2=0;} 

  if(reg_t3*10 >= t_ds3 + gis){digitalWrite(7,HIGH);nagrev3=1;}
  if(reg_t3*10 <= t_ds3 - gis){digitalWrite(7,LOW);nagrev3=0;}
                
}// end loop


float dsRead1(byte x) {
  byte data[2], addr[8][8], kol = 0;
  while (ds1.search(addr[kol])) {  // поиск датчиков, определение адреса и кол-ва датчиков
    kol++;
  } 
  ds1.reset_search();  // Сброс поиска датчика
  ds1.reset();         // Инициализация, выполняется сброс шины
  ds1.select(addr[x]); // Обращение к датчику по адресу
  ds1.write(0x44, 0);  // Измерение температуры с переносом данных в память
  ds1.reset();         // Инициализация, выполняется сброс шины
  ds1.select(addr[x]); // Обращение к датчику по адресу
  ds1.write(0xBE);     // Обращение памяти
  data[0] = ds1.read();// Чтение памяти byte low
  data[1] = ds1.read();// Чтение памяти byte high
  float value = ((data[1] << 8) | data[0]) / 16.0; return (float)value; // Расчет температуры и вывод
}  

 float dsRead2(byte x) {
  byte data[2], addr[8][8], kol = 0;
  while (ds2.search(addr[kol])) {  // поиск датчиков, определение адреса и кол-ва датчиков
    kol++;
  } 
  ds2.reset_search();  // Сброс поиска датчика
  ds2.reset();         // Инициализация, выполняется сброс шины
  ds2.select(addr[x]); // Обращение к датчику по адресу
  ds2.write(0x44, 0);  // Измерение температуры с переносом данных в память
  ds2.reset();         // Инициализация, выполняется сброс шины
  ds2.select(addr[x]); // Обращение к датчику по адресу
  ds2.write(0xBE);     // Обращение памяти
  data[0] = ds2.read();// Чтение памяти byte low
  data[1] = ds2.read();// Чтение памяти byte high
  float value = ((data[1] << 8) | data[0]) / 16.0; return (float)value; // Расчет температуры и вывод
}  

 float dsRead3(byte x) {
  byte data[2], addr[8][8], kol = 0;
  while (ds3.search(addr[kol])) {  // поиск датчиков, определение адреса и кол-ва датчиков
    kol++;
  } 
  ds3.reset_search();  // Сброс поиска датчика
  ds3.reset();         // Инициализация, выполняется сброс шины
  ds3.select(addr[x]); // Обращение к датчику по адресу
  ds3.write(0x44, 0);  // Измерение температуры с переносом данных в память
  ds3.reset();         // Инициализация, выполняется сброс шины
  ds3.select(addr[x]); // Обращение к датчику по адресу
  ds3.write(0xBE);     // Обращение памяти
  data[0] = ds3.read();// Чтение памяти byte low
  data[1] = ds3.read();// Чтение памяти byte high
  float value = ((data[1] << 8) | data[0]) / 16.0; return (float)value; // Расчет температуры и вывод
} 

void to_Timer(){newPosition = myEnc.read()/4;}  

12

Re: Терморегулятор с тремя реле

Уточните алгоритм работы реле, у Вас темп.вкл и темп.выкл, как должно работать реле?

13

Re: Терморегулятор с тремя реле

Доброго дня, я протестировал работу датчиков и регулировка температуры, алгоритм работы :датчик на пине d2 управляет первым реле выставляем температуру например 25 град. Включить  реле начинается нагрев, доходит например до 42 градусов, выключить реле. Гистерезис регулируемый до 5 градусов. Датчик на пине d3 и d4 такой же алгоритм работы.

14

Re: Терморегулятор с тремя реле

темп отк заменить на гистерезис, а тем вкл заменить на темп регуирования?

15

Re: Терморегулятор с тремя реле

Есть другой вариант

например установлено темп вкл 25, тем откл 32

при включении греет до 32, отключается, остывает до 25 - включается, снова греет до 32 и снова остывает до 25, и повтор нагрева

16

Re: Терморегулятор с тремя реле

Фото не могу скинуть, скорее всего желательно все оставить как есть, а гистерезис на четвертую строку поместить и сделать общим для всех датчиков

17

Re: Терморегулятор с тремя реле

T1=40.3  T1reg=45 R1_ON
T2=34.5  T2reg=30 R2_OFF
T3=28.7  T3reg=40 R3_ON
GIS = 4

температура темп.рег. состояние реле

18

Re: Терморегулятор с тремя реле

фото отправил на почту

19

Re: Терморегулятор с тремя реле

Нужна регулировка по асем трём каналам температуры включения и температуры выключения

20

Re: Терморегулятор с тремя реле

Фото посмотрел, я тестирую в железе, только датчиков темп. нет.

сделать как http://forum.rcl-radio.ru/viewtopic.php?pid=8042#p8042 ?

четвертая строка - состояние реле

21

Re: Терморегулятор с тремя реле

Да как в посте 15,гистерезис не нужен, я просто сам глупанул, но с возможностью выставления температуры от минимума до максимума предел (15-45) градусов.

22

Re: Терморегулятор с тремя реле

У меня все почти готово, как Вы мне написали, только скетч дома, не опубликован. вечером опубликую.

23

Re: Терморегулятор с тремя реле

#include <LiquidCrystal_I2C.h>  // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
#include <OneWire.h>            // http://rcl-radio.ru/wp-content/uploads/2018/07/OneWire.zip
#include <Wire.h>
#include <Encoder.h>            // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip       
#include <EEPROM.h>
#include <MsTimer2.h>           // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip 
 LiquidCrystal_I2C lcd(0x27,20,4);
 Encoder myEnc(9, 8);// DT, CLK
 OneWire  ds1(2); // Вход датчика 18b20
 OneWire  ds2(3); // Вход датчика 18b20
 OneWire  ds3(4); // Вход датчика 18b20

 unsigned long times,times1,oldPosition  = -999,newPosition;
 bool w,nagrev1,nagrev2,nagrev3;
 byte a4[8] = {0b10000,0b11000,0b11100,0b11110,0b11100,0b11000,0b10000,0b00000}; //>
 byte mesto2[8]={8,14,8,14,8,14};
 byte mesto3[8]={0,0,1,1,2,2};
 int menu1,t1_reg_on,t1_reg_of,t2_reg_on,t2_reg_of,t3_reg_on,t3_reg_of,t_reg;
 float t_ds1,t_ds2,t_ds3;
 bool n1,n2,n3;

 void setup(){
  Wire.begin();lcd.init();lcd.backlight();Serial.begin(9600);
  MsTimer2::set(1, to_Timer);MsTimer2::start();
  if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}// очистка памяти при первом включении
  pinMode(10,INPUT);       // кнопка SW ENCODER 
  pinMode(5,OUTPUT);       // выход реле 1
  pinMode(6,OUTPUT);       // выход реле 2
  pinMode(7,OUTPUT);       // выход реле 3
  lcd.createChar(3,a4);
  t1_reg_on = EEPROM.read(0);t1_reg_of = EEPROM.read(1);
  t2_reg_on = EEPROM.read(2);t2_reg_of = EEPROM.read(3);
  t3_reg_on = EEPROM.read(4);t3_reg_of = EEPROM.read(5);
  digitalWrite(5,LOW);digitalWrite(6,LOW);digitalWrite(7,LOW);
  } 
  
void loop(){
///////// BUTTON ////////////////////////  
  if(digitalRead(10)==LOW){menu1++;if(menu1>5){menu1=0;}times1=millis();w=1;delay(300);}
 // t_ds1 = 22.567;
 // t_ds2 = 28.567;
 // t_ds3 = 23.567;
///////// READ TEMP /////////////////////////////////////////////
 if(millis()-times>1000){times=millis();t_ds1 = dsRead1(0);t_ds2 = dsRead2(0);t_ds3 = dsRead3(0);}// Измерять температуру 1 раз в секунду
///////// LCD BIG ///////////////////////////////////////////////
   switch(menu1){
      case 0: t_reg = t1_reg_on;break;
      case 1: t_reg = t1_reg_of;break;
      case 2: t_reg = t2_reg_on;break;
      case 3: t_reg = t2_reg_of;break;
      case 4: t_reg = t3_reg_on;break;
      case 5: t_reg = t3_reg_of;break;
      }
   
 if(newPosition!=oldPosition){oldPosition=newPosition;t_reg=t_reg+newPosition;myEnc.write(0);newPosition=0;times1=millis();w=1;if(t_reg>99){t_reg=99;}if(t_reg<0){t_reg=0;}}

  switch(menu1){
      case 0: t1_reg_on = t_reg;break;
      case 1: t1_reg_of = t_reg;break;
      case 2: t2_reg_on = t_reg;break;
      case 3: t2_reg_of = t_reg;break;      
      case 4: t3_reg_on = t_reg;break;
      case 5: t3_reg_of = t_reg;break;
      }

  lcd.setCursor(0,0);lcd.print("T1=");lcd.print(t_ds1,1);
  lcd.setCursor(0,1);lcd.print("T2=");lcd.print(t_ds2,1);
  lcd.setCursor(0,2);lcd.print("T3=");lcd.print(t_ds3,1);
  for(int i=0;i<6;i++){if(menu1==i){lcd.setCursor(mesto2[i],mesto3[i]);lcd.write((uint8_t)3);}else{lcd.setCursor(mesto2[i],mesto3[i]);lcd.print(" ");}}
  lcd.setCursor(9,0);lcd.print("on=");lcd.print(t1_reg_on);lcd.setCursor(15,0);lcd.print("of=");lcd.print(t1_reg_of);
  lcd.setCursor(9,1);lcd.print("on=");lcd.print(t2_reg_on);lcd.setCursor(15,1);lcd.print("of=");lcd.print(t2_reg_of);
  lcd.setCursor(9,2);lcd.print("on=");lcd.print(t3_reg_on);lcd.setCursor(15,2);lcd.print("of=");lcd.print(t3_reg_of);
  
  if(nagrev1==1){lcd.setCursor(0,3);lcd.print("R1_ON ");}else{lcd.setCursor(0,3);lcd.print("R1_OFF");}
  if(nagrev2==1){lcd.setCursor(7,3);lcd.print("R2_ON ");}else{lcd.setCursor(7,3);lcd.print("R2_OFF");}
  if(nagrev3==1){lcd.setCursor(14,3);lcd.print("R3_ON ");}else{lcd.setCursor(14,3);lcd.print("R3_OFF");}

///////// EEPROM ////////////////////////////////////////////////
  if(millis()-times1>10000 && w==1){
   EEPROM.update(0,t1_reg_on);EEPROM.update(1,t1_reg_of);
   EEPROM.update(2,t2_reg_on);EEPROM.update(3,t2_reg_of);
   EEPROM.update(4,t3_reg_on);EEPROM.update(5,t3_reg_of);
   w=0;lcd.clear();} 
///////////////////////////////////////////////////////////////////
 
  if(t_ds1 <= t1_reg_on){n1=1;digitalWrite(5,HIGH);nagrev1=1;}
  if(t_ds1 > t1_reg_on && t_ds1 < t1_reg_of && n1==1){digitalWrite(5,HIGH);nagrev1=1;}
  if(t_ds1 >= t1_reg_of){n1=0;digitalWrite(5,LOW);nagrev1=0;}   

  if(t_ds2 <= t2_reg_on){n1=1;digitalWrite(6,HIGH);nagrev2=1;}
  if(t_ds2 > t2_reg_on && t_ds2 < t2_reg_of && n2==1){digitalWrite(6,HIGH);nagrev2=1;}
  if(t_ds2 >= t2_reg_of){n2=0;digitalWrite(6,LOW);nagrev2=0;}   

  if(t_ds3 <= t3_reg_on){n3=1;digitalWrite(7,HIGH);nagrev3=1;}
  if(t_ds3 > t3_reg_on && t_ds3 < t3_reg_of && n3==1){digitalWrite(7,HIGH);nagrev3=1;}
  if(t_ds3 >= t3_reg_of){n3=0;digitalWrite(7,LOW);nagrev3=0;}   

            
}// end loop


float dsRead1(byte x) {
  byte data[2], addr[8][8], kol = 0;
  while (ds1.search(addr[kol])) {  // поиск датчиков, определение адреса и кол-ва датчиков
    kol++;
  } 
  ds1.reset_search();  // Сброс поиска датчика
  ds1.reset();         // Инициализация, выполняется сброс шины
  ds1.select(addr[x]); // Обращение к датчику по адресу
  ds1.write(0x44, 0);  // Измерение температуры с переносом данных в память
  ds1.reset();         // Инициализация, выполняется сброс шины
  ds1.select(addr[x]); // Обращение к датчику по адресу
  ds1.write(0xBE);     // Обращение памяти
  data[0] = ds1.read();// Чтение памяти byte low
  data[1] = ds1.read();// Чтение памяти byte high
  float value = ((data[1] << 8) | data[0]) / 16.0; return (float)value; // Расчет температуры и вывод
}  

 float dsRead2(byte x) {
  byte data[2], addr[8][8], kol = 0;
  while (ds2.search(addr[kol])) {  // поиск датчиков, определение адреса и кол-ва датчиков
    kol++;
  } 
  ds2.reset_search();  // Сброс поиска датчика
  ds2.reset();         // Инициализация, выполняется сброс шины
  ds2.select(addr[x]); // Обращение к датчику по адресу
  ds2.write(0x44, 0);  // Измерение температуры с переносом данных в память
  ds2.reset();         // Инициализация, выполняется сброс шины
  ds2.select(addr[x]); // Обращение к датчику по адресу
  ds2.write(0xBE);     // Обращение памяти
  data[0] = ds2.read();// Чтение памяти byte low
  data[1] = ds2.read();// Чтение памяти byte high
  float value = ((data[1] << 8) | data[0]) / 16.0; return (float)value; // Расчет температуры и вывод
}  

 float dsRead3(byte x) {
  byte data[2], addr[8][8], kol = 0;
  while (ds3.search(addr[kol])) {  // поиск датчиков, определение адреса и кол-ва датчиков
    kol++;
  } 
  ds3.reset_search();  // Сброс поиска датчика
  ds3.reset();         // Инициализация, выполняется сброс шины
  ds3.select(addr[x]); // Обращение к датчику по адресу
  ds3.write(0x44, 0);  // Измерение температуры с переносом данных в память
  ds3.reset();         // Инициализация, выполняется сброс шины
  ds3.select(addr[x]); // Обращение к датчику по адресу
  ds3.write(0xBE);     // Обращение памяти
  data[0] = ds3.read();// Чтение памяти byte low
  data[1] = ds3.read();// Чтение памяти byte high
  float value = ((data[1] << 8) | data[0]) / 16.0; return (float)value; // Расчет температуры и вывод
} 

void to_Timer(){newPosition = myEnc.read()/4;}  

24

Re: Терморегулятор с тремя реле

Спасибо Вам, ответил на почту

25

Re: Терморегулятор с тремя реле

Я буду писать статью по терморегулятору с тремя реле, мне нужно точно знать что все работает нормально. Как полностью протестируете, то напишите сообщение, что все ОК.