Найти в Дзене
Рагозин Николай

Код С++ для терморегулятора инкубатора на Ардуино (Cyber Hen DA&S)

Сегодня я предлагаю вашему вниманию рабочий код, версия №1.3 (стабильная) без расширенного функционала для загрузки на Ардуино. Антидребезг кнопок
Плавное обновление дисплея без мерцания
Точность изменения температуры 0.1°C
Два режима работы (нагрев и охлаждение)
Гистерезис для предотвращения частых переключений реле Этот код обеспечивает базовую функциональность терморегулятора с простым и понятным управлением, без дополнительных сложных функций (более сложные функции и настройки реализованы в последующих версиях кода). Просто копируете текст в вставляете в скетч #include <OneWire.h> #include <DallasTemperature.h> #include <LiquidCrystal_I2C.h> #include <Bounce2.h> // Пины #define ONE_WIRE_BUS 2 #define RELAY_PIN 7 #define MODE_BUTTON 8 #define UP_BUTTON 9 #define DOWN_BUTTON 10 // Настройки #define TEMP_STEP 0.1 // Шаг изменения температуры 0.1°C #define HYSTERESIS 0.2 // Гистерезис 0.2°C #define LCD_UPDATE_INTERVAL 200 // Интервал обновления дисплея (мс) // Инициализация OneW
Оглавление

Сегодня я предлагаю вашему вниманию рабочий код, версия №1.3 (стабильная) без расширенного функционала для загрузки на Ардуино.

Инструкция по использованию терморегулятора для инкубатора

  1. Кнопки управления:
    Кнопка "Режим" - переключает между нагревом и охлаждением
    Кнопка "+" - увеличивает установленную температуру
    Кнопка "-" - уменьшает установленную температуру
  2. Отображение на LCD:
    Верхняя строка: текущая температура (NOW) и режим работы (HEAT/COOL)
    Нижняя строка: заданная температура (SET) и состояние реле (ON/OFF)
  3. Логика работы:
    В режиме нагрева реле включается, когда температура ниже уставки
    В режиме охлаждения реле включается, когда температура выше уставки

Основные функции реализованные в этом коде:

Антидребезг кнопок
Плавное обновление дисплея без мерцания
Точность изменения температуры 0.1°C
Два режима работы (нагрев и охлаждение)
Гистерезис для предотвращения частых переключений реле

Этот код обеспечивает базовую функциональность терморегулятора с простым и понятным управлением, без дополнительных сложных функций (более сложные функции и настройки реализованы в последующих версиях кода).

Код микроконтроллера C++:

Просто копируете текст в вставляете в скетч

#include <OneWire.h>

#include <DallasTemperature.h>

#include <LiquidCrystal_I2C.h>

#include <Bounce2.h>

// Пины

#define ONE_WIRE_BUS 2

#define RELAY_PIN 7

#define MODE_BUTTON 8

#define UP_BUTTON 9

#define DOWN_BUTTON 10

// Настройки

#define TEMP_STEP 0.1 // Шаг изменения температуры 0.1°C

#define HYSTERESIS 0.2 // Гистерезис 0.2°C

#define LCD_UPDATE_INTERVAL 200 // Интервал обновления дисплея (мс)

// Инициализация

OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);

LiquidCrystal_I2C lcd(0x27, 16, 2);

// Антидребезг для кнопок

Bounce modeButton = Bounce();

Bounce upButton = Bounce();

Bounce downButton = Bounce();

// Переменные состояния

float currentTemp = 0;

float setPoint = 37.8;

bool heatingMode = true;

bool relayState = false;

// Переменные для управления дисплеем

float lastShownTemp = -100;

float lastShownSetPoint = -100;

bool lastShownMode = false;

bool lastShownRelayState = false;

unsigned long lastDisplayUpdate = 0;

bool displayInitialized = false;

