Часы на ESP8266 своими руками
Есть несколько ситуаций, когда использование часов реального времени (RTC) может отрицательно повлиять на ваш проект, увеличивая стоимость, размер, точность времени или требования к линиям ввода вывода. Чтобы предотвратить это, особенно в проектах на основе ESP / WiFi или других, зависящих от часов, разработчики обычно обращаются за получением информации о времени с NTP-серверов. Итак, в рамках сегодняшнего проекта мы создадим сетевые часы на основе NTP.

NTP (сетевой протокол времени) – это интернет-протокол, используемый для синхронизации часов в компьютерных сетях в течение нескольких миллисекунд универсального скоординированного времени (UTC). Используя этот протокол, устройства могут запрашивать и получать данные UTC от NTP-сервера, который обычно получает точное время от атомных часов.
Wi-Fi-возможности ESP8266 будут использоваться при получении информации о времени с общедоступного NTP-сервера и будут отображаться в удобном для пользователя виде на OLED-дисплее.
Благодаря использованию всего двух компонентов, схема для сегодняшнего проекта очень проста. Используемый OLED-дисплей связывается с хост-микроконтроллером через I2C, поэтому все, что нам нужно, это подключить дисплей к выводам платы I2C Wemos D1 mini на основе ESP8266, как показано на следующей схеме.

Важно учесть максимальное входное напряжение вашего OLED-дисплея и убедиться, что оно толерантно к 5 В. Вы должны подключить вывод VCC OLED к выводу 3.3 В Wemos D1, если 5 В слишком высокое напряжение для дисплея. После завершения сборки схемы мы можем перейти к коду проекта.
Arduino IDE используется для разработки кода этого проекта, поэтому, если вы впервые используете плату на основе ESP8266 с IDE, вам необходимо установить для нее поддержку ESP8266. Алгоритм, лежащий в основе кода для сегодняшнего проекта, довольно прост. Начнем с подключения Wemos D1 к Интернету через точку доступа WiFi и доступа к NTP-серверу для получения сетевого времени. Мы конвертируем сетевое время в наш местный эквивалент времени и отображаем местное время на OLED-дисплее.
Чтобы упростить написание кода, мы будем использовать несколько библиотек, в том числе; библиотека ESP8266WIFI, библиотека ESP Time и библиотека U8g2. Библиотека ESP8266WIFI используется для всего, что связано с подключением ESP8266 к Интернету через точку доступа WiFi, в то время как библиотека времени имеет реализации функций, которые позволяют нам легко извлекать время из NTP-серверов, а библиотека U8g2 позволяет нам взаимодействовать с OLED и отображать текст на нем в причудливых шрифтах. Библиотека ESP8266WiFi и Time поставляется с предустановленной поддержкой ESP8266 Arduino IDE, в то время как библиотеку U8g2 необходимо будет установить через менеджер библиотек Arduino.
Полный код проекта приведен далее.
#include <ESP8266WiFi.h>
#include <time.h>
#include <U8x8lib.h>
const char* ssid = "Access point's SSID"; // SSID точки доступа
const char* password = "Access point's PASSWORD"; // пароль точки доступа
const char* NTP_SERVER = "ch.pool.ntp.org"; // NTP-сервер
const char* TZ_INFO = "GMT+0BST-1,M3.5.0/01:00:00,M10.5.0/02:00:00"; // введите свой часовой пояс (https://remotemonitoringsystems.ca/time-zone-abbreviations.php)
tm timeinfo;
time_t now;
long unsigned lastNTPtime;
unsigned long lastEntryTime;
U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8(/* такты=*/ SCL, /* данные=*/ SDA, /* сброс=*/ U8X8_PIN_NONE); // OLED без сброса дисплея
void setup()
{
u8x8.begin();
Serial.begin(115200);
Serial.println("\n\nNTP Time Test\n");
WiFi.begin(ssid, password);
Serial.print("Connecting to network");
int counter = 0;
while (WiFi.status() != WL_CONNECTED)
{
delay(200);
if (++counter > 100)
ESP.restart();
Serial.print( "." );
}
Serial.println("\nWiFi connected\n\n");
configTime(0, 0, NTP_SERVER);
// Смотрите коды часовых поясов для вашего региона на https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
setenv("TZ", TZ_INFO, 1);
if (getNTPtime(10))
{
// ждем до 10 секунд для синхронизации
}
else
{
Serial.println("Time not set");
ESP.restart();
}
showTime(&timeinfo);
lastNTPtime = time(&now);
lastEntryTime = millis();
}
void loop()
{
getNTPtime(10);
showTime(&timeinfo);
delay(1000);
}
bool getNTPtime(int sec)
{
{
uint32_t start = millis();
do
{
time(&now);
localtime_r(&now, &timeinfo);
delay(10);
} while (((millis() - start) <= (1000 * sec)) && (timeinfo.tm_year < (2016 - 1900)));
if (timeinfo.tm_year <= (2016 - 1900))
return false; // вызов NTP не был успешным
Serial.print("Time Now: ");
Serial.println(now);
}
return true;
}
void showTime(tm *localTime)
{
// вывод в последовательный порт
Serial.print(localTime->tm_mday);
Serial.print('/');
Serial.print(localTime->tm_mon + 1);
Serial.print('/');
Serial.print(localTime->tm_year - 100);
Serial.print('-');
Serial.print(localTime->tm_hour);
Serial.print(':');
Serial.print(localTime->tm_min);
Serial.print(':');
Serial.print(localTime->tm_sec);
Serial.print(" Day of Week ");
Serial.println(localTime->tm_wday);
Serial.println();
//показать на OLED
char time_output[30];
u8x8.setFont(u8x8_font_courB18_2x3_f);
u8x8.setCursor(0,0);
sprintf(time_output, "%02d:%02d:%02d", localTime->tm_hour, localTime->tm_min, localTime->tm_sec);
u8x8.print(time_output);
u8x8.setFont(u8x8_font_8x13B_1x2_f);
u8x8.setCursor(4,4);
sprintf(time_output, "%02d/%02d/%02d", localTime->tm_mday, localTime->tm_mon + 1, localTime->tm_year - 100);
u8x8.print(time_output);
u8x8.setCursor(4,6);
u8x8.print(getDOW(localTime->tm_wday));
}
char * getDOW(uint8_t tm_wday)
{
switch(tm_wday)
{
case 1:
return "Monday";
break;
case 2:
return "Tuesday";
break;
case 3:
return "Wednesday";
break;
case 4:
return "Thursday";
break;
case 5:
return "Friday";
break;
case 6:
return "Saturday";
break;
case 7:
return "Sunday";
break;
default:
return "Error";
break;
}
}
Соберите схему и еще раз и убедитесь, что у вас установлен в Arduino IDE пакет поддержки для ESP8266 вместе с библиотекой U8g2. Затем подключите ESP8266 к компьютеру и выберите его в Arduino IDE вместе с портом, к которому он подключен. Нажмите кнопку загрузки и дождитесь завершения процесса загрузки. По завершении вы увидите, что информация о времени и дате отображается на OLED, как показано на изображении.

Также можно распечатать корпус для данного устройства на 3D-принтере (https://www.thingiverse.com/thing:857858).

© digitrode.ru