Стопорятся RTC часы

lex0r
Offline
Зарегистрирован: 09.01.2016
Доброй ночи, прошу помощи, делаю контроллер для аквариума, все собрано спаяно, но сейчас при подключение силовых проводов от светильников, при срабатывании релле свет включается, через заданное время свет выключается и РТС (DS3231)  часы стопорятся на времени срабатывания релле... в чем может быть ошибка?

П.С. начинающий ардуинщик.

//***************************************************

// Скетч для управления релейным модулем, в котором *
// использовано два канала. Используется:           *
// Модуль часов реального времени - RTC  DS1307     *
// ЖК-дисплей  LCD 16х2 с I2C интерфейсом           * 
// Релейный модуль (4 канала)                       *
// Логика на входах релейного модуля - инверсная    * 
// Температурный датчик DS18B20                     *
// Автор: ZORS                                      *  
// Версия 2-10. Дата 24.12.2013 21:05               *
//***************************************************
//----------ИМПОРТ БИБЛИОТЕК-------------------------
 
 
#include <OneWire.h>                                //Подключаем библиотеку для использования однопроводного интерфейса 
                                                    //Температурного датчика DS18B20
#include <Wire.h>                                   //Подключаем библиотеку для использования I2C интерфейса с модулем RTC 
                                                    //И модуля ЖК дисплея 16Х2, который также испольует I2C
                                                    
#include <LiquidCrystal_I2C.h>                      //Подключаем библиотеку для Модуля ЖК дисплея 16Х2 
#include <RTClib.h>                                 //Подключаем библиотеку для использования модуля часов реального времени RTC
//---------------------------------------------------
int TSensorPin = 11;                                //Определяем порт шины OneWire (IC) для температурного датчика DS18B20
OneWire ds(TSensorPin);                             //Создаем соответсвующий объект  
LiquidCrystal_I2C lcd(0x27,16,2);                   //Устанавливаем I2С адрес ЖК-дисплея = 0x27. Это данные из документации на I2C модуль на дисплее
RTC_DS1307 RTC;                                     //Создаем переменную класса - для использования RTC
//----------Объявляем разные переменные--------------
const int RelayChn1 = 4;                            //Используем цифровой ПОРТ 6 для ПЕРВОГО канала релейного модуля
const int RelayChn2 = 8;                            //Используем цифровой ПОРТ 7 для ВТОРОГО канала релейного модуля
const int RelayChn3 = 9;                            //Используем цифровой ПОРТ 8 для ТРЕТЬЕГО канала релейного модуля
 
//----------Настройки времени и продолжительности включения реле
//----------ПЕРВЫЙ канал----------------------------
const long StartRelCn_1 = 5900;                     //Время срабатывания в ПЕРВОМ канале релейного модуля (в секундах от начала суток) 
                                                     //в данном случае 25200 - это 7 часов 00 минут  = ( 60секунд *60 минут *7 = 25200) 
const long DurationCh_1 = 10;                        //ДЛИТЕЛЬНОСТЬ срабатывания реле в ПЕРВОМ канале (в секундах) 
//----------ВТОРОЙ канал----------------------------
const long StartRelCn_2 = 37800;                     //Время срабатывания во ВТОРОМ канале релейного модуля (в секундах от начала суток)
                                                     //В данном случае 10 часов 30 минут = (60 секунд * 60 минут * 10 часов + 60сек*30мин = 37800) 
const long DurationCh_2 = 15;                        //ДЛИТЕЛЬНОСТЬ срабатывания реле во ВТОРОМ канале (в секундах) 
//----------ТРЕТИЙ КАНАЛ----------------------------
float t0 = 30.5;                                     //Уставка температуры для ТРЕТЬЕГО канала релейного модуля 
float tGistrsis = 0.7;                               //Уставка гистерезиса - т.е отклонения от темп-ры уставки
                                                     //т.е. в данном случае 0,7 = плюс минус 0,35 градуса
 
