Проблеммы с реле
- Войдите на сайт для отправки комментариев
Добрый день форумчане!
Снова прошу вас помочь с кодом. Ранее вы мне помогли решить поставленную задачу. И код исправно работал с задачей включения и отключения 3-х реле с определенной периодичностью. Теперь решил доработать код и дополнительно установить датчик температуры и задействовать четвертое реле для включения вентилятора и тут возникла проблема. А именно, не происходит срабатывание включения/отключения реле. В сом-порте все красиво и четко прописывается включение/отключение реле, но на практике этого не происходит. Точнее реле включается и через какое то время отключается, даже если условие по температуре еще не выполнено, но при этом в сом-порте пишется все правильно, что реле включено, хотя на самом деле оно отключено. Не могу поянть в чем дело. Подскажите пожалуйста в чем косяк? И сразу по пути подскажите как сделать так, чтобы информация о включенном/отключенном реле не выводилать каждый раз, а только когда произошел цикл отключения или включения?
#include <OneWire.h> #include <Wire.h> //Подключаем библиотеку для использования I2C интерфейса с модулем RTC #include <RTClib.h> //Подключаем библиотеку для использования модуля часов реального времени RTC #define DS1307_I2C_ADDRESS 0x68 //Указываем адресс RTC модуля #define RelPin1 A0 //Реле 1 насос #define RelPin2 A1 //Реле 2 компрессор #define RelPin3 A2 //Включение реле 3 общее питание #define RelPin4 A3 //Включение вентилятора охлаждения OneWire ds(2); // подключен к 2 пину (резистор на 4.7к обязателен) enum {sRel_12ON = 0, sRel_1OFF, sRel_2OFF, sRel_4OFF}; uint32_t time1 = 0; uint8_t state = sRel_12ON; uint32_t period = 0;// Период для ВК 1го и 2го-реле unsigned long prevMillis; #define PWM_MIN 0 //Если необходим ток покоя на LED - изменить эту константу #define PWM_MAX 200 //Если необходимо ограничить максимальную яркость - уменьшить значение #define PWM_PIN 6 //Пин порта, где будет ШИМ #define mn 60UL //Дополнительные константы для удобства #define hr 3600UL //Отражают соответствующие количества секунд #define d 86400UL //------------------------------------------------------------------ class time{ public: time(unsigned char h=0, unsigned char m=0, unsigned char s=0){ set_time(h, m, s); } time& operator = (time &t){hour = t.hour; min = t.min; sec = t.sec; seconds = t.seconds; return *this;} boolean operator ==(time &t){return seconds==t.get_time();} boolean operator !=(time &t){return !(*this==t);} boolean operator > (time &t){return seconds>t.get_time();} boolean operator < (time &t){return seconds<t.get_time();} boolean operator >=(time &t){return seconds>=t.get_time();} boolean operator <=(time &t){return seconds<=t.get_time();} void set_time(unsigned char h, unsigned char m, unsigned char s){ hour=h; min=m; sec=s; seconds=(unsigned long)h*1440 + (unsigned long)m*60 + s; } unsigned long get_time(){return seconds;}; void print() {Serial.print(hour); Serial.print(':');Serial.print(min); Serial.print(':');Serial.println(sec);} private: unsigned char hour; unsigned char min; unsigned char sec; unsigned long seconds; }; //------------------------------------------------------------------ class relay{ public: relay(unsigned char pin){ pin_num = pin; pinMode(pin_num, OUTPUT); digitalWrite(pin_num, 1); state=0; } void operator =(boolean val) {digitalWrite(pin_num, !val); state=val;} operator boolean() {return state;} private: unsigned char pin_num; boolean state; }; //------------------------------------------------------------------ RTC_DS1307 RTC; //------------------------------------------------------------------ time cur_time; time relay_1_on(07, 00, 00); // Время включения 1-ого реле time relay_1_off(22, 00, 00); // Время отключения 1-ого реле relay relay_1(RelPin3); // Реле 1 //------------------------------------------------------------------ char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; long sunrise_start = 07*hr+05*mn; //Начало восхода в 9 - 45 long sunrise_duration = 55*mn; //Длительность восхода 30 минут long sunset_start = 21*hr+00*mn; //начало заката в 21-15 long sunset_duration = 55*mn; //Длительность заката 30 минут //******************************************************************************************** void setup(){ pinMode(RelPin1, OUTPUT); pinMode(RelPin2, OUTPUT); pinMode(RelPin3, OUTPUT); pinMode(RelPin4, OUTPUT); Wire.begin(); //Инициируем I2C интерфейс RTC.begin(); //Инициирум RTC модуль analogWrite(PWM_PIN, PWM_MIN); //Пишем в порт минимальное значение Serial.begin(9600); //Запускаем сом-порт Serial.println("Test start"); //delay(3000); //Ожидаем открытия консоли if (! RTC.begin()) { Serial.println("Couldn't find RTC"); while (1); } RTC.adjust(DateTime(F(__DATE__), F(__TIME__))); //Текущая строка выводит дату и время компиляции скетча. После заливки скетча нужно закомментировать. // RTC.adjust(DateTime(2018, 9, 22, 17, 10, 0)); //Текущая строка предназначена для ручного ввода даты и времени в формате: Мес. день, год часы, минуты, секунды. } // КОНЕЦ ИНИЦИАЛИЗАЦИИ //******************************************************************************************** void loop() // ПРОГРАММЫй безусловный ЦИКЛ { long pwm; DateTime myTime = RTC.now(); //Читаем данные времени из RTC при каждом выполнении цикла long Day_time = myTime.unixtime() % 86400; //сохраняем в переменную - время в формате UNIX //********************************************************************************************* // обработка интервала до восхода и после заката //********************************************************************************************* if ((Day_time<sunrise_start) || //Если с начала суток меньше чем начало восхода (Day_time>=sunset_start+sunset_duration)) { //Или больше чем начало заката + длительность pwm = PWM_MIN; //Величина для записи в порт равна минимуму //********************************************************************************************* // обработка интервала восхода //********************************************************************************************* }else if ((Day_time>=sunrise_start) && //Если с начала суток больше чем начало восхода (Day_time<sunrise_start+sunrise_duration)){ //И меньше чем начало восхода + длительность pwm = ((Day_time - sunrise_start)*(PWM_MAX-PWM_MIN)) / sunrise_duration; //Вычисляем для рассвета величину для записи в порт ШИМ //********************************************************************************************* // обработка интервала заката //********************************************************************************************* }else if ((Day_time>=sunset_start) && //Если начала суток больше чем начало заката и меньше чем (Day_time<sunset_start+sunset_duration)){ //начало заката плюс длительность pwm = ((sunset_start+sunset_duration - Day_time)*(PWM_MAX-PWM_MIN)) / sunrise_duration; //Вычисляем для заката величину для записи в порт ШИМ //******************************************************************************************** // обработка интервала от конца рассвета и до начала заката, // когда свет должен быть включен на максимальную яркость //******************************************************************************************** }else { pwm = PWM_MAX; //Устанавливаем максимальную величину для записи в порт ШИМ } analogWrite(PWM_PIN, pwm); //Пишем в порт вычисленное значение byte i; byte present = 0; byte type_s; byte data[12]; byte addr[8]; float celsius, fahrenheit; if ( !ds.search(addr)) { Serial.println(); ds.reset_search(); delay(250); return; } for( i = 0; i < 8; i++) ds.reset(); ds.select(addr); ds.write(0x44, 1); // начало коммуникации delay(1000); present = ds.reset(); ds.select(addr); ds.write(0xBE); // читаем значение Serial.print(" "); for ( i = 0; i < 9; i++) { // смотрим 9 байтов data[i] = ds.read(); Serial.print(" "); } // Преобразуем получненный данные в температуру // Используем int16_t тип, т.к. он равен 16 битам // даже при компиляции под 32-х битный процессор int16_t raw = (data[1] << 8) | data[0]; if (type_s) { raw = raw << 3; if (data[7] == 0x10) { raw = (raw & 0xFFF0) + 12 - data[6]; } } else { byte cfg = (data[4] & 0x60); if (cfg == 0x00) raw = raw & ~7; else if (cfg == 0x20) raw = raw & ~3; else if (cfg == 0x40) raw = raw & ~1; } celsius = (float)raw / 16.0; DateTime now = RTC.now(); Serial.print(now.day(), DEC); Serial.print('.'); Serial.print(now.month(), DEC); Serial.print('.'); Serial.print(now.year(), DEC); Serial.print(" ("); Serial.print(daysOfTheWeek[now.dayOfTheWeek()]); Serial.print(") "); Serial.print(now.hour(), DEC); Serial.print(':'); Serial.print(now.minute(), DEC); Serial.print(':'); Serial.print(now.second(), DEC); Serial.print(" "); Serial.print("PWM="); Serial.print(pwm); Serial.print(" Temperature = "); Serial.print(celsius); Serial.print(" C, "); Serial.println(); delay(1000); if (celsius > 31) // устанавливаем значение температуры при котором включается реле { digitalWrite(RelPin4, HIGH); Serial.print("Relay 4 ON"); // Serial.print(); } if (celsius < 30) // устанавливаем значение температуры при котором отключается реле { digitalWrite(RelPin4, LOW); Serial.print("Relay 4 OFF"); // Serial.print(); } if ((millis() - time1) >= period) { time1 = millis(); switch (state) { case sRel_12ON: state = sRel_1OFF; digitalWrite(RelPin1, LOW ); digitalWrite(RelPin2, HIGH ); period = 10000; // Период для включения 1-го реле насоса 10 секунд Serial.print("Relay 1 ON"); Serial.println(); break; case sRel_1OFF: state = sRel_2OFF; digitalWrite(RelPin1, HIGH); period = 60000;// Период для включения 2го-реле компрессора 60 секунд Serial.print("Relay 2 ON"); Serial.println(); break; case sRel_2OFF: state = sRel_12ON; digitalWrite(RelPin2, LOW); period = 1200000;// Период для выключения 1го и 2го-реле 20 минут Serial.print("Relay 1 & Relay 2 OFF"); Serial.println(); break; } } }