Internet метеостанция на ESP-01+OLED

Leon111_09

★★★✩✩✩✩
6 Июн 2021
642
148
55
Таганрог
forum.wisecomp.ru
Ну,как всегда: скука привела к этому проекту.Скажу сразу-я НЕ автор скетча,я только сделал небольшую модификацию его: адаптировал под ESP-01,сделал переводы на русский язык ключевых комментариев (для лучшего понимания начинающими),так же добавил и свои комментарии.

90605748.jpg

И так,начнем.

Для получения данных о погоде вам надо зарегистрироваться на openweathermap.org/ и получить API ключ (API key). Сразу после регистрации вам предлагается API ключ по умолчанию (Default). Но вы можете сгенерировать свой ключ и дать ему название.
Затем соберите схему, показанную на рисунке:
81682725.jpg
В среде Arduino IDE в списке плат у вас должна уже присутствовать плата ESP8266 (Node MCU). Как её добавить в список, описано во многих источниках.
Для работы скетча установите из менеджера библиотек Adafruit_GFX.h, Adafruit_SSD1306.h и ArduinoJson.h.
В меню идем Инструменты -> Управлять библиотеками. В открывшемся окне в строке поиска набираем название библиотеки. Когда библиотека будет найдена, нажимаем кнопку Установка.

Важно! При установке ArduinoJson.h выберите пятую версию библиотеки. Шестая версия библиотеки ArduinoJson выдает ошибку в скетче.

В исходном проекте используется дисплей с 7 выводами. У меня же в наличии SSD1306 с 4 выводами, поэтому в скетче использовал фрагменты для 4-выводного дисплея.
В строке поиска на сайте openweathermap.org введите название города на английском и буквенный код страны (например, Chita, Ru) и проверьте выдаваемые погодные данные. На веб-странице с погодными данными для вашего города можно узнать код города (ID). Он указан в адресной строке браузера в самом её конце. Например, для Читы ID будет https://openweathermap.org/city/2025339. Этот код может пригодиться при настройке погодного виджета, например Gis Weather:

В скетче вместо звездочек пропишите название своей Wi-Fi сети (ssid), пароль для нее (password), API ключ (API_Key). Замените названия города и страны на свои.

Текст кода:
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h> // http web access library
#include <ArduinoJson.h> // JSON decoding library.Ставить пятой серии-шестая серия сыпет ошибками
// Libraries for SSD1306 OLED display
#include <Wire.h> // include wire library (for I2C devices such as the SSD1306 display)
#include <Adafruit_GFX.h> // include Adafruit graphics library
#include <Adafruit_SSD1306.h> // include Adafruit SSD1306 OLED display driver
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Описание дисплея SSD1306, подключенного к I2C (контакты SDA, SCL)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// установите имя SSID Wi-Fi и пароль
const char * ssid = "********";
const char * password = "**********";

// установка местоположения и ввод ключа API
String Location = "Taganrog, RU";
String API_Key = "**************";

void setup(void)
{
  Serial.begin(115200);
  Wire.begin(0,2 );   //эта строка нужна для программирования ESP-01.Любой другой модуль-строку закомментировать
                      //в этой строке задаются выводы на пины подключения дисплея.
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 
    Serial.println("SSD1306 allocation failed");
    for (;;);
  }
  delay(1000);

  display.clearDisplay(); // clear the display buffer
  display.setTextColor(WHITE, BLACK);
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.println(" Internet Weather");
  display.print(" Station - Taganrog");
  display.display();

  WiFi.begin(ssid, password);

  Serial.print("Connecting.");

  while ( WiFi.status() != WL_CONNECTED )
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("connected");

  delay(1000);
}

void loop()
{
  if (WiFi.status() == WL_CONNECTED) //Check WiFi connection status
  {
    WiFiClient client1;

    HTTPClient http; //Declare an object of class HTTPClient

    // specify request destination
    http.begin(client1, "http://api.openweathermap.org/data/2.5/weather?q=" + Location + "&APPID=" + API_Key); // !!

    int httpCode = http.GET(); // send the request

    if (httpCode > 0) // check the returning code
    {
      String payload = http.getString(); //Получите полезную нагрузку ответа на запрос

      DynamicJsonBuffer jsonBuffer(512);

      // Parse JSON object
      JsonObject& root = jsonBuffer.parseObject(payload);
      if (!root.success()) {
        Serial.println(F("Parsing failed!"));
        return;
      }

      float temp = (float)(root["main"]["temp"]) - 270.15; // получить температуру в °C
      int humidity = root["main"]["humidity"]; // получить влажность в %
      float pressure = ((float)(root["main"]["pressure"]) * 0.750061) - 2.72; // получить давление в мм рт. ст. для Taganrog, Ru
      //В строке float pressure = ((float)(root["main"]["pressure"]) * 0.750063) - 59;
      //значение давления из гПа переводится в мм рт. ст. и вычитается поправка 59.
      // Полученное значение более-менее соответствует реальному атмосферному давлению.
      float wind_speed = root["wind"]["speed"]; // получить скорость ветра в m/s
      int wind_degree = root["wind"]["deg"]; // получить направление ветра в °

      // print data
      Serial.printf("Temperature = %.2f°C\r\n", temp);
      Serial.printf("Humidity = %d %%\r\n", humidity);
      Serial.printf("Pressure = %.3f mmHg\r\n", pressure);
      Serial.printf("Wind speed = %.1f m/s\r\n", wind_speed);
      Serial.printf("Wind degree = %d°\r\n\r\n", wind_degree);

      display.setCursor(0, 24);
      display.printf("Temperature: %5.1f C\r\n", temp);
      display.printf("Humidity : %d %%\r\n", humidity);
      display.printf("Pressure : %.1f mmHg\r\n", pressure);
      display.printf("Wind speed : %.1f m/s\r\n", wind_speed);
      display.printf("Wind degree: %d", wind_degree);
      display.drawRect(109, 24, 3, 3, WHITE); // поместить символ степени ( ° )
      display.drawRect(97, 56, 3, 3, WHITE);
      display.display();
    }

    http.end(); //Close connection
  }

  delay(60000); // wait 1 minute
}
// End of code.
//поправку можно вычислить, используя пропорцию.
//Например, высота места 640 метров. Составляем пропорцию:
//671/59 = 640/x. Тогда поправка x = 59*640/671 = 56.3 мм рт. ст.

Если у дисплея другой адрес (не 0x3C), то на монитор порта будет выдано сообщение SSD1306 allocation failed.

Я предположил, что выдаваемое значение атмосферного давления относится к уровню моря. Город Чита выше уровня моря на 670 метров. Атмосферное давление на этой высоте меньше на 59 мм рт. ст. относительно уровня моря согласно таблице на сайте dpva.ru/Guide/GuidePhysics/GuidePhysicsPressure/BarometerCompensation/.

В строке float pressure = ((float)(root["main"]["pressure"]) * 0.750063) - 59.0; значение давления из гПа переводится в мм рт. ст. и вычитается поправка 59. Полученное значение более-менее соответствует реальному атмосферному давлению.
Если вашего значения высоты нет в таблице, то поправку можно вычислить, используя пропорцию. Например, высота места 640 метров. Составляем пропорцию:

671/59 = 640/x. Тогда поправка x = 59*640/671 = 56.3 мм рт. ст.

Направление ветра выводится в градусах. Направление северного ветра (ветер, дующий с севера) принято за 0 градусов, восточный 90 градусов.

Первоисточник

Internet метеостанция на ESP-01+OLED
 

Вложения

Leon111_09

★★★✩✩✩✩
6 Июн 2021
642
148
55
Таганрог
forum.wisecomp.ru
Чё-то не видно где здесь модуль ESP-01...
Адаптация заключалась всего в одной строчке:
код:
Wire.begin(0,2 );
Без этой строчки не получалось переназначить пины на вывод информации на ОЛЕД.
 

PiratFox

★★★★★✩✩
13 Фев 2020
1,722
481
@Leon111_09, да это понятно. Просто, если уж указали для ESP-01, так его и рисуйте на схеме. Да и на фото совсем не ESP-01. Я так понимаю, в "железе" Вы это не собирали.
 

Leon111_09

★★★✩✩✩✩
6 Июн 2021
642
148
55
Таганрог
forum.wisecomp.ru
если уж указали для ESP-01, так его и рисуйте на схеме.
Рисунок взят из схемы источника.Рисовать новый посчитал не нужным поскольку на ЕСП-01 всего два пина.
Да и на фото совсем не ESP-01.
Естественно. Но этот скетч можно залить на любой другой ЕСП.
Я так понимаю, в "железе" Вы это не собирали.
Я ВСЕГДА сначала провожу такие "эксперименты" прежде чем выложить на форум, провожу на себе.
изображение_viber_2023-02-15_19-39-51-366.jpg
Просто я сделал его,так сказать, на макетном стенде: проверка его работоспособности на время.
 

