Настольные часы-календарь на ds3231mz+ и iskra nano pro с 2 дисплеями.

Тема в разделе "Глядите, что я сделал", создана пользователем issaom, 3 июл 2020.

  1. issaom

    issaom Гуру

    Просто часы-календарь:
    Часы1.JPG
    Часы2.JPG
    Часы3.JPG
    Принципиальная электрическая схема часов:
    Принципиальная электрическая схема часов на Arduino - копия - копия.jpg


    Код (C++):
    #include <SPI.h>
    #include "i25LC512.h"
    #include "ish1106.h"
    #include "iepd4in2.h"
    #include "ish1106Print.h"
    #include "iepd4in2Print.h"
    #include "ianalogButton.h"
    #include "icalendar.h"
    #include <DS3231.h>
    DS3231  rtc(SDA, SCL);
    uint8_t newSec = 0;
    uint8_t oldSec = 0;
    uint8_t oldhour = 25;
    uint8_t newhour = 0;   // e-papir обновится при первом включении

    String TimeShow = "";
    String S = "";
    Time  t;                       // Init a Time-data structure

    #define Bpix 0              // черный пиксел
    #define Wpix 1             // белый пиксел
    #define WGpix 2          // светлосерый пиксел
    #define BGpix 3           // темносерый пиксел
    uint8_t moDe = 0;        // Переключение режимов работы

    unsigned long dotMillis = 0;     // время отрисовки точки
    boolean delDot = false;          // стереть точку?
    uint8_t setMode = 0;             // настройки
    int8_t setValue = 0;            // переменная для настройки
    int8_t setValueOLD = 1;     // переменная для настройки
    uint8_t setHH;                  // установка часов
    uint8_t setMM;                  // установка минут
    uint8_t setSS;                  // установка секунд

    uint8_t setD;                   // установка дня
    uint8_t setM;                   // установка месяца
    uint16_t setY;                  // установка года


    void setup (void)
    {
      Serial.begin(9600);
      iSPI2Init();              // инициализация 2-ого SPI
      iSH1106_begin();   // инициализация дисплея SH1106
      iSH1106_clear();    // очистка видеопамяти OLED
      iClear_4Gray();      // очистка видеопамяти e-papir
      rtc.begin();              // инициализируем часы
    }


    void loop (void)
    {

      // Get data from the DS3231
      t = rtc.getTime();
      newSec = t.sec;
      newhour = t.hour;

      if (setMode == 0) { // режим отображения часов и календаря

        if (newSec != oldSec) {      //прошло больше одной секунды
          iSH1106_clear();
          oldSec = newSec;
          switch (moDe) {
            case 0:                  // отображаем полный формат времени
              TimeShow =  rtc.getTimeStr(FORMAT_LONG);
              iPrintString(8, 0,   TimeShow , &iFont22, 1, 0);
              break;
            case 1:                 // отображаем только часы минуты и мигаем
              dotMillis = millis(); // время отображения точки
              delDot = true;        // стереть двоеточие через 0.5сек
              TimeShow =  rtc.getTimeStr(FORMAT_SHORT);
              iPrintString(13, 0,   TimeShow , &iFont32, 1, 0);
              break;
            case 2:
              // отображаем только часы минуты и не мигаем
              TimeShow =  rtc.getTimeStr(FORMAT_SHORT);
              iPrintString(13, 0,   TimeShow , &iFont32, 1, 0);
              break;
          }
          //отображаем температуру из DS3231
          S = "";
          S = "Темпер+";
          uint8_t i = round(rtc.getTemp());
          S = S + i + 'C';
          iPrintString(0, 35,   S , &iFont16, 1, 0);
          iSH1106ShowMem ();
        }

        //обновляем e-papier 1 раз в час
        if (newhour != oldhour) {
          oldhour = newhour;
          // процедура отрисовки календаря
          iInit_4Gray();                          // инициализация дисплея 4.2
          iClear_4Gray();                         // очистка видеопамяти
          icalendarPrint(t.date, t.mon, t.year);  // отображение календаря  DD.MM.YYYY
          iSet_4GrayDisplay();                    // отображение видеопамяти
          iSleep();                               // глубокий сон
        }

        // сброс точки
        if ((millis() - dotMillis  >= 500) && (delDot)) {         // если прошло более 0.5 сек
          delDot = false;
          // стираем точку
          //    iSH1106_clear();
          TimeShow =  rtc.getTimeStr(FORMAT_SHORT);
          TimeShow.replace(":", ".");
          iPrintString(13, 0,   TimeShow , &iFont32, 1, 0);
          iSH1106ShowMem ();
        }
      }


      AB = GetAB();                   // читаем значение кнопки
      if (AB == 0) ABOld = 0;         // все кнопки отпущены
      if (AB != ABOld) {              // клацнули какую то кнопку
        ABOld = AB;                   // запоминаем значение кнопки
        if (AB == 1) setValue++;      // кнопка установка +1
        if (AB == 2) setValue--;      // кнопка установка -1
        if (AB == 3) {                // кнопка резервная

        }
        if (AB == 4) {
          setMode++;                    // кнопка настроек
          if (setMode > 8) setMode = 0; // обычный режим
          setValue = 0;                 // переменная для настройки
          setValueOLD = 1;              // переменная для настройки
        }

        if (AB == 5) {
          setMode = 0;     // выход из режима настройки если случайно клацнули
          moDe++;           // кнопка переключения режимов
          if (moDe > 2) moDe = 0;
        }
      }

      if ((setMode == 1) && (setValue != setValueOLD)) {
        setValueOLD = setValue;
        iSH1106_clear();
        setHH = t.hour + setValue;
        S = "Часы " + String(setHH);
        iPrintString(0, 0, S , &iFont16, 1, 0);
        iSH1106ShowMem ();
      }

      if ((setMode == 2) && (setValue != setValueOLD)) {
        setValueOLD = setValue;
        iSH1106_clear();
        setMM = t.min + setValue;
        S = "Минуты " + String(setMM);
        iPrintString(0, 0, S , &iFont16, 1, 0);
        iSH1106ShowMem ();
      }

      if ((setMode == 3) && (setValue != setValueOLD)) {
        setValueOLD = setValue;
        iSH1106_clear();
        setSS = setValue;
        S = "Секунды " + String(setSS);
        iPrintString(0, 0, S , &iFont16, 1, 0);
        iSH1106ShowMem ();
      }

      if ((setMode == 4) && (setValue != setValueOLD)) {
        rtc.setTime(setHH, setMM, setSS);
        setValueOLD = setValue;
        iSH1106_clear();
        S = "Время ОК";
        iPrintString(0, 0, S , &iFont16, 1, 0);
        iSH1106ShowMem ();
      }

      if ((setMode == 5) && (setValue != setValueOLD)) {
        setValueOLD = setValue;
        iSH1106_clear();
        setD = t.date + setValue;
        S = "Дата " + String(setD);
        iPrintString(0, 0, S , &iFont16, 1, 0);
        iSH1106ShowMem ();
      }

      if ((setMode == 6) && (setValue != setValueOLD)) {
        setValueOLD = setValue;
        iSH1106_clear();
        setM = t.mon + setValue;
        S = "Месяц " + String(setM);
        iPrintString(0, 0, S , &iFont16, 1, 0);
        iSH1106ShowMem ();
      }

      if ((setMode == 7) && (setValue != setValueOLD)) {
        setValueOLD = setValue;
        iSH1106_clear();
        setY = t.year + setValue;
        S = "Год " + String(setY);
        iPrintString(0, 0, S , &iFont16, 1, 0);
        iSH1106ShowMem ();
      }

      if ((setMode == 8) && (setValue != setValueOLD)) {
        rtc.setDate(setD, setM, setY);
        setValueOLD = setValue;
        iSH1106_clear();
        S = "Дата ОК";
        iPrintString(0, 0, S , &iFont16, 1, 0);
        iSH1106ShowMem ();
      }

    }
    БИБЛИОТЕКИ ДЛЯ РАБОТЫ С ДИСПЛЕЯМИ НЕ ИСПОЛЬЗУЮТСЯ! - поэтому все остальное кому интересно смотрите в архиве.
    CalendarClock.zip
    Небольшой видосик про настройку и работу часов:

     

    Вложения:

    OldKryptos, Un_ka, SergeiL и 3 другим нравится это.
  2. Daniil

    Daniil Гуру

    Жду барометр)
    может ардуину усыплять, чтобы 1 раз в день обновляла экран без питания?
    А эл.бумаге столько свободного место или это заводская рамка? Я бы все сделал на эл.бумаге.
     
  3. issaom

    issaom Гуру

    Эта модель не умеет обновляться частично-кусочно.... больно уж сильно она моргает при обновлении. Раз в час нормально (как часы с кукушкой) а раз минуту уже будет переборщ.... Тут другой дисплей нужен - там можно не весь экран передергивать а только некоторые пикселы. ))) И там уже проще голый МК взять и сделать на батарейках )))
     
    SergeiL, Daniil и NikitOS нравится это.
  4. Tomasina

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

    MZ как себя ведёт, не отстаёт?
     
    Andrey12 нравится это.
  5. issaom

    issaom Гуру

    Я проверю - отпишусь - пока глюков не наблюдается.
     
  6. parovoZZ

    parovoZZ Гуру

    Прикона.
    Но это как трактор беларусь с колесом от жигулей. Зачем OLED, если рядом электронные чернила? Зачем чернила, если рядом OLED?
     
  7. Andrey12

    Andrey12 Гик

    Были проблемы?
    У меня из 2х разных партий глючат одинаково. Отстают сильно, и температуру выдают не адекватную. Грешу на то что на али продают отбраковку. Пока вернулся назад на SN.
     
  8. issaom

    issaom Гуру

    Ну... с температурой у меня тоже есть вопросы - хотя я так понимаю для измерения температуры он и не предназначен..... А часы пока ходят точно....

    Патамучто чернила обновляются более 4 секунд и вывести на него например секунды не получится, и моргает он сильно - конкретно эта модель подходит только как информационная панель с нечастым обновлением - за то она бАлшая и не светит в физиономию.
     
    Последнее редактирование модератором: 14 июл 2020
    Andrey12 нравится это.
  9. Andrey12

    Andrey12 Гик

    У меня с 29го мая отстали больше чем на час, видимо партия какая о бракованная
     
  10. SergeiL

    SergeiL Оракул Модератор

    А с ESP8266 и NTP можно было бы отказаться от DS3231, да и от кнопок тоже ;)
     
  11. issaom

    issaom Гуру

    Чето я дико торможу - а сколько в ESP8266 оперативы ?
     
  12. Un_ka

    Un_ka Гуру

    источник.
     
  13. issaom

    issaom Гуру

    Там вот так получится сделать или нет ? uint8_t disp [30000] с учетом каких-нибудь Wi-Fi плюшек ?
     
  14. parovoZZ

    parovoZZ Гуру

    У меня часы из IKEA made in Belarus за месяц максимум минуту накручивают. Связываю с тем, что висят на кухне, ну и с просадкой батарейки.
     
  15. SergeiL

    SergeiL Оракул Модератор

    По сравнению с Мегой, памяти там дохрена ;)
    Пределов еще не достигал, обычно получается как то так:
    Код (Text):
    Скетч использует 331684 байт (31%) памяти устройства. Всего доступно 1044464 байт.
    Глобальные переменные используют 31360 байт (38%) динамической памяти, оставляя 50560 байт для локальных переменных. Максимум: 81920 байт.
     
  16. SergeiL

    SergeiL Оракул Модератор

    По точности DS3231SN.
    Сейчас проверил свои часы, стоящие на шкафу в коридоре.
    время в DS3231SN было загружено 9 сентября 2017-го года. Писал тут
    После этого время только читалось, когда не было NTP при старте.
    А так они по NTP синхронизируются, показывают время и температуру с уличной ESP.
    Снял, подключил к компу - разница между получаемым временем по NTP и времени с DS3231SN 42 секунды.
    DS-ка убежала вперед на 42 секунды (Там, где "NTP Time" начало минуты по NTP) :
    Код (Text):
    Tempr is : 20.62
    #
    6.07.20 18:14:40
    6.07.20 18:14:41
    6.07.20 18:14:42
    NTP Time: 18:14
    6.07.20 18:14:43
    6.07.20 18:14:44
    6.07.20 18:14:45
     
  17. b707

    b707 Гуру

    а по коду замечания нужны?
     
  18. issaom

    issaom Гуру

    Дык конечно )))
     
  19. ANV

    ANV Гуру

    Интересный проект
    По мелочи:
    - Просится корпус
    - Синхронизация секунд (они то замирают, то быстро две проскакивают). Если лениво и паяете быстрее, чем думаете, то задействуйте секундный выход с часов
    - ощущение что календарь не всю активную площадь экрана использует
    - «темпер» - лучше убрать и так ясно что это температура, либо если планируется ещё уличный термометр, то замените на иконку домика
     
    issaom нравится это.
  20. b707

    b707 Гуру

    я бы вот эти 8 почти одинаковых if
    Код (C++):
     if ((setMode == 1) && (setValue != setValueOLD)) {
        setValueOLD = setValue;
        iSH1106_clear();
        setHH = t.hour + setValue;
        S = "Часы " + String(setHH);
        iPrintString(0, 0, S , &iFont16, 1, 0);
        iSH1106ShowMem ();
      }

      if ((setMode == 2) && (setValue != setValueOLD)) {
        setValueOLD = setValue;
        iSH1106_clear();
        setMM = t.min + setValue;
        S = "Минуты " + String(setMM);
        iPrintString(0, 0, S , &iFont16, 1, 0);
        iSH1106ShowMem ();
      }

      if ((setMode == 3) && (setValue != setValueOLD)) {
        setValueOLD = setValue;
        iSH1106_clear();
        setSS = setValue;
        S = "Секунды " + String(setSS);
        iPrintString(0, 0, S , &iFont16, 1, 0);
        iSH1106ShowMem ();
      }

      if ((setMode == 4) && (setValue != setValueOLD)) {
        rtc.setTime(setHH, setMM, setSS);
        setValueOLD = setValue;
        iSH1106_clear();
        S = "Время ОК";
        iPrintString(0, 0, S , &iFont16, 1, 0);
        iSH1106ShowMem ();
      }

      if ((setMode == 5) && (setValue != setValueOLD)) {
        setValueOLD = setValue;
        iSH1106_clear();
        setD = t.date + setValue;
        S = "Дата " + String(setD);
        iPrintString(0, 0, S , &iFont16, 1, 0);
        iSH1106ShowMem ();
      }

      if ((setMode == 6) && (setValue != setValueOLD)) {
        setValueOLD = setValue;
        iSH1106_clear();
        setM = t.mon + setValue;
        S = "Месяц " + String(setM);
        iPrintString(0, 0, S , &iFont16, 1, 0);
        iSH1106ShowMem ();
      }

      if ((setMode == 7) && (setValue != setValueOLD)) {
        setValueOLD = setValue;
        iSH1106_clear();
        setY = t.year + setValue;
        S = "Год " + String(setY);
        iPrintString(0, 0, S , &iFont16, 1, 0);
        iSH1106ShowMem ();
      }

      if ((setMode == 8) && (setValue != setValueOLD)) {
        rtc.setDate(setD, setM, setY);
        setValueOLD = setValue;
        iSH1106_clear();
        S = "Дата ОК";
        iPrintString(0, 0, S , &iFont16, 1, 0);
        iSH1106ShowMem ();
      }
    переписал бы так:
    Код (C++):
     if  (setValue != setValueOLD) {
       switch (setMode) {
        case 1:
          setHH = t.hour + setValue;
          S = "Часы " + String(setHH);
          break;
       case 2:
          setMM = t.min + setValue;
          S = "Минуты " + String(setMM);
          break;
       case 3:
         
       ......
      }
        setValueOLD = setValue;
        iSH1106_clear();
        iPrintString(0, 0, S , &iFont16, 1, 0);
        iSH1106ShowMem ();
      }
     
    DetSimen, Daniil и issaom нравится это.