TempRelay/TempRelay.ino

181 lines
6.7 KiB
Arduino
Raw Normal View History

2022-10-07 06:28:04 +00:00
#include <microDS18B20.h> // Датчик температуры
// Отладка вывода
#define DEBUG 1
2022-10-07 06:28:04 +00:00
// Отладка ввода температуры
#define DEBUG_INPUT 0
// Пин датчика температуры
#define PIN_SENSOR 2
// Пин управления реле
#define PIN_RELAY 5
MicroDS18B20<PIN_SENSOR> sensor; // датчик на пине D2
// Лимит таймаутов
#define MAX_TIMEOUTS 10
// Структура для хранения данных о температуре и таймаутах
struct
{
float temp;
2022-10-07 06:28:04 +00:00
uint32_t openTime;
uint32_t closeTime;
} timeouts[MAX_TIMEOUTS];
int timeouts_count = 0; // Общее количество зарегистрированных данных о тем-ре и таймаутах
// Макрос для регистрации данных о тем-ре и таймаутах (тем-ра в градусах цельсия, время открытия и закрытия в миллисекундах)
#define REGISTER_TIMEOUT(temp_C, openTime_ms, closeTime_ms) timeouts[timeouts_count++] = {temp_C, openTime_ms, closeTime_ms};
// Макрос для удобства записи таймаута в секундах (переводит в мс)
2022-10-07 06:28:04 +00:00
#define SEC_TO_MSEC(time) (long)time*1000
void setup()
{
// Для отладочной печати
#if DEBUG == 1
Serial.begin(9600);
#endif // DEBUG
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //
// НИЖЕ РЕГИСТРИРУЕТСЯ ВРЕМЯ И ТАЙМАУТЫ ОТКРЫТИЯ/ЗАКРЫТИЯ РЕЛЕ //
// ЗНАЧЕНИЯ ДОЛЖНЫ БЫТЬ ОТСОРТИРОВАНЫ ПО ВОЗРАСТАНИЮ ТЕМПЕРАТУРЫ //
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //
REGISTER_TIMEOUT(83, 300, SEC_TO_MSEC(150));
2022-10-03 13:54:57 +00:00
REGISTER_TIMEOUT(85, 300, SEC_TO_MSEC(120));
REGISTER_TIMEOUT(88, 300, SEC_TO_MSEC(90));
REGISTER_TIMEOUT(89, 300, SEC_TO_MSEC(70));
REGISTER_TIMEOUT(90, 300, SEC_TO_MSEC(50));
REGISTER_TIMEOUT(91, 300, SEC_TO_MSEC(40));
REGISTER_TIMEOUT(92, 300, SEC_TO_MSEC(35));
REGISTER_TIMEOUT(93, 300, SEC_TO_MSEC(30));
REGISTER_TIMEOUT(94, 300, SEC_TO_MSEC(25));
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //
// ВЫШЕ РЕГИСТРИРУЕТСЯ ВРЕМЯ И ТАЙМАУТЫ ОТКРЫТИЯ/ЗАКРЫТИЯ РЕЛЕ //
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //
// Проверка что не было зарегистрировано больше данных, чем это возможно
if (timeouts_count >= MAX_TIMEOUTS)
{
#if DEBUG == 1
Serial.println("TIMEOUTS LIMIT REACHED ! ! !");
#endif // DEBUG
while(1); // Программа не запуститься дальше, если допущена ошибка
}
// Настройка реле
pinMode(PIN_RELAY, OUTPUT); // Объявляем пин реле как выход
digitalWrite(PIN_RELAY, LOW); // Выключаем реле - посылаем сигнал 0
2022-10-07 06:28:04 +00:00
// запрашиваем новое измерение с датчика
sensor.requestTemp();
}
2022-10-07 06:28:04 +00:00
uint32_t tmr; // Для таймера опроса датчика
uint32_t lastRelayTime = 0; // Для управления реле
float currentTemp; // Текущая температура
void loop()
{
int relayState; // Значение реле на текущий момент
int i; // Счетчик для цикла перебора температур
uint32_t current_time = millis(); // Текущее время
2022-10-07 06:28:04 +00:00
#if DEBUG_INPUT == 1
byte n = Serial.available();
if (n == 0)
{
currentTemp = Serial.parseFloat();
}
#endif // DEBUG_INPUT
// конструкция программного таймера на 800 мс
if (current_time - tmr >= 800)
{
// Обновляем переменную для таймера опроса датчика
tmr = current_time;
// читаем прошлое значение
if (sensor.readTemp())
{
2022-10-07 06:28:04 +00:00
#if DEBUG_INPUT == 0
currentTemp = sensor.getTemp();
#endif // DEBUG_INPUT
}
#if DEBUG == 1
else
2022-10-07 06:28:04 +00:00
Serial.println("sensor.readTemp error");
#endif // DEBUG
// запрашиваем новое измерение
sensor.requestTemp();
}
// Подбор подходящих таймаутов по текущей температуре
for (i = 0; i < timeouts_count; i++)
{
// Если обнаружили пороговое значение, которое больше текущей температуры - берем предыдущее и прерываем поиск
if (timeouts[i].temp > currentTemp)
{
i--;
break;
}
}
// Если перебрали все пороги и температура выше - берем последний
if (i == timeouts_count)
i--;
2022-10-07 06:28:04 +00:00
relayState = LOW; // Считаем что если не попали во время открытия, то реле надо закрыть
// Если значение индекса параметров таймаута для данной температуры неотрицательное, значит нужно произвести работу с реле на текущей
#if DEBUG == 1
Serial.print("Temp: ");
Serial.print(currentTemp);
Serial.print(" Time: ");
Serial.print(current_time);
Serial.print(" Relay: ");
Serial.print(lastRelayTime);
Serial.print(" index: ");
Serial.print(i);
#endif // DEBUG
if (0 <= i)
{
2022-10-07 06:28:04 +00:00
#if DEBUG == 1
Serial.print(" openTime: ");
Serial.print(timeouts[i].openTime);
Serial.print(" closeTime: ");
Serial.print(timeouts[i].closeTime);
#endif // DEBUG
// Если время открытия ещё не истекло, то открываем реле
if (current_time < lastRelayTime + timeouts[i].openTime)
{
relayState = HIGH;
}
else // иначе,
// Если время привышает время закрытия, то необходимо сбросить время управления реле
2022-10-07 06:28:04 +00:00
if (current_time > lastRelayTime + timeouts[i].openTime + timeouts[i].closeTime
|| !lastRelayTime)
{
lastRelayTime = current_time;
}
}
else // иначе, выключить реле
2022-10-07 06:28:04 +00:00
{
relayState = LOW; // Считаем что если не попали во время открытия, то реле надо закрыть
2022-10-07 06:28:04 +00:00
lastRelayTime = 0;
}
#if DEBUG == 1
Serial.println("");
#endif // DEBUG
digitalWrite(PIN_RELAY, relayState); // Изменяем значение сигнала на пине для управление реле
2022-10-07 06:28:04 +00:00
}