Будильник на DS3231

Тема в разделе "Arduino & Shields", создана пользователем Artem88, 20 сен 2015.

  1. Artem88

    Artem88 Нерд

    Расскажите как настроить будильник на модуле DS3231. Планируется сделать так, чтобы arduino uno просыпался один раз в сутки, выполнял необходимые действия и опять засыпал. Про будильник информации очень мало, а самому разобраться не получается.
     
  2. DrProg

    DrProg Вечный нерд

    Именно чтоб "засыпал"? Или чтобы просто выполнял действия раз в сутки?
     
  3. Artem88

    Artem88 Нерд

    Будильник нужен чтобы только разбудить arduino uno, будет опрос датчика один раз в сутки и запись данных на SD-карту.
     
  4. DrProg

    DrProg Вечный нерд

    ИгорьК нравится это.
  5. Alex19

    Alex19 Гуру

    Не работал с данным модулем, только предстоит его приобрести. Прежде всего открываем данный документ - http://datasheets.maximintegrated.com/en/ds/DS3231.pdf, на мой взгляд, это исчерпывающие описание чипа.

    И так, данный модуль имеет возможность устанавливать до 2 будильников в день. На данные будильники можно повесить прерывание, что нам и нужно.

    1. Настраиваем текущее время, нас интересуют регистры 00h - 06h. (формат BCD)
    2. Настраиваем регистры тревоги 1 (Alarm), нас интересуют регистры с 07h - 0Ah. (формат BCD)
    3. Настраиваем модуль, нас интересует регистр 0Eh.

    1. Настройка текущего времени, примеров достаточно много, как вариант этот - http://knodit.blogspot.ru/2014/05/arduino-ds3231-i2c-wire.html (данный вариант не использует библиотек, но и их огромное кол-во).
    2. Настройка, происходит почти так же, лишь с небольшим исключением, старший бит регистров 07h - 0Ah (A1M1 - A1M4) и DY/DT. Настройка сравнений тревоги с текущем временем в таблице 2, документа выше, подробное описание.

    Раз Вам надо включать ардуину раз в день, настройка такая A1M4 = 1, остальные 0.

    3. Настраиваем модуль.
    Регистр 0Eh. Биты A1IE = 1 (разрешаем прерывание, при совпадении с тревогой 1), INTCN = 1 (разрешаем прерывание на ноге INT/SQW).

    Теперь у нас есть прерывание по совпадению таймера, теперь осталось настроить сон или дрему контролера. Вроде ни чего не упустил, модуль очень интересный.

    UPD. Данная библиотека - https://github.com/JChristensen/DS3232RTC, позволяет не только работать с часами, но и задавать тревоги и прерывания. Не вникая в регистры, сам не пробовал, просто пробежался по методам.
     
    Последнее редактирование: 20 сен 2015
    Megakoteyka нравится это.
  6. Artem88

    Artem88 Нерд

  7. Alex19

    Alex19 Гуру

    Мы все когда-то начинаем (я так вечный ученик).

    Просто Вы хотите реализовать спящий режим, поэтому предположил, что Вы умеете работать с I2C без библиотек, поэтому описывал регистры.

    Отлично, Вы нашли рабочую библиотеку.

    Предположу, что у Вас такой модуль
    [​IMG]
    Питание и I2C Вы подключили, раз есть рабочие примеры. Осталось соединить SQW c 2 пином на Ардуине. И запустить пример DS3231_intalarm.

    UPD. Судя по примеру, прерывание будет происходить каждый 10 сек.
    И каждые 10 сек., в мониторе порта Вы увидите - *** INT 0 *** и 4 пин будет дергаться, но Вы его не увидите.
     
    Последнее редактирование: 21 сен 2015
  8. Artem88

    Artem88 Нерд

    Модуль точно такой.

    В мониторе порта непрерывно пишется *** INT 0 ***, светодиод подключенный к пину 4 не загорается. Светодиод подключенный к SQW (2 pin ардуино) отрицательным концом постоянно горит, а если изменить полярность то горит тускло. Может не хватает какой-нибудь команды или ошибка в библиотеке?
     
  9. Alex19

    Alex19 Гуру

    Что-то не так.

    Такое ощущение, что работает не прерывание, а он просто генерирует частоту на выходе.

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

    Сейчас на работе, ближе к вечеру постараюсь разобраться.

    UPD. Появилась минутка, похоже дело в примере.
    Ни где не задается бит INTCN.

    Давайте его установим, после
    Код (C++):
    clock.begin();
    добавим строчку
    Код (C++):
    clock.enableOutput(false);
    Если другие примеры работали, в частности DS3231_alarm.ino, то все должно заработать.
     
    Последнее редактирование: 21 сен 2015
  10. Artem88

    Artem88 Нерд

    Это помогло!
    Код уже стал работоспособен. А вот пример надо еще доработать.
     
  11. Artem88

    Artem88 Нерд

    Код (C++):
    /*
      DS3231: Real-Time Clock. Alarm simple
      Read more: www.jarzebski.pl/arduino/komponenty/zegar-czasu-rzeczywistego-rtc-DS3231.html
      GIT: https://github.com/jarzebski/Arduino-DS3231
      Web: http://www.jarzebski.pl
      (c) 2014 by Korneliusz Jarzebski
    */


    #include <Wire.h>
    #include <DS3231.h>

    DS3231 clock;
    RTCDateTime dt;
    boolean isAlarm = false;
    boolean alarmState = false;
    int alarmLED = 4;

    void alarmFunction()
    {
      Serial.println("*** INT 0 ***");
      isAlarm = true;
    }

    void setup()
    {
      Serial.begin(9600);
     
      // Initialize DS3231
      Serial.println("Initialize DS3231");;
      clock.begin();
      clock.enableOutput(false);
      // Disarm alarms and clear alarms for this example, because alarms is battery backed.
      // Under normal conditions, the settings should be reset after power and restart microcontroller.
      clock.armAlarm1(false);
      clock.armAlarm2(false);
      clock.clearAlarm1();
      clock.clearAlarm2();

      // Manual (Year, Month, Day, Hour, Minute, Second)
      clock.setDateTime(2014, 4, 25, 0, 0, 0);

      // Set Alarm1 - Every 20s in each minute
      // setAlarm1(Date or Day, Hour, Minute, Second, Mode, Armed = true)
      clock.setAlarm1(0, 0, 0, 10, DS3231_MATCH_S);

      // Attach Interrput 0. In Arduino UNO connect DS3231 INT to Arduino Pin 2
      attachInterrupt(0, alarmFunction, FALLING);

      // Setup LED Pin
      pinMode(alarmLED, OUTPUT);
    }

    void loop()
    {
      dt = clock.getDateTime();
      Serial.println(clock.dateFormat("d-m-Y H:i:s - l", dt));

      if (isAlarm)
      {
        digitalWrite(alarmLED, alarmState);
        alarmState = !alarmState;
        clock.clearAlarm1();
        isAlarm = false;
      }

      delay(1000);
    }
     
    Добавил строку
    Код (C++):
    clock.enableOutput(false);
    и
    Код (C++):
    isAlarm = false;
    в конце скетча, без нее светодиод на 4 пине постоянно мигает. А с этой строкой меняет свое состояние при каждом срабатывании будильника.
    Скрин монитора порта:
    DS3231.jpg
     
  12. Alex19

    Alex19 Гуру

    Отлично.

    Бегло ознакомившись с библиотекой, понял, что сама библиотека написана нормально. Проблема только в примерах.

    Вам осталось, лишь задать текущее время, для этого можно воспользоватся примером DS3231_simple. Там время устанавливается автоматически __DATE__, __TIME__. И задать интервал прерываний раз в день, к примеру
    Код (C++):
    clock.setAlarm1(0, 1, 10, 30, DS3231_MATCH_H_M_S);
    в 1 ночи 10 минут 30 сек., каждый день.

    Если нужно задать интервал относительно текущего времени, то получаем значения часов и устанавливаем setAlarm1, примерно так.
    Код (C++):
    RTCDateTime  dt = clock.getDateTime();
    clock.setAlarm1(0, dt.hour, dt.minute, dt.second, DS3231_MATCH_H_M_S);
     
    Возможно потребуется либо дать задержу в 1 секунду, либо отнять секунду, чтобы прерывание не сработало сразу.

    С таймером пожалуй все.

    Тут к сожалению, знаний не хватает, ни когда не требовалось спать:), но в сети полно примеров.
     
    Artem88 нравится это.