На рисунке показана схема простого трехканального терморегулятора. В примере используется 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
Плата — термостат
Добрый день! А можно такой же регулятор сделать для измерения более высоких температур на max 6675? Может поможете со скетчем) Заранее благодарен!