Термостат для инкубатора

cerber

Местный инквизитор
Команда форума
Администратор
затеялись мы переделать инкубатор,делали давненько,точнее переделывали из старого холодильника,и схема известного "петушка",работала не очень то и корректно,перепад температур был в пределах 1-1.5 градусов,что очень критично,ну посидел,поискал и нашёл одну статейку,собрал,но не работала как надо,оговорюсь сразу,я не любитель arduino и работаю с ней крайне редко,и всех тонкостей не знаю,но всё же собрали мы всё в кучу,приключения описывать не буду,они не критичные,единственное было с энкодером с отдельным питанием,но не суть,запустили мы чудо,оно даже заработало,но не так,как мне было надо,но про это позже,сейчас о деталях
MCP9808 — высокоточный датчик температуры
экран WH1602A,
твердотельное реле SSR-25DA на 25А,но его оказалось даже много,но это ничего
энкодер модуль KY-040,
собиралось по схеме
tmp102_bb.jpg
tmp102_схема.jpg
собирать по какой удобнее,мне было без разницы,теперь возвращаюсь к обогреву,я использую четыре лампы накаливания на 100 ватт,включённые последовательно-параллельно,при выставленных параметрах,как в статье,лампы мигали словно поворотник на машине и температура прыгала в пределах 3-5 градусов,пришлось подкорректировать период срабатывания,и в отличии от статьи,период наоборот уменьшил,а не увеличил,лампы медленно разогреваются и медленно погасают,что дало погрешность в 0.1 градуса,что меня не может не радовать,ниже прикреплены библиотеки именно для работы с указанными, выше, деталями,сам скетч
C++:
//Термостат для инкубатора или PID регулятор на arduino
//код из видео https://www.youtube.com/watch?v=9odcsuAquLU
//донат, http://www.donationalerts.ru/r/arduinolab

/// датчик температуры MCP9808, LCD1602
 
 

#include <EEPROM.h>
#include <Wire.h>
#include <LiquidCrystal.h>
#include "Adafruit_MCP9808.h"                // https://codeload.github.com/adafruit/Adafruit_MCP9808_Library/zip/master
#include <PID_v1.h>                          // https://playground.arduino.cc/Code/PIDLibrary

Adafruit_MCP9808 tempsensor = Adafruit_MCP9808();
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
//////////////////////////////////////////
#define ENCODER_A 2                          // вход энкодера
#define ENCODER_B 3
#define ENCODER_KEY 11

#define TEMP_MAX 40.0                        // Пределы настройки термостата
#define TEMP_MIN 30.0

#define RELAY_PIN 12                         // выход на реле
                      
#define WindowSize 16                   // период срабатывания обогревателя                                     
//////////////////////////////////////////////

bool encoderPinALast = LOW;
bool n = LOW;
unsigned long windowStartTime;

double Setpoint, Input, Output;
double Kp=2, Ki=5, Kd=1.5;
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
 
float temperature;
 
void setup() {
//   Serial.begin(9600);
    
   lcd.begin(16, 2);
   lcd.clear();

   if (!tempsensor.begin()) {
    lcd.print("not find MCP9808!");
    while (1);
  }

   pinMode(RELAY_PIN, OUTPUT);
   pinMode (ENCODER_A, INPUT);
   pinMode (ENCODER_B, INPUT);
   pinMode (ENCODER_KEY, INPUT);

   myPID.SetOutputLimits(0, WindowSize);
   myPID.SetMode(AUTOMATIC);

      //// проверка ЕЕПРОМ для первого включения
   if (EEPROM.read(0) == 255 && EEPROM.read(4) == 255){
        EEPROM.write(0, 10);
        EEPROM.write(1, 0);
        EEPROM.write(2, 240);
        EEPROM.write(3, 65);
   }
 
   EEPROM.get(0, Setpoint);

 
}

void loop() {
  temperature = tempsensor.readTempC();      // забираем температуру
  Input = temperature;
 
  myPID.Compute(); 
/////////////////////////////
   lcd.setCursor(0, 0);
   lcd.print(temperature);
   lcd.print("C  ");
   lcd.setCursor(8, 0);
   lcd.print(Setpoint, 1);
   lcd.print("C     ");
   lcd.setCursor(0, 1);
   lcd.print(map(Output, 0, WindowSize, 0, 100));
   lcd.print("%  ");
   lcd.setCursor(8, 1); 
   lcd.print(Output);
   lcd.print("mS ");
    

///////////////////////


   if(!digitalRead(ENCODER_KEY)){                    // если надавили на кнопку, входим в настройки
     lcd.setCursor(13, 0);
     lcd.print("<<"); 
                                                     // управление энкодером
   n = digitalRead(ENCODER_A);
   if ((encoderPinALast == LOW) && (n == HIGH)) {
     if (digitalRead(ENCODER_B) == LOW) {
        Setpoint -= .1;
        if (Setpoint < TEMP_MIN) Setpoint = TEMP_MIN;        // проверяем пределы настроек
     } else {
        Setpoint += .1;
        if (Setpoint > TEMP_MAX) Setpoint = TEMP_MAX;
     } 
   }
   EEPROM.put(0, Setpoint);                          // пишем в еепром настройку
   encoderPinALast = n;
  delay(5);
//  return;
   }


      /************************************************
   * turn the output pin on/off based on pid output
   ************************************************/
  if (millis() - windowStartTime >= WindowSize) { //time to shift the Relay Window
    windowStartTime += WindowSize;
    if (windowStartTime > millis()) windowStartTime = 0;    // защита от переполнения
  }
  if (Output < millis() - windowStartTime) digitalWrite(RELAY_PIN, LOW);
  else digitalWrite(RELAY_PIN, HIGH);
 

}
3eROVu-wWMA.jpg
на экране
слева вверху - температура в режиме реального времени
справа вверху - установленная температура
справа внизу - период срабатывания твердотельного реле в мили секундах
слева внизу - процент набора мили секунд,ну если не нужны,то можно убрать
температура регулируется при нажатии на кнопку энкодера,если не нажать,то регулировка температуры осуществляться не будет
вот так получился довольно не плохой терморегулятор,и довольно дешево
 

Вложения

  • Arduino-PID-Library-master.zip
    10,2 KB · Просмотры: 3
  • Adafruit_MCP9808_Library-master.zip
    144,1 KB · Просмотры: 2
  • Like
Реакции: alex

alex

Команда форума
Администратор
До чего дошел прогресс... Заканчиваю ремонт в квартире, раздумываю на тему умного дома своими руками.
 
Сверху Снизу