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; }