TempRelay/TempRelay.ino

146 lines
5.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <microDS18B20.h>
// Отладка вывода
#define DEBUG 1
// Отладка ввода
#define DEBUG_INPUT 1
// Пин датчика температуры
#define PIN_SENSOR 2
// Пин управления реле
#define PIN_RELAY 5
MicroDS18B20<PIN_SENSOR> sensor; // датчик на пине D2
// Лимит таймаутов
#define MAX_TIMEOUTS 10
// Структура для хранения данных о температуре и таймаутах
struct
{
float temp;
int openTime;
int 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};
// Макрос для удобства записи таймаута в секундах (переводит в мс)
#define SEC_TO_MSEC(time) time*1000
void setup()
{
// Для отладочной печати
#if DEBUG == 1
Serial.begin(9600);
#endif // DEBUG
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //
// НИЖЕ РЕГИСТРИРУЕТСЯ ВРЕМЯ И ТАЙМАУТЫ ОТКРЫТИЯ/ЗАКРЫТИЯ РЕЛЕ //
// ЗНАЧЕНИЯ ДОЛЖНЫ БЫТЬ ОТСОРТИРОВАНЫ ПО ВОЗРАСТАНИЮ ТЕМПЕРАТУРЫ //
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //
REGISTER_TIMEOUT(83, 300, SEC_TO_MSEC(150));
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
}
void loop()
{
static uint32_t tmr; // Для таймера опроса датчика
static uint32_t lastRelayTime = 0; // Для управления реле
static float currentTemp = 0; // Текущая температура
int relayState; // Значение реле на текущий момент
int i; // Счетчик для цикла перебора температур
uint32_t current_time = millis(); // Текущее время
// конструкция программного таймера на 200 мс
if (current_time - tmr >= 200)
{
// Обновляем переменную для таймера опроса датчика
tmr = current_time;
// читаем прошлое значение
if (sensor.readTemp())
{
currentTemp = sensor.getTemp();
#if DEBUG == 1
Serial.println(currentTemp);
#endif // DEBUG
#if DEBUG_INPUT == 1
currentTemp = Serial.parseFloat();
#endif // DEBUG_INPUT
}
#if DEBUG == 1
else
Serial.println("error");
#endif // DEBUG
// запрашиваем новое измерение
sensor.requestTemp();
}
// Подбор подходящих таймаутов по текущей температуре
for (i = 0; i < timeouts_count; i++)
{
// Если обнаружили пороговое значение, которое больше текущей температуры - берем предыдущее и прерываем поиск
if (timeouts[i].temp > currentTemp)
{
i--;
break;
}
}
// Если перебрали все пороги и температура выше - берем последний
if (i == timeouts_count)
i--;
// Если значение индекса параметров таймаута для данной температуры неотрицательное, значит нужно произвести работу с реле на текущей температуре
if (0 <= i)
{
relayState = LOW; // Считаем что если не попали во время открытия, то реле надо закрыть
// Если время открытия ещё не истекло, то открываем реле
if (current_time < lastRelayTime + timeouts[i].openTime)
{
relayState = HIGH;
}
else // иначе,
// Если время привышает время закрытия, то необходимо сбросить время управления реле
if (current_time > lastRelayTime + timeouts[i].openTime + timeouts[i].closeTime)
{
lastRelayTime = current_time;
}
}
else // иначе, выключить реле
relayState = LOW; // Считаем что если не попали во время открытия, то реле надо закрыть
digitalWrite(PIN_RELAY, relayState); // Изменяем значение сигнала на пине для управление реле
}