//----------Модуль инициализации setup() - выполняется один раз при инициализации платы при подаче напряжение (и аналогичных событиях) 
void setup(){
  
   digitalWrite(TSensorPin,HIGH); 
    pinMode(RelayChn1,OUTPUT);                       //Инициализируем порт для ПЕРВОГО канала как ВЫХОД
    pinMode(RelayChn2,OUTPUT);                       //Инициализируем порт для ВТОРОГО канала как ВЫХОД   
    pinMode(RelayChn3,OUTPUT);                       //Инициализируем порт для ТРЕТЬЕГО канала как ВЫХОД   
 
    digitalWrite(RelayChn1,HIGH);                    //Устанавливаем на входах релейного модуля ВЫСОКИЙ уровень 
    digitalWrite(RelayChn2,HIGH);                    //Т.к. используемый релейный модуль с опторазвязкой - управляется инверсной логикой 
    digitalWrite(RelayChn3,HIGH);                    //   
 
    Wire.begin();                                    //Инициируем I2C интерфейс
    RTC.begin();                                     //Инициирум RTC модуль
 
    lcd.init();                                      //Инициализируем ЖК дисплей 
    lcd.setBacklight(1);                             //Включаем на ЖК дисплее подсветку
//    RTC.adjust(DateTime(__DATE__, __TIME__));      //С этой строки необходимо убрать комментарии один раз в начале, 
                                                     //для того, чтобы загрузить в RTC дату и время на момент компиляции программы  
                                                     //Иногда необходимо заливать СКЕТЧ на плату со снятым комментарием - для поправки 
                                                     //времени в RTC, НО оставлять такой СКЕТЧ в работе НЕЛЬЗЯ !!!!!!!!!!!!!
 
//----------Подготавливаем экран ЖК дисплея - выводим на него статичные поля
    lcd.clear();
    lcd.setCursor(9, 0);
    lcd.print("t=");
    lcd.setCursor(0, 1);
    lcd.print("R1=0");
    lcd.setCursor(5, 1);
    lcd.print("R2=0");
    lcd.setCursor(10, 1);
    lcd.print("R3=0");
 
}                                                    // КОНЕЦ ИНИЦИАЛИЗАЦИИ
//--------------------------------------------------
void loop()                                          // ПРОГРАММЫй безусловный ЦИКЛ 
{
    DateTime myTime = RTC.now();                     //Читаем данные времени из RTC   
 
    //---------Вывод часов на ЖК--------------------
    lcd.setCursor(0, 0);                             //Перемещаем курсор ЖК дисплея в первую строку в 5-ю позицию
    if (myTime.hour() < 10) lcd.print ("0");         //так дополняются лидирующие нули - когда есть необходимость
    lcd.print(myTime.hour());                        //Выводим значение ЧАСОВ               
    lcd.print(':');                                  //Выводим символ разделителя (:) 
    if (myTime.minute() < 10) lcd.print ("0");    
    lcd.print(myTime.minute());                      //Выводим значение МИНУТ 
    lcd.print(':');                                  //Выводим символ разделителя (:) 
    if (myTime.second() < 10) lcd.print ("0");
    lcd.print(myTime.second());                      //Выводим значение СУЕКУНД
 
    //----------Раздел обработки реле по времени ----
    long utime = myTime.unixtime();                  //сохраняем время в формате UNIX
    utime %= 86400;                                  //Сохраняем в переменной остаток деления на кол-во секнд в сутках, 
                                                     //Это дает количество секунд с начала текущих суток
 
    //------------КАНАЛ 1------------------------------
    if ((utime >= StartRelCn_1) && 
       (utime < (StartRelCn_1+DurationCh_1)))
                                                     //Если секунд с начала суток больше, чем задано для включения 
                                                     //Но, одновременно и меньше, чем задано для включения + длительность 
      {
          digitalWrite(RelayChn1,LOW);               //Устанавливаем на ПЕРВОМ входе релейного модуля НИЗКИЙ уровень - реле срабатывает
         lcd.setCursor(3, 1);
         lcd.print("1");
      }  
    else
      {
          digitalWrite(RelayChn1,HIGH);              //Устанавливаем на ПЕРВОМ входе релейного модуля ВЫСОКИЙ уровень - реле выключается
          lcd.setCursor(3, 1);
          lcd.print("0");
      } 
 
    //------------КАНАЛ 2 - все аналогично -----------
    if ((utime >= StartRelCn_2) && 
       (utime < (StartRelCn_2+DurationCh_2)))
      {
        digitalWrite(RelayChn2,LOW);                 //Устанавливаем на ВТОРОМ входе релейного модуля НИЗКИЙ уровень - реле срабатывает
        lcd.setCursor(8, 1);
        lcd.print("1");
      }  
    else
      {
          digitalWrite(RelayChn2,HIGH);              //Устанавливаем на ВТОРОМ входе релейного модуля ВЫСОКИЙ уровень - реле выключается
          lcd.setCursor(8, 1);
          lcd.print("0");
      } 
    //----------Вывод температуры на ЖК--------------
    float temp = getTemp();                          //Читаем температуру с датчика 
    lcd.setCursor(11, 0);                            //Выводим температуру на ЖК
    lcd.print(temp);
    //------------КАНАЛ 3 Контроль температуры -------
    if (temp < t0-tGistrsis/2)
      {
        digitalWrite(RelayChn3,LOW);                 //Устанавливаем на ТРЕТЬЕМ входе релейного модуля НИЗКИЙ уровень - реле срабатывает
        lcd.setCursor(13, 1);
        lcd.print("1");
      }     
    else if (temp > t0+tGistrsis/2)
      {
        digitalWrite(RelayChn3,HIGH);                //Устанавливаем на ТРЕТЬЕМ входе релейного модуля ВЫСОКИЙ уровень - реле выключается
        lcd.setCursor(13, 1);
        lcd.print("0");
      }     
      
 
 
}
//------------Конец ЦИКЛА-----------------------------
//*****************************************************
 
