概要
Raspberry Pi Pico と ESP-01 で時計を作成します。
ESP-01をATコマンドで制御し、SNTPで時刻同期します。
時刻同期は毎正時に行います。
ソフトウエア資材
- Arduino IDE for Raspberry Pi Pico on Windows 11
ハードウエア資材
- [Cytron] Maker Pi Pico Base (開発用基板)
- Raspberry Pi Pico
- ESP-01(WiFi module)
- SSD1306(OLED)
- GROVE - 4ピン-ジャンパメスケーブル
プログラム(スケッチ)
EspATClock.ino
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <TimeLib.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
String sendCommand(String command, String replyEnd="OK");
time_t getSNTPTIME();
time_t parseTimeString(String timeString);
void displayDateTime();
bool syncTime = false;
void setup() {
Wire.setSDA(4);
Wire.setSCL(5);
Wire.begin();
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
display.println("Initializing");
Serial1.setTX(16);
Serial1.setRX(17);
Serial1.begin(115200);
sendCommand("RST","ready");
sendCommand("CWJAP=\"<your ssid>\",\"<your password>\"");
sendCommand("CIPSNTPCFG=1,9,\"ntp.nict.jp\"");
time_t t = getSNTPTIME();
setTime(t);
}
void loop() {
if (minute() == 0) {
if (!syncTime) {
syncTime = true;
time_t t = getSNTPTIME();
setTime(t);
}
} else {
syncTime = false;
}
displayDateTime();
}
getSNTPTIME()
time_t getSNTPTIME() {
while (true) {
String response = sendCommand("CIPSNTPTIME?");
time_t t = parseTimeString(response);
if (year(t) > 1970) return t;
delay(500);
}
}
parseTimeString()
time_t parseTimeString(String timeString) {
char dayName[4], monthName[4], buff[256];
int year, month;
struct tm tm;
strcpy(buff,timeString.c_str());
char* pt = strchr(buff,':') + 1;
sscanf(pt, "%s %s %d %d:%d:%d %d",
dayName, monthName, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &year);
for(month=1; month<=12; month++) if (strcmp(monthShortStr(month), monthName) == 0) break;
tm.tm_year = year - 1900;
tm.tm_mon = month - 1;
return mktime(&tm);
}
sendCommand()
String sendCommand(String command, String replyEnd) {
const int timeout = 5000;
String response = "";
String strLine = "";
bool blnOK = false;
Serial1.print("AT+");
Serial1.print(command);
Serial1.println();
long int time = millis();
while(true) {
while(Serial1.available()) {
char c = Serial1.read();
if (c == '\r') {
} else if (c == '\n') {
if (strLine.charAt(0) == '+') response = strLine;
else if (strLine == replyEnd) blnOK = true;
strLine = "";
} else strLine += c;
}
if (blnOK) break;
if ((millis()-time) > timeout) break;
}
return response;
}
displayDateTime()
void displayDateTime() {
char bufTime[32], bufDate[32], dayName[4], monthName[4];
strcpy(dayName, dayShortStr(weekday()));
strcpy(monthName, monthShortStr(month()));
sprintf(bufTime, "%02d:%02d:%02d", hour(), minute(), second());
sprintf(bufDate, "%s %02d %s %d", dayName, day(), monthName, year());
display.clearDisplay();
display.setTextSize(2);
display.setCursor(0, 0);
display.println(bufTime);
display.setTextSize(1);
display.setCursor(0, 20);
display.println(bufDate);
display.display();
}
まとめ
動作確認に使用した ESP-01 のATファームウエアのバージョンは下記のとおりです。
AT+GMR
AT version:1.7.4.0(Jul 8 2020 15:53:04)
SDK version:3.0.5-dev(52383f9)
compile time:Aug 28 2020 14:37:33
OK
ATファームウエアの説明は下記です。
https://docs.espressif.com/projects/esp-at/en/release-v2.2.0.0_esp8266/index.html