//sntp_RTC_sync_ESP32_oled ; update: 2024/01/15 13:30 //Board: ESP32 Dev Module // use ESP32 ESP-WROOM-32, RTC DS1307 AT24C32, I2C 0.96inch 128x64 SSD1306 // #include #include // **** #include // for struct timeval #include // for sntp_sync_status #include "RTClib.h" #include #include #include #include //漢字フォント用 #define TIMEZONE "JST-9" #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels #define OLED_RESET -1 // 使用しないので -1を設定する。 #define SCREEN_ADDRESS 0x3C // I2Cアドレスは 0x3C #define OLED_SCL 22 // Wire SCLのGPIOは 22 #define OLED_SDA 21 // Wire SDAのGPIOは 21 // normal//debug #define OLED_YEAR 2 // 2// 1 #define OLED_YEARGUD 0 // 0// 0 #define OLED_YEAROPT 8 // 8// 7 #define OLED_MONTH 24 //24//21 #define OLED_MONTHGUD 30 //30//27 #define OLED_HOUR 46 //46//41 #define OLED_HOURGUD 52 //52//49 #define OLED_DEBUG -1 //-1//57 const char* ssid = "ax50anotherZ"; const char* password = "rock#tang@50Gpgw"; const char* ntpServer1 = "ntp.nict.jp"; const char* ntpServer2 = "time.google.com"; const char* ntpServer3 = "ntp.jst.mfeed.ad.jp"; const int ctimeout = 10; //Wait WiFi Connection static int itimeout = ctimeout; static int lastSec = -1; static int lastHour = -1; static int wifienable = 1; //WiFi 接続有効/無効(1:OK, -1:NG) static char* wifistate="Alive";//"Alive" or "Down" static char buf[30];//20 static struct tm timeinfo; static int timeset = -1;// 時間正常(-1:異常/1:正常) static int rtcenable = -1;// RTC状態(-1:異常/1:正常) static int fixed = -1;// set Time static int movetolocal = -1;// set Time to Local rtc // RTCオブジェクト RTC_DS1307 rtc; // 曜日表示文字 static char *weekChar[7] = { "日", "月", "火", "水", "木", "金", "土" }; uint8_t font[8]; // フォント格納バッファ Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); //表示制御にはAdafruit製 SSD1306を使用する。 void printLocalTime() { if(rtcenable == -1) { startwifi(); //connect to WiFi } else if(rtcenable == 1 && timeinfo.tm_year+1900 != rtc.now().year() && rtc.now().year() > 2020) { getRTCtime(); Serial.println("70: set RTC to Local RTC"); sprintf(buf, "71: set RTC(%04d) %04d", rtc.now().year(), timeinfo.tm_year+1900); Serial.println(buf); } else if(rtcenable == 1 && timeinfo.tm_year+1900 > 2020 && rtc.now().year() < timeinfo.tm_year+1900) { rtc.adjust(DateTime(timeinfo.tm_year+1900, timeinfo.tm_mon+1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec+1)); rtcenable = 1; Serial.println("78: set RTC"); } #if OLED_DEBUG != -1 transportdebugTime(); oled.display(); //バッファ転送(表示) #endif if(timeinfo.tm_year+1900 < 2020 || rtc.now().year() < timeinfo.tm_year+1900) rtcenable = -1; if (lastHour != rtc.now().hour()) { // 1 時間経過した lastHour = rtc.now().hour(); Serial.println("88: 1 hour has passed, Connecting to NTP Server!"); startwifi(); } if(fixed < 3 && rtc.now().year() != (timeinfo.tm_year+1900) && wifienable == 1 && timeinfo.tm_year > 2020) { rtc.adjust(DateTime(timeinfo.tm_year+1900, timeinfo.tm_mon+1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec+1)); rtcenable = 1; fixed++; sprintf(buf, "97: set RTC(%02d) %04d = %04d", fixed, rtc.now().year(), timeinfo.tm_year+1900); Serial.println(buf); } if(rtc.now().year() == timeinfo.tm_year+1900 ) rtcenable = 1; if (lastSec != rtc.now().second()) {// 時刻が変わった時に描画する lastSec = rtc.now().second(); oledDisp(); // 時刻描画 } } void oledDisp() { //何か表示されている場合に備えて表示クリア oled.clearDisplay(); setRTCTime(); //setLocalTime(); #if OLED_DEBUG != -1 transportdebugTime(); #endif //oled.setRotation(2); //デフォルト位置から、180度回転 oled.display(); //バッファ転送(表示) } #if OLED_DEBUG != -1 void transportdebugTime() // print time for debug { if(OLED_DEBUG == -1) return; /// DateTime now = rtc.now(); oled.setTextSize(1); // text size // sprintf(buf, "year=%4d", timeinfo.tm_year+1900);//now.year()); // Serial.println(buf); // sprintf(buf, "%2d", timeinfo.tm_year+1900);//now.year()); // oled.setCursor(0+4, OLED_DEBUG); //テキストの表示開始位置 0,46 // oled.print(buf); //表示文字列 // sprintf(buf, "month=%2d", timeinfo.tm_mon + 1);//now.month()); // Serial.println(buf); // sprintf(buf, "%2d", timeinfo.tm_mon + 1);//now.month()); // oled.setCursor(45+10, OLED_DEBUG); //テキストの表示開始位置 45,46 // oled.print(buf); //表示文字列 // sprintf(buf, "day=%2d", timeinfo.tm_mday);//now.day()); // Serial.println(buf); // sprintf(buf, "%2d", timeinfo.tm_mday);//now.day()); // oled.setCursor(88+10, OLED_DEBUG); //テキストの表示開始位置 88,46 // oled.print(buf); //表示文字列 // 時分秒の描画 sprintf(buf, "hour=%2d", timeinfo.tm_hour); //now.hour()); // Serial.println(buf); sprintf(buf, "%2d", timeinfo.tm_hour);//now.hour()); oled.setCursor(0+10, OLED_DEBUG); //テキストの表示開始位置 0,46 oled.print(buf); //表示文字列 // sprintf(buf, "minute=%02d", timeinfo.tm_min);//now.minute() // Serial.println(buf); sprintf(buf, "%02d", timeinfo.tm_min);//now.minute() oled.setCursor(45+10, OLED_DEBUG); //テキストの表示開始位置 45,46 oled.print(buf); //表示文字列 // sprintf(buf, "second=%02d", timeinfo.tm_sec);//now.second() // Serial.println(buf); sprintf(buf, "%02d", timeinfo.tm_sec);//now.second() oled.setCursor(88+10, OLED_DEBUG); //テキストの表示開始位置 88,46 oled.print(buf); //表示文字列 oled.setTextSize(2); // text size getFontData(font, "時"); oled.drawBitmap(28, OLED_DEBUG, font,8,8,1);//28,52 getFontData(font, "分"); oled.drawBitmap(72, OLED_DEBUG, font,8,8,1);//72,52 getFontData(font, "秒"); oled.drawBitmap(113, OLED_DEBUG, font,8,8,1);//113,52 // oled.display(); //バッファ転送(表示) } #endif // Callback function (get's called when time adjusts via NTP) void timeavailable(struct timeval *t) { Serial.println("179:Got time adjustment from NTP!"); } void setup() { Serial.begin(921600);//115200//921600 wifistate="????"; /// Wire.begin(OLED_SDA,OLED_SCL);// i2c_scanner //Wire.begin(2,0); #この記述により、SDAをGPIO2へ、SCLをGPIO0へと割り当てる事が出来る /// Wire.setClock(400000); //I2C0で使用するGPは SDA = 0, SCL = 1 /// Wire.setSDA(OLED_SDA);//GP21 /// Wire.setSCL(OLED_SCL);//GP22 if (!rtc.begin()) { Serial.println("194:Couldn't find RTC"); while(1); rtcenable = -1; } /// else rtcenable = 1;//意図的にコメント if (!oled.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println(F("201:SSD1306 allocation failed")); while (true); } delay(500); // wait for initializing oled.clearDisplay(); // clear display // oled.display(); //バッファ転送(表示) oled.setTextSize(2); // text size oled.setTextColor(SSD1306_WHITE); // text color # 色指定はできないが必要 oled.setCursor(0, 10); // position to display } void getRTCtime() { DateTime now = rtc.now(); timeinfo.tm_year = now.year()-1900; timeinfo.tm_mon = now.month()-1; timeinfo.tm_mday = now.day(); timeinfo.tm_hour = now.hour(); timeinfo.tm_min = now.minute(); timeinfo.tm_sec = now.second(); } void startwifi() { itimeout = ctimeout; //connect to WiFi Serial.printf("228:Connecting to %s ", ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { itimeout--; if(itimeout < 1) { wifienable = -1; // WIFI_REASON_TDLS_PEER_UNREACHABLE; wifistate="Down"; break; } else { wifistate="Alive"; Serial.print("."); delay(500); wifienable = 1; } } Serial.println("\n"); if(wifienable == 1) { Serial.println("248:has Connected "); //init and get the time sntp_set_time_sync_notification_cb( timeavailable ); // NTPサーバを用いた時刻合わせ関数 configTzTime(TIMEZONE, ntpServer1, ntpServer2, ntpServer3); // esp32 api compatibility // 時刻待ち合せ while (!getLocalTime(&timeinfo)) { delay(1000); } Serial.println(" 259:Setting _ _ _ RTC Time "); if(wifienable == 1) { delay(1000); if(timeinfo.tm_year+1900 > 2020 && rtc.now().year() < timeinfo.tm_year+1900) { rtc.adjust(DateTime(timeinfo.tm_year+1900, timeinfo.tm_mon+1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec)); rtcenable = 1; Serial.println("267: set RTC"); } } } else { Serial.println("WiFi is Down "); getRTCtime();// ################## } if(timeinfo.tm_year != 70) { //disconnect WiFi as it's no longer needed delay(500); // wait for WiFi.disconnect(true, true); WiFi.mode(WIFI_OFF); Serial.println("280: WiFi_Off\n"); } } void loop() { printLocalTime(); // oledDisp(); // 時刻描画 // delay(500); // wait for } void setRTCTime() { DateTime now = rtc.now(); // 時分秒の描画 sprintf(buf, "%2d", now.hour()); oled.setCursor(0, OLED_HOUR); //テキストの表示開始位置 0,46 oled.print(buf); //表示文字列 sprintf(buf, "%02d", now.minute()); oled.setCursor(45, OLED_HOUR); //テキストの表示開始位置 45,46 oled.print(buf); //表示文字列 sprintf(buf, "%02d", now.second()); oled.setCursor(88, OLED_HOUR); //テキストの表示開始位置 88,46 oled.print(buf); //表示文字列 // 年月日の描画 //sprintf(buf, "%4d", timeinfo.tm_year + 1900); sprintf(buf, "%2d", now.year()); oled.setCursor(0, OLED_YEAR); //テキストの表示開始位置 0,2 oled.print(buf); //表示文字列 oled.setTextSize(1); // text size sprintf(buf, "wifi:%s", wifistate); // WiFi State // Alive/Down oled.setCursor(66, OLED_YEAROPT);// テキストの表示開始位置 66,8 oled.print(buf); // 表示文字列 oled.setTextSize(2); // text size sprintf(buf, "%2d", now.month()); oled.setCursor(0, OLED_MONTH); //テキストの表示開始位置 0,24 oled.print(buf); //表示文字列 sprintf(buf, "%2d", now.day()); oled.setCursor(46, OLED_MONTH); //テキストの表示開始位置 46,24 oled.print(buf); //表示文字列 // 曜日()の描画 getFontData(font, "("); oled.drawBitmap(96, OLED_MONTHGUD, font,8,8,1);//96,30 getFontData(font, ")"); oled.drawBitmap(116, OLED_MONTHGUD, font,8,8,1);//116,30 // 年月日時分秒の描画 // 日本語フォントをセット getFontData(font, "時"); oled.drawBitmap(28, OLED_HOURGUD, font,8,8,1);//28,52 getFontData(font, "分"); oled.drawBitmap(72, OLED_HOURGUD, font,8,8,1);//72,52 getFontData(font, "秒"); oled.drawBitmap(113, OLED_HOURGUD, font,8,8,1);//113,52 getFontData(font, "年"); oled.drawBitmap(54, OLED_YEAROPT, font,8,8,1);//54,8 getFontData(font, "月"); oled.drawBitmap(28, OLED_MONTHGUD, font,8,8,1);//28,30 getFontData(font, "日"); oled.drawBitmap(72, OLED_MONTHGUD, font,8,8,1);//72,30 getFontData(font, weekChar[now.dayOfTheWeek()]); // 曜日表示文字 oled.drawBitmap(104, OLED_MONTHGUD, font,8,8,1);//104,30 } //---------------------------------------------------------------------- /* void setLocalTime() { // 時分秒の描画 sprintf(buf, "%2d", timeinfo.tm_hour); oled.setCursor(0, OLED_HOUR); //テキストの表示開始位置 0,46 oled.print(buf); //表示文字列 sprintf(buf, "%02d", timeinfo.tm_min); oled.setCursor(45, OLED_HOUR); //テキストの表示開始位置 45,46 oled.print(buf); //表示文字列 sprintf(buf, "%02d", timeinfo.tm_sec); oled.setCursor(88, OLED_HOUR); //テキストの表示開始位置 88,46 oled.print(buf); //表示文字列 // 年月日の描画 sprintf(buf, "%4d", timeinfo.tm_year + 1900); oled.setCursor(0, OLED_YEAR); //テキストの表示開始位置 0,2 oled.print(buf); //表示文字列 oled.setTextSize(1); // text size sprintf(buf, "wifi:%s", wifistate); // WiFi State // Alive/Down oled.setCursor(66, OLED_YEAROPT);// テキストの表示開始位置 66,8 oled.print(buf); // 表示文字列 oled.setTextSize(2); // text size sprintf(buf, "%2d", timeinfo.tm_mon + 1); oled.setCursor(0, OLED_MONTH); //テキストの表示開始位置 0,24 oled.print(buf); //表示文字列 sprintf(buf, "%2d", timeinfo.tm_mday); oled.setCursor(46, OLED_MONTH); //テキストの表示開始位置 46,24 oled.print(buf); //表示文字列 // 曜日()の描画 getFontData(font, "("); oled.drawBitmap(96, OLED_MONTHGUD, font,8,8,1);//96,30 getFontData(font, ")"); oled.drawBitmap(116, OLED_MONTHGUD, font,8,8,1);//116,30 // 年月日時分秒の描画 // 日本語フォントをセット getFontData(font, "時"); oled.drawBitmap(28, OLED_HOURGUD, font,8,8,1);//28,52 getFontData(font, "分"); oled.drawBitmap(72, OLED_HOURGUD, font,8,8,1);//72,52 getFontData(font, "秒"); oled.drawBitmap(113, OLED_HOURGUD, font,8,8,1);//113,52 getFontData(font, "年"); oled.drawBitmap(54, OLED_YEAROPT, font,8,8,1);//54,8 getFontData(font, "月"); oled.drawBitmap(28, OLED_MONTHGUD, font,8,8,1);//28,30 getFontData(font, "日"); oled.drawBitmap(72, OLED_MONTHGUD, font,8,8,1);//72,30 getFontData(font, weekChar[timeinfo.tm_wday]); // 曜日表示文字 oled.drawBitmap(104, OLED_MONTHGUD, font,8,8,1);//104,30 } */ //-----------------------------------------------------------------------------