Dự báo thời tiết với NodeMCU và SSD1306 OLED | Dự án IoT

Dự báo thời tiết với NodeMCU và SSD1306 OLED | Dự án IoT

Trong dự án IoT này, tôi sẽ trình bày cách tạo một thết bị dự báo thời tiết đơn giản bằng cách sử dụng board phát triển Wi-Fi ESP8266 NodeMCU (ESP-12E) và màn hình OLED SSD1306 (128 × 64 Pixel). NodeMCU lấy dữ liệu thời tiết (nhiệt độ, độ ẩm, áp suất, tốc độ gió và độ gió) từ trang web thời tiết  openweathermap.org  và hiển thị trên màn hình SSD1306.

SSD SSD1306 được sử dụng trong dự án được cấu hình để hoạt động ở chế độ I2C, một số board OLED SSD1306 có thể yêu cầu sửa đổi nhỏ phần cứng (để chọn giữa chế độ SPI hoặc chế độ I2C) như hàn, nối dây.

Yêu cầu phần cứng:

  • Board phát triển ESP8266 NodeMCU
  • Màn hình OLED SSD1306 với độ phân giải 128 × 64 Pixel
  • cáp micro USB (để lập trình và cấp nguồn cho mạch)
  • Breadboard
  • Dây nối

Sơ đồ mạch cho dự án:

Hình ảnh sau đây cho thấy sơ đồ mạch dự án.

Và đây là mạch fritzing :

Các chân SDA và SCL của bus I2C nối với GPIO4 (D2) và GPIO0 (D3) của board NodeMCU (tương ứng), chúng được nối với các chân SDA và SCL (SCK) của mô-đun hiển thị SSD1306.

Chân reset (RES) của mô-đun hiển thị được kết nối với GPIO5 (D1) của board phát triển NodeMCU.

Mô-đun hiển thị SSD1306 được cấp nguồn 3,3V từ board NodeMCU.

Code cho dự án:

Arduino IDE bên dưới sử dụng trình điều khiển  Adafruit SSD1306 OLED và thư viện Adafruit GFX để liên kết giữa NodeMCU và mô-đun màn hình. Tải xuống các liên kết và cách cài đặt chúng, trong bài sau:

ESP8266 NodeMCU giao tiếp với SSD1306 OLED

Để có được dữ liệu thời tiết, tôi đã sử dụng  trang web openweathermap.org , vì vậy trước tiên chúng ta phải đăng ký tài khoản miễn phí để lấy khóa API quan trọng trong dự án này. Với trang web openweathermap.org, chúng ta có thể:

  • Truy cập dữ liệu thời tiết hiện tại cho bất kỳ vị trí nào, bao gồm hơn 200.000 thành phố
  • Thời tiết hiện tại được cập nhật thường xuyên dựa trên các mô hình và dữ liệu toàn cầu từ hơn 40.000 trạm thời tiết
  • Dữ liệu có sẵn ở định dạng JSON, XML hoặc HTML
  • Có sẵn miễn phí và trả phí cho các tài khoản

Khi bạn đăng nhập vào tài khoản của mình (tất nhiên sau khi đăng ký miễn phí), bạn sẽ được chuyển đến khu vực thành viên, đi đến các khóa API và bạn sẽ tìm thấy khóa API của mình như trong hình sau:

Mã API được hiển thị, chúng ta sẽ sử dụng nó sau.

Với khóa đó, chúng ta có thể truy cập dữ liệu thời tiết do trang web cung cấp, tất cả những gì chúng ta làm là nhập URL sau vào trình duyệt web (google Chrome, Mozilla Firefox Nott):

http://api.openweathermap.org/data/2.5/weather?q=CITY,COUNTRY_CODE&APPID=YOUR_API_KEY

Thay thế CITY bằng thành phố bạn muốn có dữ liệu thời tiết, COUNTRY_CODE bằng mã quốc gia cho thành phố đó (ví dụ: UK cho Vương quốc Anh, US cho Hoa Kỳ) và YOU_API_KEY bằng khóa API được hiển thị ở trên.

Ví dụ: thời tiết ở Luân Đôn, URL của Vương quốc Anh là (với khóa API của tôi):

http://api.openweathermap.org/data/2.5/weather?q=London,uk&APPID=1041444a18cfb8448343254a45721b1d

Truy cập URL này bằng trình duyệt web của bạn:

Như đã đề cập ở trên, trang web openweathermap.org cung cấp dữ liệu thời tiết ở định dạng JSON, XML hoặc HTML. Trong dự án này, chúng tôi sẽ sử dụng định dạng JSON có thể được phân tích cú pháp bằng thư viện Arduino có tên ArduinoJSON .

Cài đặt thư viện ArduinoJson:

Dễ dàng cài đặt thư viện ArduinoJson, chúng ta có thể thực hiện bằng cách truy cập:

Arduino IDE –> Sketch –> Include Library –> Manage Libraries

Một cửa sổ mới sẽ mở ra, trong hộp tìm kiếm ghi: arduinojson

chọn phiên bản thư viện (Tôi đang sử dụng phiên bản 5.13.2) và nhấp vào cài đặt.

Chúng ta có thể cài đặt thư viện theo cách thủ công bằng cách tải xuống từ URL sau:

Thư viện ArduinoJSON

Sau khi tải xuống, giải nén tệp nén và một thư mục có tên ArduinoJSON-5.13.2 sẽ xuất hiện. Di chuyển thư mục vào thư mục thư viện Arduino, thư mục nên được đổi tên thành ArduinoJSON (loại bỏ -5.13.2).

