Arduino UNO R4 WiFiを使って、ネットから日時取得 のプログラム 

 

 前回の記事でArduino UNO R4 WiFiボードで日時を取得して表示することを書いたのだが、肝心のプログラムがブログの文字制限で入りきらなかったので、改めてここに書こうと思う。

↓前回記事はここから

https://ameblo.jp/ogura-castle/entry-12821756104.html

 

改めて見ても、なんか無駄が多そう。 たぶんもうちょっとスリム化できるんじゃないかな。

 

 実際に実装する時は、プログラム内のWi-Fi環境に関する記述を書く必要がある。

具体的には、5・6行目の、ssidとpasswordの変数に代入すればよい。

#include <WiFiS3.h>
#include "Arduino_LED_Matrix.h"
#include "RTC.h"

const char ssid[]     = "**********";
const char password[] = "**********";

WiFiUDP Udp;

#define timeZoneOffsetHours 7  //タイ国なので+7時間
RTCTime currentTime;

//スクロール時間
#define SCROLL_TIME 100   //ミリ秒
unsigned long tm = 0;

//LED Matrix用領域
byte matrix[200];  //文字列をドットに変換用
char DateTime[100];  //日時を文字列に変換用
int max_idx;  //matrix配列の最終カラム
int secIdx;  //matrix配列でどこから秒数表示か格納
int idx;
int secBack, minBack;

//LED matrix用のフォントを独自に作成
byte cfa[][6] PROGMEM = {
  {'A', 0x7f, 0x88, 0x88, 0x7f},  //A
  {'D', 0xff, 0x81, 0x81, 0x7e},  //D
  {'E', 0xff, 0x91, 0x91, 0x91},  //E
  {'F', 0xff, 0x90, 0x90, 0x90},  //F
  {'H', 0xff, 0x10, 0x10, 0xff},  //H
  {'I', 0x81, 0xff, 0x81},  //I
  {'M', 0xff, 0x40, 0x30, 0x40, 0xff},  //M
  {'N', 0xff, 0x60, 0x18, 0x06, 0xff},  //N
  {'O', 0x7e, 0x18, 0x18, 0x7e},  //O
  {'P', 0xff, 0x90, 0x90, 0x60},  //P
  {'R', 0xff, 0x98, 0x94, 0x63},  //R
  {'S', 0x62, 0x91, 0x91, 0x4e},  //S
  {'T', 0x80, 0x80, 0xff, 0x80, 0x80},  //T
  {'U', 0xfe, 0x01, 0x01, 0xfe},  //U
  {'W', 0xf8, 0x07, 0x38, 0x07, 0xf8},  //W
  {'0', 0x7e, 0x8d, 0xb1, 0x7e},  //0
  {'1', 0x41, 0xff, 0x01},  //1
  {'2', 0x67, 0x89, 0x91, 0x61},  //2
  {'3', 0x46, 0x91, 0x91, 0x6e},  //3
  {'4', 0x38, 0x48, 0xff, 0x08},  //4
  {'5', 0xf2, 0x91, 0x91, 0x8e},  //5
  {'6', 0x7e, 0x91, 0x91, 0x4e},  //6
  {'7', 0xc0, 0x87, 0x98, 0xe0},  //7
  {'8', 0x6e, 0x91, 0x91, 0x6e},  //8
  {'9', 0x72, 0x89, 0x89, 0x7e},  //9
  {'.', 0x03, 0x03},  // .
  {'/', 0x03, 0x0c, 0x30, 0xc0},  // /
  {':', 0x36, 0x36},  // :
  {'-', 0x08, 0x08, 0x08, 0x08} };  // -

//曜日を数字から文字列に変換するテーブル
char dow[7][4] PROGMEM = {
  { "SUN" },
  { "MON" },
  { "TUE" },
  { "WED" },
  { "THU" },
  { "FRI" },
  { "SAT" }
};