//-------------Объявления и реализация функций---------
float getTemp(){                                       //функция чтения значения температуры с датчика DS18B20 по шине OneWire
    byte data[12];
    byte addr[8];
 
    if ( !ds.search(addr)) {
        //no more sensors on chain, reset search
        lcd.setCursor(0, 0);
        lcd.print("NO more addrss!");
 
        ds.reset_search();
        return -1001;
     }
 
    if ( OneWire::crc8( addr, 7) != addr[7]) {
          lcd.setCursor(0, 0);
          lcd.print("CRC is not valid!");
 
        return -1002;
    }
 
    if ( addr[0] != 0x10 && addr[0] != 0x28) {
          lcd.setCursor(0, 0);
          lcd.print("NOT recognizd!");
 
        return -1003;
    }
 
    ds.reset();
    ds.select(addr);
    ds.write(0x44,1); 
 
    byte present = ds.reset();
    ds.select(addr); 
    ds.write(0xBE); 
 
 
    for (int i = 0; i < 9; i++) { 
        data[i] = ds.read();
    }
 
    ds.reset_search();
 
    byte MSB = data[1];
    byte LSB = data[0];
 
    float TRead = ((MSB<<8) | LSB); 
    float Temperature = TRead / 16;
 
    return Temperature;
}
 
bwn
Offline
Зарегистрирован: 25.08.2014

Что то подсказывает, что стопорятся не часы, а повисает МК. Ищите правила подключения мощных индуктивных нагрузок.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А в часах батарея автономного питания подключена? Если нет - то стопудово см. ответ №1. 

lex0r
Offline
Зарегистрирован: 09.01.2016

Конечно подключено, дело в том, что летом, когда я только начал все это дело, я пробовал и у меня все абсолютно работало, сейчас через пол года все что я сделал - это спаял, скетч не менял.

bwn
Offline
Зарегистрирован: 25.08.2014

lex0r пишет:

Конечно подключено, дело в том, что летом, когда я только начал все это дело, я пробовал и у меня все абсолютно работало, сейчас через пол года все что я сделал - это спаял, скетч не менял.

Допускаю, что поменяли розетку (питающую линию), поставили другой БП на девайс и т.д.

Проверить достаточно просто, если после reset все работает дальше - висим.

lex0r
Offline
Зарегистрирован: 09.01.2016

Ничего не менял ни бп и тд и тп, после ресета работают и часы и датчик температуры, но вот после выключения релле все зависает, попробую контакты перекинуть на другие 

lex0r
Offline
Зарегистрирован: 09.01.2016

bwn пишет:

lex0r пишет:

Конечно подключено, дело в том, что летом, когда я только начал все это дело, я пробовал и у меня все абсолютно работало, сейчас через пол года все что я сделал - это спаял, скетч не менял.

Допускаю, что поменяли розетку (питающую линию), поставили другой БП на девайс и т.д.

Проверить достаточно просто, если после reset все работает дальше - висим.

Срасибо, что навели на мысль в чем проблема, действительно перебросив управляющие провода на другие входы все заработало, видимо припаял криво ...

bwn
Offline
Зарегистрирован: 25.08.2014

Поставьте параллельно контактам RC цепь, здесь это не раз обсуждалось. Или твердотельное реле вместо вашего. 99% все сразу станет хорошо.

lex0r
Offline
Зарегистрирован: 09.01.2016

Извиняюсь, но я еще таких вещей не понимаю, я начинающий ардуинщик :)

bwn
Offline
Зарегистрирован: 25.08.2014

lex0r пишет:

Извиняюсь, но я еще таких вещей не понимаю, я начинающий ардуинщик :)

А дуина здесь не при чем. Это физика. Рекомендую обновить в голове базовый курс.))))

vk007
Offline
Зарегистрирован: 16.06.2015

У меня тоже недавно какие-то непонятки происходили с ds3231. Но у меня никаких реле нет. В процессе обучения собрал часы на матрицах. Собрано на макетке, питание от usb компьютера (все никак не доведу до полного ума, руки не доходят).

Так вот, выключил комп на ночь, на следующий день включил, а часы отстают минут на 10-15. Померял аккумулятор - норма, за ночь не садится. При этом, что на ночь выключить, что на два дня подряд - уход все те же 10-15 минут. И так за несколько суток набежал почти час. Подкорректировал время и выключил я их недели на две, дал "отстояться". Включил - норма и больше не опаздывают.

Что было? Загадка. Грешу разве что на макетку, но ds3231 вроде как автономное устройство, тикают сами по себе, в скетче ничего в них не пишется, только читается.