Проблеммы с реле

Нет ответов
restiv
Offline
Зарегистрирован: 03.01.2016

Добрый день форумчане!

Снова прошу вас помочь с кодом. Ранее вы мне помогли решить поставленную задачу. И код исправно работал с задачей включения и отключения 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;
        }
  }
}