Với thư viện tích hợp có tên:  ESP8266HTTPClient, chúng ta có thể đọc các trang http, truy cập một trang rất đơn giản với thư viện này, chỉ bằng cách đặt URL của nó như hiển thị bên dưới nơi tôi đặt URL của thời tiết thành phố London:

http.begin(“http://api.openweathermap.org/data/2.5/weather?q=London,uk&APPID=1041444a18cfb8448343254a45721b1d”);

Sau đó, chúng tôi sẽ đọc và lưu toàn bộ trang JSON dưới dạng một chuỗi:

String payload = http.getString();   //Get the request response payload

Và cuối cùng, thư viện ArduinoJSON thực hiện công việc của mình và giải mã

JsonObject& root = jsonBuffer.parseObject(payload);

Trang web openweathermap.org cung cấp nhiệt độ theo ° K (độ Kelvin) và để chuyển đổi ° K thành ° C (độ C), bằng cách sử dụng dòng sau:

float temp = (float)(root[“main”][“temp”]) 273.15;    // get temperature

Ngoài ra, nó cho áp suất tính bằng hPa (Hectopascal) với 1hPa = 100 Pascal = 1/1000 bar:

float pressure = (float)(root[“main”][“pressure”]) / 1000; // get pressure

Độ ẩm tính bằng%, tốc độ gió tính bằng m / s (mét trên giây) và độ gió tính bằng độ (°).

Trang web sau đây cung cấp trợ giúp với định dạng JSON:

ArduinoJson Assistant

Trong code, đừng quên thay thế SSID WIFI và PASSWORD WIFI CỦA BẠN .

// set Wi-Fi SSID and password
const char *ssid = “YOUR WIFI SSID”;
const char *password = “YOUR WIFI PASSWORD”;

Ngoài ra, chúng ta có thể đặt vị trí và khóa API bằng hai dòng sau (dòng 25 và 26) trong ví dụ này tôi đang đặt vị trí thành London, Vương quốc Anh và khóa API thành khóa API của tôi:

// set location and API key
String Location = “London,uk”;
String API_Key = “1041444a18cfb8448343254a45721b1d”;

Code hoàn chỉnh:

#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 OLED_RESET 5 // define SSD1306 OLED reset at ESP8266 GPIO5 (NodeMCU D1)
Adafruit_SSD1306 display(OLED_RESET);

// set Wi-Fi SSID and password
const char *ssid = “YOUR WIFI SSID”;
const char *password = “YOUR WIFI PASSWORD”;

// set location and API key
String Location = “London,uk”;
String API_Key = “1041444a18cfb8448343254a45721b1d”;

void setup(void)
{
Serial.begin(9600);
delay(1000);

Wire.begin(4, 0); // set I2C pins [SDA = GPIO4 (D2), SCL = GPIO0 (D3)], default clock is 100kHz

// by default, we’ll generate the high voltage from the 3.3v line internally! (neat!)
display.begin(SSD1306_SWITCHCAPVCC, 0x3D); // initialize with the I2C addr 0x3D (for the 128×64)
// init done

Wire.setClock(400000L); // set I2C clock to 400kHz

display.clearDisplay(); // clear the display buffer
display.setTextColor(WHITE, BLACK);
display.setTextSize(1);
display.setCursor(0, 0);
display.println(” Internet Weather”);
display.print(” Station – London”);
display.display();

WiFi.begin(ssid, password);

Serial.print(“Connecting.”);
display.setCursor(0, 24);
display.println(“Connecting…”);
display.display();
while ( WiFi.status() != WL_CONNECTED )
{
delay(500);
Serial.print(“.”);
}
Serial.println(“connected”);
display.print(“connected”);
display.display();
delay(1000);

}

void loop()
{
if (WiFi.status() == WL_CONNECTED) //Check WiFi connection status
{
HTTPClient http; //Declare an object of class HTTPClient

// specify request destination
http.begin(“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(); //Get the request response payload

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”]) – 273.15; // get temperature in °C
int humidity = root[“main”][“humidity”]; // get humidity in %
float pressure = (float)(root[“main”][“pressure”]) / 1000; // get pressure in bar
float wind_speed = root[“wind”][“speed”]; // get wind speed in m/s
int wind_degree = root[“wind”][“deg”]; // get wind degree in °

// print data
Serial.printf(“Temperature = %.2f°C\r\n”, temp);
Serial.printf(“Humidity = %d %%\r\n”, humidity);
Serial.printf(“Pressure = %.3f bar\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.2f C\r\n”, temp);
display.printf(“Humidity : %d %%\r\n”, humidity);
display.printf(“Pressure : %.3fbar\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); // put degree symbol ( ° )
display.drawRect(97, 56, 3, 3, WHITE);
display.display();

}

http.end(); //Close connection

}

delay(60000); // wait 1 minute

}
// End of code.

Hình ảnh sau đây cho thấy dữ liệu trong Arduino IDE serial monitor:

 

 

 

 

 

 

 

 

 

 

 

 

 

1 phản hồi

Leave a Reply to Tuấn Cancel reply

  • Em có lập trình như trên cho ESP8266, có hiển thị trên Serial Monitor được, nhưng không hiển thị được trên SSD1306, mình cần thêm gì nữa vậy anh

    Tuấn Reply

Trả lời Tuấn Hủy

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *