Трехканальный терморегулятор (Arduino)

На рисунке показана схема простого трехканального терморегулятора. В примере используется 3 цифровых датчика температуры DS18B20, энкодер и LCD2004 с модулем I2C.

Терморегулятор основан на плате Arduino Nano, но можно использовать более дешевый аналог — плату LGT8F328P-LQFP32 MiniEVB.

Как использовать плату LGT8F328P-LQFP32 MiniEVB в среде Arduino IDE рассказано в http://rcl-radio.ru/?p=129966.

Управление трехканальный терморегулятором очень простое и осуществляется при помощи кнопки энкодера. В первой , второй и третьей строке дисплея LCD2004 (с модулем I2C) отображаются показания 3-х цифровых датчиков температуры, а так же температура включения и выключения нагревательного элемента, отдельно для каждого канала. Управление нагревательными элементами осуществляется при помощи 3-х реле. Реле к плате Arduino осуществляется через транзисторный ключ или напрямую если Вы используете модуль реле (с транзисторным ключом). В четвертой строке дисплея отображается состояние 3-х реле.

При включении терморегулятора, температура начинает повышаться до значения Toff, далее температура снижается до значения Ton, нагрев снова включается и цикл повторяться по новой.

Значения температур регулирования сохраняются в энергонезависимой памяти микроконтроллера.

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

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

Скетч нуждается в тестировании!!!

Форум — http://forum.rcl-radio.ru/viewtopic.php?pid=8053#p8053

Плата — термостат

Comments

  1. Добрый день! А можно такой же регулятор сделать для измерения более высоких температур на max 6675? Может поможете со скетчем) Заранее благодарен!

Добавить комментарий

Войти с помощью: