интернет часы с погодой на esp8266, P10 LegMatrix
- Войдите на сайт для отправки комментариев
Пт, 23/08/2019 - 00:58
Обещал выложить часики на светодиодной матрице
/* подключение Pin on DMD P10 GPIO NODEMCU 2 A GPIO16 D0 8 CLK GPIO14 D5 4 B GPIO12 D6 - 10 SCK GPIO0 D3 12 R GPIO13 D7 1 NOE GPIO15 D8 3 GND GND GND */ #include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino //needed for library #include <DNSServer.h> #include <ESP8266WebServer.h> #include <WiFiManager.h> //https://github.com/tzapu/WiFiManager #include <WiFiClient.h> // Библиотека для связи с сетевыми хостами (локальными и интернет) #include <TimeLib.h> // Библиотека для работы с временем #include <SPI.h> #include <DMD2.h> #include <fonts/Droid_Sans_16.h> #include <fonts/Arial_Black_16_ISO_8859_1.h> //Arial_Black_16_ISO_8859_1.h //SoftDMD dmd(1,1); // DMD controls the entire display SPIDMD dmd(1,1); // DMD controls the entire display DMD_TextBox box(dmd, 0, 0, 32, 16); String regionID = "11207"; // Код региона по Yandex для выбора часового пояса https://tech.yandex.ru/xml/doc/dg/reference/regions-docpage/ String SunriseTime, SunsetTime, Temperature; char icon[20]; WiFiClient client; // Создаём объект для работы с удалёнными хостами void setup() { // put your setup code here, to run once: Serial.begin(115200); Serial.println("\n\n"); //WiFiManager //Local intialization. Once its business is done, there is no need to keep it around WiFiManager wifiManager; //reset settings - for testing //wifiManager.resetSettings(); //sets timeout until configuration portal gets turned off //useful to make it all retry or go to sleep //in seconds wifiManager.setTimeout(180); //fetches ssid and pass and tries to connect //if it does not connect it starts an access point with the specified name //here "AutoConnectAP" //and goes into a blocking loop awaiting configuration if(!wifiManager.autoConnect("AutoConnectAP")) { Serial.println("failed to connect and hit timeout"); delay(500); //reset and try again, or maybe put it to deep sleep // ESP.reset(); // delay(5000); } dmd.setBrightness(50); dmd.selectFont(Arial_Black_16_ISO_8859_1); dmd.begin(); //if you get here you have connected to the WiFi Serial.println("connected...yeey :)"); while (!TimeAndWeather()) // Синхронизируем время микроконтроллера с реальным временем и получаем информацию о погоде delay(500); digitalClockDisplay(); // Выводим дату и время } static boolean flagSec = 0; String DataTime; boolean rejim=0; boolean flag=1; unsigned long halfSecondMillis = millis(); unsigned long lastMillis = millis(); unsigned long lastMillisRejim = millis(); void loop() { // put your main code here, to run repeatedly: if (flag == 0){ byte i1=0; while (!TimeAndWeather()){ delay(500); i1++; if (i1==10) break; } // Синхронизируем время микроконтроллера с реальным временем и получаем информацию о погоде lastMillis = millis(); flag = 1; } if (millis() - lastMillis >= 5 * 1000*60) { // ОБНОВЛЯЕМ ДАННЫЕ РАЗ В ПЯТЬ МИНУТ flag = 0; } if (millis() - lastMillisRejim >= 17000){rejim=!rejim; lastMillisRejim = millis(); box.clear(); } if (rejim==0){ dmd.selectFont(Arial_Black_16_ISO_8859_1); digitalClockDisplay(); }else{ dmd.selectFont(Droid_Sans_16); String ret=WeatherDisplay(); // DataTime="Сегодня "+leadNull(day())+"."+leadNull(month())+"."+year()+" "+" на улице "+ Temperature + " C "+ret+ " Восход в " + SunriseTime+" Закат в " + SunsetTime; DataTime="Today "+leadNull(day())+"."+leadNull(month())+"."+year()+" "+" on the street "+ Temperature + "C "+ret+ " Sunrise " + SunriseTime+" Sunset " + SunsetTime; scroll_text(); } } bool TimeAndWeather () { // Функция синхронизации времени работы программы с реальным временем и получения информации о погоде if (client.connect("yandex.com",443)) { // Если удаётся установить соединение с указанным хостом (Порт 443 для https) client.println("GET /time/sync.json?geo=" + regionID + " HTTP/1.1\r\nHost: yandex.com\r\nConnection: close\r\n\r\n"); // Отправляем параметры запроса delay(200); // Даём серверу время, чтобы обработать запрос char endOfHeaders[] = "\r\n\r\n"; // Системные заголовки ответа сервера отделяются от остального содержимого двойным переводом строки if (!client.find(endOfHeaders)) { // Отбрасываем системные заголовки ответа сервера Serial.println("Invalid response"); // Если ответ сервера не содержит системных заголовков, значит что-то пошло не так return false; // и пора прекращать всё это дело } Serial.println("chitaem dannie"); String line2; while ( client.available() ) { char c = client.read(); line2 += c; } Serial.print("line2= "); Serial.println(line2); String StringCurrentTime = line2.substring(8,18); int n_offset=line2.indexOf("offset"); int k_offset = line2.indexOf(',',n_offset); String StringOffset= line2.substring(n_offset+8,k_offset); //18000000 int n_sunrise=line2.indexOf("sunrise"); int k_sunrise = line2.indexOf(',',n_sunrise); SunriseTime= line2.substring(n_sunrise+9,k_sunrise); //18000000 int n_sunset=line2.indexOf("sunset"); int k_sunset = line2.indexOf(',',n_sunset); SunsetTime= line2.substring(n_sunset+8,k_sunset); //18000000 int n_temp=line2.indexOf("temp"); int k_temp = line2.indexOf(',',n_temp); Temperature= line2.substring(n_temp+6,k_temp); //18000000 int n_icon=line2.indexOf("icon"); int k_icon = line2.indexOf(',',n_icon); String Stringicon= line2.substring(n_icon+6,k_icon); //18000000 Serial.print("Stringicon= "); Serial.println(Stringicon); client.stop(); // Разрываем соединение с сервером strcpy(icon,Stringicon.c_str()); // Достаём иконку - Четвёртый уровень вложенности пары ключ/значение clocks -> значение RegionID -> weather -> icon Serial.print("icon= "); Serial.println(icon); unsigned long CurrentTime = StringToULong(StringCurrentTime); // Переводим значение реального времени в секундах, считанное с Яндекса, из String в unsigned long unsigned long Offset = StringToULong(StringOffset) / 1000; // Переводим значение смещения времени по часовому поясу, считанное с Яндекса, из String в unsigned long и переводим его в секунды setTime(CurrentTime + Offset); // Синхронизируем время return true; } } unsigned long StringToULong(String Str) { // Эта функция преобразует String в unsigned long unsigned long ULong = 0; for (int i = 0; i < Str.length(); i++) { // В цикле посимвольно переводим строку в unsigned long char c = Str.charAt(i); if (c < '0' || c > '9') break; ULong *= 10; ULong += (c - '0'); } return ULong; } void scroll_text(){ const char *next = DataTime.c_str(); while(*next) { // Serial.print(*next); box.print(*next); delay(300); next++; } } void digitalClockDisplay(){ // Эта функция выводит время if (millis() - halfSecondMillis > 500) { halfSecondMillis=millis(); int uiTime=hour()*100+minute(); box.clear(); dmd.drawChar( 0, 0,'0'+((uiTime%10000)/1000), GRAPHICS_ON ); // thousands dmd.drawChar( 8, 0, '0'+((uiTime%1000) /100), GRAPHICS_ON ); // hundreds dmd.drawChar( 17, 0, '0'+((uiTime%100) /10), GRAPHICS_ON ); // tens dmd.drawChar( 25, 0, '0'+ (uiTime%10), GRAPHICS_ON ); // units flagSec =! flagSec; //Инверсия признака if (flagSec) { dmd.setPixel(15,4,GRAPHICS_ON); dmd.setPixel(15,5,GRAPHICS_ON); dmd.setPixel(15,11,GRAPHICS_ON); dmd.setPixel(15,12,GRAPHICS_ON); dmd.setPixel(16,4,GRAPHICS_ON); dmd.setPixel(16,5,GRAPHICS_ON); dmd.setPixel(16,11,GRAPHICS_ON); dmd.setPixel(16,12,GRAPHICS_ON); }else{ dmd.setPixel(15,4,GRAPHICS_OFF); dmd.setPixel(15,5,GRAPHICS_OFF); dmd.setPixel(15,11,GRAPHICS_OFF); dmd.setPixel(15,12,GRAPHICS_OFF); dmd.setPixel(16,4,GRAPHICS_OFF); dmd.setPixel(16,5,GRAPHICS_OFF); dmd.setPixel(16,11,GRAPHICS_OFF); dmd.setPixel(16,12,GRAPHICS_OFF); } } } String leadNull(int digits){ // Функция добавляет ведущий ноль String out = ""; if(digits < 10) out += "0"; return out + String(digits); } String WeatherDisplay(){ char * out = strtok(icon,"-"); // Выделяем первую часть из строки до символа '-' String ret=" "; while (out != NULL) { // Выделяем последующие части строки в цикле, пока значение out не станет нулевым (пустым) if (String(out) == "skc"){ // Перебираем в условиях все возможные варианты, зашифрованные в названии иконки // Serial.println("Yasno"); // ret=ret+"Ясно ";} ret=ret+"Yasno ";} else if (String(out) == "ovc"){ // Serial.println("Pasmurno"); // ret=ret+"Пасмурно ";} ret=ret+"Pasmurno ";} else if (String(out) == "bkn"){ // Serial.println("Oblachno"); ret=ret+"Облачно ";} else if (String(out) == "ra"){ // Serial.println("Dozhd'"); // ret=ret+"Дождь ";} ret=ret+"Dozhd ";} else if (String(out) == "ts"){ // Serial.println("Groza"); // ret=ret+"Гроза ";} ret=ret+"Groza ";} else if (String(out) == "sn"){ // Serial.println("Sneg"); // ret=ret+"Снег ";} ret=ret+"Sneg ";} else if (String(out) == "bl"){ // Serial.println("Metel'"); // ret=ret+"Метель ";} ret=ret+"Metel ";} else if (String(out) == "fg"){ // Serial.println("Tuman"); // ret=ret+"Туман ";} ret=ret+"Tuman ";} else if (String(out) == "n"){ // Serial.println("\nTemno"); // ret=ret+"Ночь ";} ret=ret+"Temno ";} else if (String(out) == "d"){ // Serial.println("\nSvetlo"); // ret=ret+"День ";} ret=ret+"Svetlo ";} out = strtok(NULL,"-"); // Выделяем очередную часть } return ret; }
Неплохо, но можно пару комментариев?
- при выводе цифр нужно учитывать ширину символов, иначе выглядит неровно - на картинке цифра 1 явно слишком смещена влево.
- не понятно, почему только сообщение "Облачно" удостоилось быть показанным кириллицей, а все остальные в транслите...
И вопрос - библиотеку DMD2 для ЕСП пришлось допиливать или все заработало "из коробки" ?
Добавлю - Вы меня немного опередили, собирался делать точно такие же часы, но на СТМ32... а теперь, скорее всего, уже смысла нет.
Неплохо, но можно пару комментариев?
- при выводе цифр нужно учитывать ширину символов, иначе выглядит неровно - на картинке цифра 1 явно слишком смещена влево.
- не понятно, почему только сообщение "Облачно" удостоилось быть показанным кириллицей, а все остальные в транслите...
И вопрос - библиотеку DMD2 для ЕСП пришлось допиливать или все заработало "из коробки" ?
Добавлю - Вы меня немного опередили, собирался делать точно такие же часы, но на СТМ32... а теперь, скорее всего, уже смысла нет.
1. Да единичка смещена, по уму ее бы перерисивать на ширину 8 пикселей, да лень родилась чуть раньше меня :).
2. ну это чтобы юные копипастеры помучалсь... а кто в теме легко сам перепишет.
3. "DMD2 для ЕСП все заработало "из коробки" "
4. тогда с Вас шрифты для esp8266 под DMD2, как для СТМ32 сделали. это конечно, если время найдете.
единичку поправил, строки 187-190 надо заменить на
бинарник погода текушая для Копейска.
Я так понимаю, Вы еспшку к матрице подключили напрямую? И яркость нормальная? Мне кажется, что нужно согласование уровней делать. Я не могу добиться нормальной яркости матрицы (P10 красная) от ESP8266, а от ардуины ярко светит. Как у Вас подкючено?
Матрицы, надеюсь, питаете отдельно хорошим БП на 5в?
У меня зеленые матрицы подключены к СТМ32 (тоже 3.3в) - без всякого согласования уровней с яркостью порядок
Да, с питанием всё в порядке. На ардуине вообще без питания работает, только подключаю колодку 16 пиновую и светит ярко, просто какой-то бегущий текст.