void setup() {
  byte packetBuffer[48];
  int sts, i1;
  turnLed(0, true);
  
  RTC.begin();
  turnLed(1, true);
  WiFi.begin(ssid, password);
  turnLed(2, true);
  delay(3000);
  while (WiFi.status() != WL_CONNECTED)
    delay(500);
  turnLed(3, true);

  Udp.begin(2390);
  turnLed(4, true);
  memset(packetBuffer, 0, 48);
  packetBuffer[0] = 0xE3;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;
  turnLed(5, true);
  delay(3000);

  do{
    sts = Udp.beginPacket("pool.ntp.org", 123); //NTP requests are to port 123
  }while(!sts);
  turnLed(6, true);
  sts = Udp.write(packetBuffer, 48);
  do{
    sts = Udp.endPacket();
  }while(!sts);
  turnLed(7, true);

  while(!Udp.parsePacket())
    delay(500);
  turnLed(8, true);
  Udp.read(packetBuffer, 48); // read the packet into the buffer
  unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
  unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
  unsigned long secsSince1900 = highWord << 16 | lowWord;
  unsigned long seventyYears = 2208988800UL;
  unsigned long secondsSince1970 = secsSince1900 - seventyYears + (timeZoneOffsetHours * 3600);
  turnLed(9, true);
  RTCTime timeToSet = RTCTime(secondsSince1970);
  RTC.setTime(timeToSet);
  turnLed(10, true);

  //disconnect WiFi as it's no longer needed
  WiFi.disconnect();
  turnLed(11, true);

  RTC.getTime(currentTime); 
  turnLed(12, true);
  for(i1 = 0; i1 < 11; i1++) //最初の11マスは空白
    matrix[i1] = 0;
  sprintf(DateTime, "%04d/%02d/%02d %s %02d:%02d:@%02d", 
    currentTime.getYear(), 
    Month2int(currentTime.getMonth()), 
    currentTime.getDayOfMonth(), 
    dow[(int)currentTime.getDayOfWeek()],
    currentTime.getHour(), 
    currentTime.getMinutes(), 
    currentTime.getSeconds());
  turnLed(13, true);
  max_idx = setMatrixText(DateTime, 11);
  turnLed(14, true);

  secBack = currentTime.getSeconds();
  minBack = currentTime.getMinutes();
  idx = 0;

}

void loop() {
  int ic1, ic2;

  RTC.getTime(currentTime);
  if(secBack != currentTime.getSeconds()){
    char secStr[3];
    sprintf(secStr, "%02d", currentTime.getSeconds());
    setMatrixText(secStr, secIdx);
    secBack = currentTime.getSeconds();
  }

  if(minBack != currentTime.getMinutes()){
    sprintf(DateTime, "%04d/%02d/%02d %s %02d:%02d:@%02d", 
      currentTime.getYear(), 
      Month2int(currentTime.getMonth()), 
      currentTime.getDayOfMonth(), 
      dow[(int)currentTime.getDayOfWeek()],
      currentTime.getHour(), 
      currentTime.getMinutes(), 
      currentTime.getSeconds());
    max_idx = setMatrixText(DateTime, 11);
    minBack = currentTime.getMinutes();
  }

  if(tm + SCROLL_TIME <= millis()) {
    //格納場所をスライド、末端に到達したら始めに戻る
    if (idx < max_idx)
      idx++;
    else{
      idx = 0;
    }

    //経過時間を再計測
    tm = millis();
  }

  //8x12LED View
  for(ic1 = 0; ic1 < 8; ic1++){
    for(ic2 = 0; ic2 < 12; ic2++){
      turnLed(ic1 * 12 + ic2 , matrix[idx + ic2] >> (7 - ic1) & 0x01);
      delayMicroseconds(20);
    }
  }
}

unsigned int setMatrixText(char* setStr, int setStart)
{
  unsigned int srcf; //, setIdx;
  int idx2, idx3 = 0;

  while(setStr[idx3] != '\0'){
    if(setStr[idx3] != ' ' && setStr[idx3] != '@')
      for(srcf = 0; srcf < 29; srcf++)
        if(setStr[idx3] == cfa[srcf][0])
          break;
    if(srcf >= 29) break;

    switch(setStr[idx3]){  //文字をmtrixに変換
      case '@':  //秒の場所を取得
        secIdx = setStart;
        break;
      case ' ':
        for(idx2 = 0; idx2 < 3; idx2++){
          matrix[setStart] = 0;
          setStart++;
        }
        break;
      case '.':
      case ':':
        for(idx2 = 0; idx2 < 2; idx2++){
          matrix[setStart] = cfa[srcf][idx2 + 1];
          setStart++;
        }
        break;
      case 'I':
      case '1':
        for(idx2 = 0; idx2 < 3; idx2++){
          matrix[setStart] = cfa[srcf][idx2 + 1];
          setStart++;
        }
        break;
      case 'M':
      case 'N':
      case 'T':
      case 'W':
        for(idx2 = 0; idx2 < 5; idx2++){
          matrix[setStart] = cfa[srcf][idx2 + 1];
          setStart++;
        }
        break;
      default:
        for(idx2 = 0; idx2 < 4; idx2++){
          matrix[setStart] = cfa[srcf][idx2 + 1];
          setStart++;
        }
    }
    matrix[setStart] = 0;
    setStart++;
    idx3++;
  }
  for(idx2 = 0; idx2 < 11; idx2++)
    matrix[setStart] = 0;  //最後に余白を入れる

  return setStart;
}