Сверх-точные часы и термометр на Arduino

Тема в разделе "Arduino & Shields", создана пользователем A1209, 3 апр 2016.

  1. A1209

    A1209 Нуб

    Всем привет!
    Моя просьба прежде всего обращена к программистам т.к. сам в этом деле полный ноль!!! Могу спаять, прошить а вот программировать...... %)!!!
    Суть проблемы заключается в следующем:
    Бабушка из деревни, по причине плохого зрения, попросила "Собрать часы с БОЛЬШИМИ ЦИФРАМИ и чтобы шли хорошо".
    Погуглив наткнулся на проект http://student-proger.ru/2014....vremenihttp://student-proger.ru/2015/11/svetodiodnye-chasy-2-0-temperatura/
    Собрал его, правда вместо светодиодной ленты использовал светодиодные индикаторы на 8 дюймов, слегка изменив ключи сегментов на КТ315 вместо ULN2003a (не запустилась).
    Часы идут отлично, но:
    1. При подаче питания сразу обращение к интернету за синхронизацией (в деревне такое чудо отсутствует)
    2. Когда часы синхронизировались инет можно отключить до следующей синхронизации, а она происходит раз в сутки.
    3. Да и жалко в таком девайсе оставлять Arduino UNO, Ethernet-shield Wiznet W5100 когда можно собрать на Arduino NANO и DS3231.
    Итого просьба заключается в том, чтобы отключить полностью интернет и убрать Ethernet-shield Wiznet W5100.
    С уважением!!!
     

    Вложения:

  2. ostrov

    ostrov Гуру

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

    Что до синхронизации, то может исключить ее из программы вообще? Синхронизировать вручную по случаю.
     
  3. Airbus

    Airbus Радиохулиган Модератор

    Просто идеальные часы для Бабушек а также для тех кто умеет паять прошивать но не умеет программировать!
     
  4. A1209

    A1209 Нуб

    Да, нужно ее исключить. А модуль DS3231 уже синхронизирован. Как обещает производитель 2мин в год вполне достаточно. Ленты я заменил на большие индикаторы KEM-18102AR 38х56мм, 1 знак, высота зн. 45мм
     
  5. ostrov

    ostrov Гуру

    Индикаторы тоже каждая цифра отдельно рисуется или таки динамически?

    Из той программы что по ссылке исключить все лишнее сами не сможете?
     
  6. A1209

    A1209 Нуб

    Цифры передаются по шине SDA SCL которая собрана на четырех PCF8574. Индикация динамическая, т.е. первый 0 не светится. Рисует к примеру "8:15" а не "08:15".
    К сожалению программист я никакой , исключить обращение к инет сам не смогу.
     
  7. ostrov

    ostrov Гуру

    Динамическая индикация не совсем то что вы наверное думаете. Это поочередное высвечивание цифр каждого разряда при отключении остальных. Смена происходит очень быстро (при правильной программе несколько тысяч раз в секунду) и все выглядит очень гладко. Преимущество такого подключения: для индикации 4 разрядов нужно всего 11 ножек + 1 ножка на разделительные точки, если они нужны. То есть, либо напрямую с МК формировать можно, либо через пару сдвиговых регистров типа 74HC595 (с запасом), и проводов меньше надо будет намного и пайки. Отображать ноль или нет дело хозяйское, это в программе устраивается.

    Да, и еще замечание, для вывода на большие индикаторы силы тока на ножках МК может и не хватить. Я использовал микросхему ULN2003A (сборка из 7 транзисторов Дарлингтона), которая легко решила эту проблему .
     
    Последнее редактирование: 4 апр 2016
  8. A1209

    A1209 Нуб

    Между контроллером и блоком индикации идет два провода SDA и SCL подключены соответственно к А4 иА5 Ардуинки. Блок индикации на четырех PCF8574 по микросхеме на цифру. Каждый сегмент индикатора подключен к своему пину микросхемы.
     
  9. A1209

    A1209 Нуб

  10. A1209

    A1209 Нуб

  11. ostrov

    ostrov Гуру

    Это стандартная схема: один драйвер - один индикатор. Да еще и часы на этой шине. Я так стараюсь не делать.
     
  12. A1209

    A1209 Нуб

    Уже все собрано, работает. Только синхронизация все портит.
     
  13. ostrov

    ostrov Гуру

    Ну выкинуть из программы лишнее не проблема. Могу попробовать, только надо будет проверить, т.к. операция по удалению органов может пройти удачно не с первого раза. )
     
  14. A1209

    A1209 Нуб

    Сделайте пожалуйста, тесты проведу оперативно.
     
  15. ostrov

    ostrov Гуру

    Текст из первой ссылки? Или вы его под себя правили как то?
     
  16. A1209

    A1209 Нуб

    Единственно добавил время между синхронизациями и свои адреса микросхем PCF8574. Остальное не трогал.
     
  17. ostrov

    ostrov Гуру

    Понятно. Ладно я попробую сейчас, но надо будет проверить сразу, потому что я даже скомпилировать не смогу, нет библиотек.
     
  18. A1209

    A1209 Нуб

    Ок! Жду
     
  19. ostrov

    ostrov Гуру

    Кстати, если не нужен перфекционизм, то достаточно просто закаментить или удалить этот кусок в loop:
    Код (C++):
    if (TimeSync.check() == 1) //Синхронизация по времени
      {
        //Запрашиваем время с NTP сервера
        setSyncProvider(getNtpTime);
        //Если время получили успешно, то записываем данные в RTC
        if (timeStatus() != timeNotSet)
        {
          RTC.set(now());
        }
      }
    И оно не будет синхронизироваться. Но, по уму, надо конечно все лишнее вырезать.
     
  20. ostrov

    ostrov Гуру

    Попробуйте вот так:
    Код (C++):
    // Скетч для Arduino. Светодиодные часы с синхронизацией.
    // Версия 1.0 (29.07.2014)
    //
    // Автор: Гладышев Дмитрий (2014)
    // http://student-proger.ru/2014/07/arduino-svetodiodnye-chasy-s-sinhronizaciej-vremeni/
    #include <SPI.h>         //для Ethernet-shield
    //#include <Ethernet.h>    //   --//--
    //#include <EthernetUdp.h>
    #include <Wire.h>        //I2C для RTC
    #include <DS1307RTC.h>   //RTC
    #include <Time.h>
    //#include <Metro.h>       //для задания интервалов времени (аля Cron)
    //****************************************************************************************
    //byte mac[] = {  0xDE, 0xAD, 0x00, 0x00, 0x00, 0x00 }; //MAC-адрес Arduino
    //byte clock_addr[] = {0x20, 0x21, 0x22, 0x23}; //адреса PCF8574
    //IPAddress timeServer(132, 163, 4, 101);   // IP-адрес NTP сервера
    //const int timeZone = 8;                   // TimeZone
    //****************************************************************************************
    //unsigned int localPort = 53;
    //Metro TimeSync = Metro(86400000); //Частота синхронизации (1 сутки)
    char clockbuf[4];
    //EthernetClient client2;
    //EthernetUDP Udp;
    unsigned long lastTimeUpdate = 0;
    bool DotTimeState = false;
    void setup() {
      for (int i=0; i<4; i++)
      {
        clockbuf[i]='-';
      }
      UpdateClock();
      // Ethernet connection:
    /*  do
      {
        delay(1000);
      } while (Ethernet.begin(mac) == 0);
      Wire.begin();
      Udp.begin(localPort);
      //Запрашиваем время с NTP сервера
      setSyncProvider(getNtpTime);
      //Если время получили успешно, то записываем данные в RTC
      if (timeStatus() != timeNotSet)
      {
        RTC.set(now());
      }*/

    }
    //==============================
    void loop()
    {
    //  tmElements_t tm;
    /*  if (TimeSync.check() == 1) //Синхронизация по времени
      {
        //Запрашиваем время с NTP сервера
        setSyncProvider(getNtpTime);
        //Если время получили успешно, то записываем данные в RTC
        if (timeStatus() != timeNotSet)
        {
          RTC.set(now());
        }
      }*/
     
    /*  if (client2.available())
      {
        char c = client2.read();
      }*/

      if (abs(millis() - lastTimeUpdate) > 500)
      {
        lastTimeUpdate = millis();
        if (RTC.read(tm))
        {
          DotTimeState=!DotTimeState;
          clockbuf[0] = (char)(tm.Hour/10)+'0';
          if (tm.Hour<10)
          {
            clockbuf[0] = ' ';
          }
          clockbuf[1] = (char)(tm.Hour%10)+'0';
          clockbuf[2] = (char)(tm.Minute/10)+'0';
          clockbuf[3] = (char)(tm.Minute%10)+'0';
          UpdateClock();
        }
      }
    }
    //================================================
    void reverse(char s[])
    {
      int i, j;
      char c;
      for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
        c = s[i];
        s[i] = s[j];
        s[j] = c;
      }
    }
    void itoa(int n, char s[])
    {
      int i, sign;
      if ((sign = n) < 0)  /* записываем знак */
      n = -n;          /* делаем n положительным числом */
      i = 0;
      do {       /* генерируем цифры в обратном порядке */
        s[i++] = n % 10 + '0';   /* берем следующую цифру */
      } while ((n /= 10) > 0);     /* удаляем */
      if (sign < 0)
        s[i++] = '-';
      s[i] = '\0';
      reverse(s);
    }
    int len(char *buf)
    {
      int i=0;
      do
      {
        i++;
      } while (buf[i]!='\0');
      return i;
    }
    void UpdateClock()
    {
      for (int i=0; i<4; i++)
      {
        Wire.beginTransmission(clock_addr[i]);
        Wire.write(SegmentValue(clockbuf[i]));
        Wire.endTransmission();
      }
    }
    byte SegmentValue(char k)
    {
      byte u;
      switch (k)
      {
        case '0':
          u=B1111110;
          break;
        case '1':
          u=B0110000;
          break;
        case '2':
          u=B1101101;
          break;
        case '3':
          u=B1111001;
          break;
        case '4':
          u=B0110011;
          break;
        case '5':
          u=B1011011;
          break;
        case '6':
          u=B1011111;
          break;
        case '7':
          u=B1110000;
          break;
        case '8':
          u=B1111111;
          break;
        case '9':
          u=B1111011;
          break;
        case '-':
          u=B0000001;
          break;
        case ' ':
          u=B0000000;
          break;
        case 'E':
          u=B1001111;
          break;
        case 'U':
          u=B0111110;
          break;
        case 'u':
          u=B0011100;
          break;
        case 'I':
          u=B0110000;
          break;
        case 'i':
          u=B0010000;
          break;
        case 'O':
          u=B1111110;
          break;
        case 'o':
          u=B0011101;
          break;
        case 'P':
          u=B1100111;
          break;
        case 'A':
          u=B1110111;
          break;
        case 'S':
          u=B1011011;
          break;
        case 'F':
          u=B1000111;
          break;
        case 'H':
          u=B0110111;
          break;
        case 'J':
          u=B0111100;
          break;
        case 'L':
          u=B0001110;
          break;
        case 'C':
          u=B1001110;
          break;
        case 'B':
          u=B1111111;
          break;
        case 'b':
          u=B0011111;
          break;
        case 'd':
          u=B0111101;
          break;
        case '°':
          u=B1100011;
          break;
        default:
          u=B0000000;
      }
      byte t=0;
      //переворачиваем биты
      for (byte i=0; i<7; i++)
      {
        if ((u&(1<<i))!=0)
        {
          t=t|(1<<(6-i));
        }
      }
      u=t;
      u=u<<1;
      if (DotTimeState)
      {
        u=u+1;
      }
      return u;
    }
    /*-------- NTP code ----------*/
    /*const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
    byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets
    time_t getNtpTime()
    {
      while (Udp.parsePacket() > 0) ; // discard any previously received packets
      sendNTPpacket(timeServer);
      uint32_t beginWait = millis();
      while (millis() - beginWait < 1500)
      {
        int size = Udp.parsePacket();
        if (size >= NTP_PACKET_SIZE)
        {
          Udp.read(packetBuffer, NTP_PACKET_SIZE);  // read packet into the buffer
          unsigned long secsSince1900;
          // convert four bytes starting at location 40 to a long integer
          secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
          secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
          secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
          secsSince1900 |= (unsigned long)packetBuffer[43];
          return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
        }
      }
      return 0; // return 0 if unable to get the time
    }
    // send an NTP request to the time server at the given address
    void sendNTPpacket(IPAddress &address)
    {
      // set all bytes in the buffer to 0
      memset(packetBuffer, 0, NTP_PACKET_SIZE);
      // Initialize values needed to form NTP request
      // (see URL above for details on the packets)
      packetBuffer[0] = 0b11100011;   // LI, Version, Mode
      packetBuffer[1] = 0;     // Stratum, or type of clock
      packetBuffer[2] = 6;     // Polling Interval
      packetBuffer[3] = 0xEC;  // Peer Clock Precision
      // 8 bytes of zero for Root Delay & Root Dispersion
      packetBuffer[12]  = 49;
      packetBuffer[13]  = 0x4E;
      packetBuffer[14]  = 49;
      packetBuffer[15]  = 52;
      // all NTP fields have been given values, now
      // you can send a packet requesting a timestamp:
      Udp.beginPacket(address, 123); //NTP requests are to port 123
      Udp.write(packetBuffer, NTP_PACKET_SIZE);
      Udp.endPacket();
    }*/

    /*-------- NTP code END ----------*/
     
    Последнее редактирование: 4 апр 2016