diff --git a/TempRelay.ino b/TempRelay.ino new file mode 100644 index 0000000..6b5152c --- /dev/null +++ b/TempRelay.ino @@ -0,0 +1,138 @@ +#include + +// Отладка вывода +#define DEBUG 1 +// Отладка ввода +#define DEBUG_INPUT 1 + +// Пин датчика температуры +#define PIN_SENSOR 2 +// Пин управления реле +#define PIN_RELAY 5 + +MicroDS18B20 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)); + + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // + // ВЫШЕ РЕГИСТРИРУЕТСЯ ВРЕМЯ И ТАЙМАУТЫ ОТКРЫТИЯ/ЗАКРЫТИЯ РЕЛЕ // + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // + + + // Проверка что не было зарегистрировано больше данных, чем это возможно + 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); // Изменяем значение сигнала на пине для управление реле +} \ No newline at end of file