интернет часы с погодой на 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 пиновую и светит ярко, просто какой-то бегущий текст.