Leon111_09

★★★✩✩✩✩
6 Июн 2021
642
148
55
Таганрог
forum.wisecomp.ru
Четыре, если не использовать UART.
Это с UART четыре, а так штатно только два: D0 и D2. Знаю,что умельцы выводят непосредственно с чипа еще дополнительные пины (даже один аналоговый), но новичкам это не нужно совсем.
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,834
589
44
Это с UART четыре, а так штатно только два: D0 и D2.
Штатно четыре: GPIO0..3
UART, который использует два пина можно отключить. Не знаю как на ардуиновском "загрузчике" это делать, но на родном SDK это делается одной галочкой в настройках.
 

Leon111_09

★★★✩✩✩✩
6 Июн 2021
642
148
55
Таганрог
forum.wisecomp.ru
первый и третий пины используются для запуска/программирования чипа.Официально из описания доступно только два пина.
Не знаю как на ардуиновском "загрузчике" это делать,
Честно говоря я тоже этого не знаю.
на родном SDK это делается одной галочкой в настройках.
А вот с этого места пожалуйста поподробней: никогда не отказывался от лишних знаний.
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,834
589
44
первый и третий пины используются для запуска/программирования чипа.Официально из описания доступно только два пина.
Официально это GPIO-пины, пины общего назначения. Вы можете их вручную дергать, либо проинициализировать на них аппаратные блоки ввода-вывода, например тот же UART. Но для запуска и/или прошивки на некоторые из них нужно подавать определенный уровень.

А вот с этого места пожалуйста поподробней: никогда не отказывался от лишних знаний.
Например в VisualGDB.
Отключаем стандартный UART:
1676559810118.png
Отключаем вывод логов во время загрузки, на всякий случай, вдруг портом будет дергать:
1676559868500.png

Или то же самое через make menuconfig, если через VSCode или подобных писать.
1676559930678.png
1676559947472.png
1676559966511.png
 
Изменено:
  • Лойс +1
Реакции: Leon111_09

Геннадий П

★★★★★★✩
14 Апр 2021
1,834
589
44
в этот огрызок
Ну, он не такой уж и огрызок в умелых руках.
Только если хочешь нормальную отладку через JTAG, то лучше сразу переходи на ESP32, с ним китайский клон JLink нормально работает, с ESP8266 я его не победил.
 

Leon111_09

★★★✩✩✩✩
6 Июн 2021
642
148
55
Таганрог
forum.wisecomp.ru
Учитывая что они не на много дороже,
Я бы так не сказал: я на алике под другие проекты покупал есп-01 примерно за 45/50р.шт., а 32-я еспшка стоит раза в три дороже. Да и жирновато будет под этот проект ставить такой мощный мк. У меня на этом же стенде что на фото почти год проработал скетч на интернет-часы (бралось время с сервера и выводилось на экран,не добавилось сейчас ни грамма лишнего по электронике-все в таком же виде).Я 32-ю (если понадобится) лучше под другой проект использую.У меня сейчас на ней Ка-радио работает :).
зато имеешь нормальный контроллер с нормальными аппаратными возможностями,
Которые в этом проекте не будут использоваться совсем-не задействованы.Это как на КАМАЗе мешок картошки каждый день возить на базар :).
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,834
589
44
а 32-я еспшка стоит раза в три дороже
Для разового проекта совсем не критично. Вы же не в производство запускаете.
Да и жирновато будет под этот проект ставить такой мощный мк.
Как и ESP8266. :sneaky:

Ну да ладно, не мне за вас решать какой МК использовать.
 
  • Лойс +1
Реакции: Leon111_09

Vitaliy Sumrak

✩✩✩✩✩✩✩
7 Окт 2023
1
0
Для получения данных в метрической системе нужно добавить: + "&units=metric"
В таком виде
http.begin(client1, "http://api.openweathermap.org/data/2.5/weather?q=" + Location + "&appid=" + API_Key + "&units=metric");

Для получения погоды по координатам нужно добавить:
http.begin(client1, "http://api.openweathermap.org/data/2.5/weather?lat=" + Latitude + "&lon=" + Longitude + "&appid="+ API_Key);
Где Latitude - широта, а Longitude - долгота. С условием что вы их заранее объявили.
Ну или в таком виде:
http.begin(client1, "http://api.openweathermap.org/data/2.5/weather?lat=55.7522&lon=37.6156&appid="+ API_Key); // Geo coords: Moscow