void setup() {

pinMode(RELAY_PIN, OUTPUT);

digitalWrite(RELAY_PIN, LOW);

// Настройка кнопок

modeButton.attach(MODE_BUTTON, INPUT_PULLUP);

modeButton.interval(25);

upButton.attach(UP_BUTTON, INPUT_PULLUP);

upButton.interval(25);

downButton.attach(DOWN_BUTTON, INPUT_PULLUP);

downButton.interval(25);

// Инициализация датчика температуры

sensors.begin();

sensors.setResolution(12);

// Инициализация дисплея

lcd.init();

lcd.backlight();

// Первоначальное отображение

updateDisplay(true);

}

void loop() {

unsigned long currentMillis = millis();

// Обновление состояния кнопок

modeButton.update();

upButton.update();

downButton.update();

// Обработка кнопок

handleButtons();

// Обновление температуры

static unsigned long lastTempUpdate = 0;

if (currentMillis - lastTempUpdate >= 1000) {

sensors.requestTemperatures();

currentTemp = sensors.getTempCByIndex(0);

controlLogic();

lastTempUpdate = currentMillis;

}

// Плавное обновление дисплея

if (currentMillis - lastDisplayUpdate >= LCD_UPDATE_INTERVAL) {

updateDisplay(false);

lastDisplayUpdate = currentMillis;

}

}

void handleButtons() {

// Переключение режима

if (modeButton.fell()) {

heatingMode = !heatingMode;

}

// Увеличение температуры

if (upButton.fell()) {

setPoint += TEMP_STEP;

}

// Уменьшение температуры

if (downButton.fell()) {

setPoint -= TEMP_STEP;

}

}

void controlLogic() {

if (heatingMode) {

// Режим нагрева

if (currentTemp < (setPoint - HYSTERESIS/2) && !relayState) {

digitalWrite(RELAY_PIN, HIGH);

relayState = true;

} else if (currentTemp >= (setPoint + HYSTERESIS/2) && relayState) {

digitalWrite(RELAY_PIN, LOW);

relayState = false;

}

} else {

// Режим охлаждения

if (currentTemp > (setPoint + HYSTERESIS/2) && !relayState) {

digitalWrite(RELAY_PIN, HIGH);

relayState = true;

} else if (currentTemp <= (setPoint - HYSTERESIS/2) && relayState) {

digitalWrite(RELAY_PIN, LOW);

relayState = false;

}

}

}

void updateDisplay(bool forceFullUpdate) {

// Определяем необходимость обновления каждой части

bool updateTemp = forceFullUpdate || (fabs(currentTemp - lastShownTemp) >= 0.05);

bool updateSetPoint = forceFullUpdate || (fabs(setPoint - lastShownSetPoint) >= 0.05);

bool updateMode = forceFullUpdate || (heatingMode != lastShownMode);

bool updateRelay = forceFullUpdate || (relayState != lastShownRelayState);

// Если нечего обновлять и не принудительное обновление - выходим

if (!forceFullUpdate && !updateTemp && !updateSetPoint && !updateMode && !updateRelay) {

return;

}

// Полное обновление при первом вызове или по требованию

if (forceFullUpdate || !displayInitialized) {

lcd.clear();

lcd.setCursor(0, 0); lcd.print("Now:");

lcd.setCursor(11, 0); lcd.print("");

lcd.setCursor(0, 1); lcd.print("Set:");

lcd.setCursor(11, 1); lcd.print("");

displayInitialized = true;

}

// Обновляем только измененные части

if (updateTemp) {

lcd.setCursor(4, 0);

lcd.print(currentTemp, 1);

lcd.write(0xDF); // Символ градуса

lcd.print("C ");

lastShownTemp = currentTemp;

}

if (updateSetPoint) {

lcd.setCursor(4, 1);

lcd.print(setPoint, 1);

lcd.write(0xDF);

lcd.print("C ");

lastShownSetPoint = setPoint;

}

if (updateMode) {

lcd.setCursor(12, 0);

lcd.print(heatingMode ? "HEAT" : "COOL");

lastShownMode = heatingMode;

}

if (updateRelay) {

lcd.setCursor(12, 1);

lcd.print(relayState ? "ON " : "OFF");

lastShownRelayState = relayState;

}

}

Стать из этого цикла: