#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)); 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); // Изменяем значение сигнала на пине для управление реле }