Часы ds 3231

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

  1. Securbond

    Securbond Гуру

    Если в скетче вы пишете Serial.println то разумеется он будет сыпать время каждый раз проходя loop
     
  2. uvarofff

    uvarofff Нуб

    да и пусть себе сыпет, вопрос в другом - как избежать морганий диода, и почему спустя минуту диод всё таки гаснет.
     
  3. Securbond

    Securbond Гуру

    Попробуйте добавить еще одну переменную. Если время включить, присваиваем переменной 1. Если время выключить то 0. Т в цикле включить реле если переменная =1 и выключить если переменная = 0.
     
  4. uvarofff

    uvarofff Нуб

    Всем спасибо за советы. Несколько своих ошибок я исправил, но всё равно, к желаемому результату не пришёл. Решил плюнуть на это дело и найти уже рабочий скетч.

    P.S

    //Serial.println(time.gettime("d-m-Y, H:i:s, D")); // выводим время
    //delay(1); // приостанавливаем на 1 мс, чтоб не выводить время несколько раз за 1мс
    //если закомментировать строки выше, то диод горит ярко (и без миганий, так как убрать delay(1000) в качестве паузы между выводом показаний в serial)

    tmp_h = time.Hours;
    tmp_m = time.minutes;
    tmp_s = time.seconds;

    if (tmp_h>=11 && tmp_m>=17) { //заменил == на >= для корректного включения диода даже после условного времени.
    //Включаем в 7 утра
    digitalWrite(lamp, HIGH);
    }

    if (tmp_h>=19 && tmp_m>=00); { //по идее, 19>11 и после 19.00 условие будет действовать
    //Выключаем в 7 вечера
    digitalWrite(lamp, LOW);
    }
     
    Последнее редактирование: 14 дек 2016
  5. Securbond

    Securbond Гуру

    Как вам такие часики :D

     
    vvr нравится это.
  6. uvarofff

    uvarofff Нуб

    Рабочего скетча так и не нашёл, зато написал свой.
    Делюсь, может кому пригодиться. Там два варианта - один понятный, второй короткий.

    void loop() {

    Serial.println(time.gettime("d-m-Y, H:i:s, D")); // выводим время
    delay(1000); // приостанавливаем на 1с, чтоб не выводить время несколько раз за 1с

    tmp_h = time.Hours;
    tmp_m = time.minutes;
    tmp_s = time.seconds;

    // короткий
    if (H_off<=tmp_h || tmp_h<H_on) //tmp_h = 18.59 h_off = 19 h_on = 17 светит с 19 до 17 часов.
    digitalWrite(lamp, HIGH);
    else
    digitalWrite(lamp, LOW);

    //стопудово рабочий вариант (понятный)
    //if (tmp_h >= H_off && tmp_m >= M_off)
    //digitalWrite(lamp, LOW);
    //if (tmp_h < H_off)
    //digitalWrite(lamp, HIGH);


    Критика приветствуется.
     
  7. Tomasina

    Tomasina Сушитель лампочек Модератор

    Использую библиотеку RtcDS3231 (https://github.com/Makuna/Rtc).
    При перепрошивке текущее время с компа записывается корректно, но после отключения питания и последующего включения отсчет продолжается с момента отключения, т.е. если отключаю питание в 19:40, а включаю в 9:15, то время в МК становится 19:41, тогда как должно быть 9:15.
    В каком направлении копать?

    Как вообще реализовать следующую логику работы (без дальнейшего вмешательства в скетч, если понадобится изменить время)?
    * после каждой перепрошивки дата и время берутся из компа (время компиляции) и принудительно записываются в RTC.
    * Далее при каждом включении питания (кроме перепрошивки) дата и время берется из RTC.
    * При ручном задании обновленные дата и время записываются в RTC.
    Т.е. по отдельности каждый пункт я знаю как сделать, а вот как логика комплексной работы пока недоступна. Вчерне так: при прошивке ставить флаг "0" в EEPROM (как это сделать однократно, только при прошивке, а не после каждого вызова setup?), далее в setup смотреть его состояние и ветка на два направления.
     
    Последнее редактирование: 1 мар 2017
  8. rf68

    rf68 Нерд

    Код (C++):
    //Подключаем библиотеки для работы часов реального времени

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

    // выводы для дешифратора
      int out1 = A3;
      int out2 = A1;
      int out4 = A0;
      int out8 = A2;
    // выводы для транзисторных ключей
      int key1= 4;
      int key2 = 6;
      int key3 = 7;
      int key4 = 8;

      int led1=11;// вывод светодиода
      int keyb=A6;// пин для клавиатуры


      int keynum=0; //номер нажатой кнопки
      int mode =0; //0 - отображение текущего времени 1- установка времени
      int currentdigit = 0; //0 - установка часов 1- установка минут
      bool blinkflag = 0; // флаг для мигания цифр при установке времени
      bool timeout=false; // таймаут после нажатия кнопки (для устраниния дребезга)
      unsigned long startTime; //для мигания светодиода
      unsigned long startTime2; // для опроса нажатых кнопок
      int sec; //переменная увеличивается каждые 500мс на единицу. Нужна для мигания секундных светодиодов, бывает в двух значениях 0 - светодиоды не горят, 1 - горят, если больше 1, то сбрысывается в 0

      // переменные, необходимые для работы ds3231
      DS3231 Clock;
      bool Century=false;
      bool h12;
      bool PM;
      byte ADay, AHour, AMinute, ASecond, ABits;
      bool ADy, A12h, Apm;

      //определяем глобальные переменные для различных параметров часов
      int second,minute,hour,date,month,year,temperature;


    void setup() {
      // put your setup code here, to run once:
      // задаем частоту ШИМ на 9 выводе 30кГц
      TCCR1B=TCCR1B&0b11111000|0x01;
      analogWrite(9,130);

        // Start the I2C interface
      Wire.begin();
      // Start the serial interface
      Serial.begin(9600);
     
      //задаем режим работы выходов микроконтроллера
      pinMode(out1,OUTPUT);
      pinMode(out2,OUTPUT);
      pinMode(out4,OUTPUT);
      pinMode(out8,OUTPUT);

      pinMode(key1,OUTPUT);
      pinMode(key2,OUTPUT);
      pinMode(key3,OUTPUT);
      pinMode(key4,OUTPUT);

      pinMode(led1,OUTPUT);

      startTime = millis();
      startTime2=startTime;
      sec = 0;
      // считываем текущее вермя
      ReadDS3231();
    }

    void ReadDS3231()   //функция считывает в глобальные переменные minute и hour текущие значения
    {
      minute=Clock.getMinute();
      hour=Clock.getHour(h12, PM);
    }


    void loop() {
      // put your main code here, to run repeatedly:
     
      int digits[3]; // массив для текущего значения времени на четыре цифры
      int keyval= analogRead(keyb); // считываем значение с клавиатуры
     
      unsigned long currentTime = millis(); //текущее время с момента запуска рограммы
       if (currentTime>=(startTime2+200)) // если прошло 200мс посмотрим какая кнопка была нажата
       {
          timeout=false;
         //проверим нажатие кнопок
          if (keynum==3) // кнопка переключения между режимами "время" и "настройка"
          {
            timeout=true; // запрещаем считывать нажатия кнопок
            if (mode==0) mode=1; // если отображалось время, переходим в режим настроек
            else
              if (mode==1) mode=0; //если был режим настроек, переключаемся на текущее время
          }
          if (keynum==2) // кнопка переключения между часами и минутами
          {
            timeout=true; // запрещаем считывать нажатия кнопок
            // currentdigit либо 0 - настройка часов, либо 1 - настройка минут
            currentdigit++;
            if (currentdigit==2) currentdigit=0;
          }
          if (keynum==1) // кнопка увеличения количества часов или минут(при настройке)
          {
            blinkflag=true; // прекращаем мигать цифрами
            startTime=millis();
            timeout=true;  // запрещаем считывать нажатия кнопок
            if (currentdigit==0) // если меняем часы
            {
              if (hour<=22) hour++;
              else
                hour=0;
              Clock.setHour(hour);
            }
            if (currentdigit==1) // если меняем минуты
            {
              if (minute<=58) minute++;
              else
                minute=0;
             Clock.setMinute(minute);//Set the minute
             Clock.setSecond(0);
            }
          }
          keynum=0; //сбрасываем нажатую кнопку
          startTime2=millis();
       }

      if (currentTime>=(startTime+500)) // если прошло 500мс
      {
        blinkflag=!blinkflag; // инвертируем флаг мигающей цифры
         
        if(sec<1) // светодиоды не горят
        {
          // зажечь светодиоды
          digitalWrite(led1,HIGH);
          Serial.println(blinkflag);
         
        }
        if(sec>=1) // светодиоды горят
        {
          // потушить светодиоды
          digitalWrite(led1,LOW);
        }
        startTime = currentTime;
        ReadDS3231();
        sec = (sec+1);
        if(sec>=2) sec=0;

      }
        digits[0] = hour/10;
        digits[1] = hour%10;
        digits[2] = minute/10;
        digits[3] = minute%10;

        show(digits); // вывести цифры на дисплей

      //проверяем нажатые кнопки
      if(!timeout) //если разрешено, считываем нажатую кнопку
      {
        /*keyval - значение функции analogread
         * если нажата первая кнопка, то принимает значение около 200
         * если нажата вторая кнопка то значение около 700
         * если третяя кнопка, то значение будет около 1000
         * эти значения зависят от выбранных резисторов в клавиатуре
        */

        if (keyval>150 && keyval<400) keynum=1;
        if (keyval>700 && keyval<900) keynum=2;
        if (keyval>960) keynum=3;
      }
    }
    void show(int a[])
    {
        //выведем цифру a[0] на первый индикатор
      setNumber(a[0]);
      if (!(mode==1&&currentdigit==0&&blinkflag==false)) //если мы в режиме настройки и происходит настройка часов, то в первая цифра будет мигать
      {
        digitalWrite(key1,HIGH);
        delay(2);
        //потушим первый индикатор
        digitalWrite(key1,LOW);
        delay(1);
      }
     
      //цифра a[1] на второй индикатор
      setNumber(a[1]);
      if (!(mode==1&&currentdigit==0&&blinkflag==false))
      {
      digitalWrite(key2,HIGH);
      delay(2);
      //потушим второй индикатор
      digitalWrite(key2,LOW);
      delay(1);
      }

      //цифра a[2] на третий индикатор
      setNumber(a[2]);
      if (!(mode==1&&currentdigit==1&&blinkflag==false))
      {
      digitalWrite(key3,HIGH);
      delay(2);
      //потушим третий индикатор
      digitalWrite(key3,LOW);
      delay(1);
      }

      //выведем цифру a[3] на четвертый индикатор
      setNumber(a[3]);
      if (!(mode==1&&currentdigit==1&&blinkflag==false))
      {
      digitalWrite(key4,HIGH);
      delay(2);
      //потушим четвертый индикатор
      digitalWrite(key4,LOW);
      delay(1);
      }
    }
    // передача цифры на дешифратор
    void setNumber(int num)
    {
      switch (num)
      {
        case 0:
        digitalWrite (out1,LOW);
        digitalWrite (out2,LOW);
        digitalWrite (out4,LOW);
        digitalWrite (out8,LOW);
        break;
        case 1:
        digitalWrite (out1,HIGH);
        digitalWrite (out2,LOW);
        digitalWrite (out4,LOW);
        digitalWrite (out8,LOW);
        break;
        case 2:
        digitalWrite (out1,LOW);
        digitalWrite (out2,HIGH);
        digitalWrite (out4,LOW);
        digitalWrite (out8,LOW);
        break;
        case 3:
        digitalWrite (out1,HIGH);
        digitalWrite (out2,HIGH);
        digitalWrite (out4,LOW);
        digitalWrite (out8,LOW);
        break;
        case 4:
        digitalWrite (out1,LOW);
        digitalWrite (out2,LOW);
        digitalWrite (out4,HIGH);
        digitalWrite (out8,LOW);
        break;
        case 5:
        digitalWrite (out1,HIGH);
        digitalWrite (out2,LOW);
        digitalWrite (out4,HIGH);
        digitalWrite (out8,LOW);
        break;
        case 6:
        digitalWrite (out1,LOW);
        digitalWrite (out2,HIGH);
        digitalWrite (out4,HIGH);
        digitalWrite (out8,LOW);
        break;
        case 7:
        digitalWrite (out1,HIGH);
        digitalWrite (out2,HIGH);
        digitalWrite (out4,HIGH);
        digitalWrite (out8,LOW);
        break;
        case 8:
        digitalWrite (out1,LOW);
        digitalWrite (out2,LOW);
        digitalWrite (out4,LOW);
        digitalWrite (out8,HIGH);
        break;
        case 9:
        digitalWrite (out1,HIGH);
        digitalWrite (out2,LOW);
        digitalWrite (out4,LOW);
        digitalWrite (out8,HIGH);
        break;
      }
    }
    Народ помогите!!! С ардуино первый раз. Собрал часы http://itworkclub.ru/arduino-часы-на-газоразрядных-индикаторах/. Отстают за минуту секунд на 15. Не могу вставить антиотравление.
     
  9. fogary

    fogary Гик

    Если без индикации, кнопок и прочего, только вывод в serial - часы (RTC) идут правильно, или то же отстают?

    По коду. Вот в этом месте возможна опечатка:
    Код (C++):
    int digits[3]; // массив для текущего значения времени на четыре цифры
    Массив заявляете на четыре значения, а объявляете на три.
     
  10. rf68

    rf68 Нерд

     
  11. rf68

    rf68 Нерд

    часы (RTC) идут правильно, отстают после подключения к основной схеме
     
  12. rf68

    rf68 Нерд

    int digits[4 ] - 15 секунд за минуту
     
  13. fogary

    fogary Гик

    Поизучал код - просто фиэрия какая-то. :eek:

    Может знаете для чего используется конструкция на подобия этой:
    Код (C++):
      if (!(mode==1&&currentdigit==0&&blinkflag==false))
      {
      digitalWrite(key2,HIGH);
      delay(2);
      //потушим второй индикатор
      digitalWrite(key2,LOW);
      delay(1);
      }
    Только для мигания цифрой в режиме настройки, или для регенерации значений индикатора?

    Раз часы сами по себе идут правильно, то попробуйте теперь просто выводить значение времени на индикаторы. Т. е. без кнопок и функции настроек. Например, с такой функцией loop():
    Код (C++):
    void loop() {
      static unsigned long currentTime = 0;
      int digits[4];
     
      if (millis() - currentTime >= 500) // если прошло 0,5с
      {
        digitalWrite(led1, !digitalRead(led1)); // мигнуть светодиодом
        currentTime = millis();
        ReadDS3231();
        digits[0] = hour/10;
        digits[1] = hour%10;
        digits[2] = minute/10;
        digits[3] = minute%10;
        show(digits); // вывести цифры на дисплей
      }
    }
     
  14. rf68

    rf68 Нерд

    Добавил Вашу функцию, результат тот-же. Так понимаю нужна или другая ардуина или другая схема?
     
  15. rf68

    rf68 Нерд

    Пардон, не добавил, а заменил void loop
     
  16. fogary

    fogary Гик

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

    По первому куску кода, я так понимаю Вы ничего сказать не можете?
    Допустим, что этот кусок нужен только для мигания цифр. Тогда, можете попробовать такой код?
    Код (C++):
    void loop() {
      static unsigned long currentTime = 0;

      if (millis() - currentTime >= 1000) // если прошла 1с
      {
        digitalWrite(led1, !digitalRead(led1));
        currentTime = millis();
        ReadDS3231();
        setNumber(hour/10);
        setNumber(hour%10);
        setNumber(minute/10);
        setNumber(minute%10);
      }
    }
    Если после включения цифры гореть не будут, то попробуйте добавить в конец setup() строчки:
    Код (C++):
    digitalWrite(key1,HIGH);
    digitalWrite(key2,HIGH);
    digitalWrite(key3,HIGH);
    digitalWrite(key4,HIGH);
    Позвольте глупый вопрос. Отстают на 15 сек за 1 мин - это значит, что в реальности проходит 5 минут, а часы отсчитывают только 4 минуты? Или значение минут сменяются на 15 секунд позже чем в "эталонных" часах?
     
    Последнее редактирование: 22 мар 2017
  17. rf68

    rf68 Нерд

    Значение минут сменяется примерно на 15 секунд позже. По куску кода, указанному выше -без понятия. Библиотеку прилагаю. Спасибо за терпение....
     

    Вложения:

    • DS3231.zip
      Размер файла:
      378,7 КБ
      Просмотров:
      409
  18. fogary

    fogary Гик

    Посмотрел примеры к библиотеке, сразу заметил несоответствие с Вашим кодом.
    Согласно примеру, объявление и инициализация объекта Clock должны выглядеть так:
    Код (C++):
    . . .
    DS3231  Clock(SDA, SCL);
    . . .
    void setup() {
      . . .
      Clock.begin();
      . . .
    }
    Функции getHour() и getMinute() в библиотеке вовсе отсутствуют. Вместо этого, если нужны числовые значения даты и времени, есть функция getTime(), которая записывает значения в структуру Time. Для получения даты или времени в текстовом формате, в библиотеке есть функции getDateStr() и getTimeStr().

    Т. е. в вашем случае, вместо int minute, hour; нужно объявить, например, переменную Time cur_time; и все вызовы функции ReadDS3231() заменить на:
    Код (C++):
    cur_time = Clock.getTime();
    Так же, заменить minute и hour на cur_time.min и cur_time.hour ответственно.

    Либо, если не хотите заморачиваться, изменить функцию ReadDS3231():
    Код (C++):
    void ReadDS3231()
    {
      cur_time = Clock.getTime();
      minute = cur_time.min;
      hour = cur_time.hour;
    }
    PS Странно, что код вообще компилировался.
     
  19. rf68

    rf68 Нерд

    void ReadDS3231() //функция считывает в глобальные переменные minute и hour текущие значения
    {
    cur_time = Clock.getTime();
    minute = cur_time.min;
    hour = cur_time.hour;
    }
    ошибка
    75:error: 'cur_time' was not declared in this scope
    :75: error: 'class DS3231' has no member named 'getTime'

    Библиотека с официального сайта не компилировалась.
    Из кучи скачанных из инета подошла только выше указанная
     
  20. fogary

    fogary Гик

    Либо перед setup() добавьте строчку:
    Код (C++):
    Time cur_time;
    или в функции поправьте:
    Код (C++):
    Time cur_time = Clock.getTime();
    Но, судя по тексту ошибки, Вы дали ссылку не на ту библиотеку. Название библиотек совпадают, а содержимое разное. Посмотрите примеры к библиотеки, которая установлена конкретно у Вас. Возможно упущены какие-то нюансы.

    Заодно убедитесь, что время в часах выставлено правильное. В исходном коде, при установки значений минут, значение секунд сбрасывается на "0". Может, пока выставляли минуты, секунды и сбились.
    Код (C++):
    if (currentdigit==1) // если меняем минуты
            {
              if (minute<=58) minute++;
              else
                minute=0;
             Clock.setMinute(minute);//Set the minute
             Clock.setSecond(0);
            }