ESP32 บทเรียน 43/55 - สถานีตรวจอากาศอินเทอร์เน็ต IoT | ชุดเรียนรู้ IoT ESP32 ของ SunFounder
ในบทช่วยสอนนี้ เราจะสร้างสถานีตรวจอากาศที่เชื่อมต่ออินเทอร์เน็ตโดยใช้ ESP32 และบอร์ดเสริมกล้องจาก SunFounder โปรเจกต์นี้ช่วยให้ ESP32 ดึงข้อมูลสภาพอากาศแบบเรียลไทม์ รวมถึงอุณหภูมิและความชื้น และแสดงผลบนหน้าจอ LCD แอปพลิเคชันนี้ไม่เพียงแต่แสดงความสามารถของ ESP32 แต่ยังสาธิตวิธีการดึงและแยกวิเคราะห์ข้อมูลจาก API ภายนอกอีกด้วย

เมื่อเราดำเนินไปตามบทช่วยสอน เราจะต่อวงจรส่วนประกอบ กำหนดค่าโค้ด และตรวจสอบให้แน่ใจว่าทุกอย่างทำงานร่วมกันได้อย่างราบรื่น ผลลัพธ์สุดท้ายจะเป็นสถานีตรวจอากาศที่ทำงานได้เต็มรูปแบบซึ่งอัปเดตค่าที่อ่านได้ทุก 10 วินาที โดยแสดงสภาพอากาศปัจจุบันอย่างชัดเจนและกระชับ (ในวิดีโอที่เวลา 00:30)
อธิบายฮาร์ดแวร์
ส่วนประกอบหลักที่ใช้ในโปรเจกต์นี้ประกอบด้วยไมโครคอนโทรลเลอร์ ESP32 จอแสดงผล LCD และการเดินสายไฟที่จำเป็น ESP32 มี Wi-Fi และบลูทูธในตัว ช่วยให้เชื่อมต่ออินเทอร์เน็ตและดึงข้อมูลได้ จอ LCD จะแสดงข้อมูลสภาพอากาศปัจจุบัน รวมถึงอุณหภูมิและความชื้น
LCD ที่เราใช้เป็นจอแสดงผลอักขระขนาด 16x2 ซึ่งหมายความว่าสามารถแสดงได้ 2 บรรทัด บรรทัดละ 16 ตัวอักษร ซึ่งเพียงพอสำหรับการแสดงข้อมูลสภาพอากาศของเรา ESP32 จะสื่อสารกับ LCD ผ่าน I2C ซึ่งช่วยลดความซับซ้อนของการเดินสายโดยใช้สายข้อมูลเพียงสองเส้น
รายละเอียดจาก Datasheet
| ผู้ผลิต | Espressif |
|---|---|
| หมายเลขชิ้นส่วน | ESP32-WROOM-32 |
| แรงดันไฟฟ้าลอจิก/IO | 3.3 V |
| แรงดันไฟฟ้าจ่าย | 3.0–3.6 V |
| กระแสเอาต์พุต (ต่อช่อง) | สูงสุด 12 mA |
| กระแสสูงสุด (ต่อช่อง) | 40 mA |
| คำแนะนำความถี่ PWM | 1 kHz |
| เกณฑ์แรงดันไฟฟ้าอินพุตลอจิก | 0.3 V (ต่ำ), 0.7 V (สูง) |
| แรงดันตก / RDS(on) / อิ่มตัว | 0.5 V |
| ขีดจำกัดความร้อน | -40 ถึง 85 °C |
| แพ็กเกจ | QFN48 |
| หมายเหตุ / รุ่นต่างๆ | มีหลายรุ่นสำหรับการใช้งานที่แตกต่างกัน |
- ตรวจสอบให้แน่ใจว่า ESP32 ได้รับพลังงานจากแหล่งจ่าย 3.3 V ที่เสถียร
- ใช้กราวด์ร่วมกันสำหรับส่วนประกอบทั้งหมดเพื่อหลีกเลี่ยงปัญหาการสื่อสาร
- ตรวจสอบที่อยู่ I2C ของ LCD โดยใช้เครื่องสแกน I2C
- ตรวจสอบสถานะการเชื่อมต่อ Wi-Fi เพื่อหลีกเลี่ยงการตัดการเชื่อมต่อระหว่างการดึงข้อมูล
- จัดการข้อผิดพลาดการแยกวิเคราะห์ JSON เพื่อความทนทานในการดึงข้อมูล
คำแนะนำการเดินสายไฟ

ในการต่อวงจรส่วนประกอบ ให้เริ่มต้นด้วยการเชื่อมต่อ LCD เข้ากับ ESP32 LCD จะใช้อินเทอร์เฟซ I2C ดังนั้นให้เชื่อมต่อพิน SDA ของ LCD เข้ากับ GPIO21 บน ESP32 และพิน SCL เข้ากับ GPIO22 ตรวจสอบให้แน่ใจว่าได้เชื่อมต่อพินไฟและกราวด์ของ LCD เข้ากับพิน 5V และ GND บน ESP32 ตามลำดับ
จากนั้น ตรวจสอบให้แน่ใจว่า ESP32 ได้รับพลังงานอย่างถูกต้องโดยใช้แบตเตอรี่ลิเธียมที่ให้มาหรือการเชื่อมต่อ USB แบตเตอรี่ให้ความสะดวกในการพกพา ในขณะที่การเชื่อมต่อ USB มีประโยชน์สำหรับการเขียนโปรแกรมและการดีบัก สุดท้าย ตรวจสอบการเชื่อมต่อทั้งหมดว่าปลอดภัยดีเพื่อหลีกเลี่ยงปัญหาสายไฟหลวมที่อาจรบกวนการทำงาน
ตัวอย่างโค้ดและคำอธิบาย
ในขั้นตอนการตั้งค่าโปรแกรมของเรา เราจะเริ่มต้นการสื่อสารแบบอนุกรมและเชื่อมต่อกับเครือข่าย Wi-Fi โดยใช้ SSID และรหัสผ่านที่ให้ไว้ โค้ดต่อไปนี้จัดการการเชื่อมต่อ Wi-Fi:
WiFi.begin(ssid, password);
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Connected to WiFi network with IP Address: ");
Serial.println(WiFi.localIP());
โค้ดนี้ช่วยให้แน่ใจว่า ESP32 เชื่อมต่อกับเครือข่าย Wi-Fi ที่ระบุก่อนดำเนินการดึงข้อมูลใดๆ หากการเชื่อมต่อล้มเหลว มันจะพยายามเชื่อมต่อใหม่ต่อไป
ถัดไป เราจำเป็นต้องส่งคำขอ HTTP GET เพื่อดึงข้อมูลสภาพอากาศ ซึ่งทำได้โดยใช้โค้ดต่อไปนี้:
String serverPath = "http://api.openweathermap.org/data/2.5/weather?q=" + city + "," + countryCode + "&units=metric" + "&APPID=" + openWeatherMapApiKey;
jsonBuffer = httpGETRequest(serverPath.c_str());
ที่นี่ เราสร้าง URL สำหรับคำขอ API ซึ่งรวมถึงเมือง รหัสประเทศ และคีย์ API ของเรา จากนั้นเรียกใช้ฟังก์ชัน httpGETRequest เพื่อดึงข้อมูลสภาพอากาศ
สุดท้าย เราจะแยกวิเคราะห์การตอบสนอง JSON และแสดงข้อมูลที่เกี่ยวข้องบน LCD:
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(time);
lcd.print(" ");
lcd.print(myObject["weather"][0]["main"]);
lcd.setCursor(0, 1);
lcd.print("T:");
lcd.print(myObject["main"]["temp"]);
lcd.print("\xDF"); // "°" char
lcd.print("C ");
lcd.print("H:");
lcd.print(myObject["main"]["humidity"]);
lcd.print("%");
โค้ดนี้จะอัปเดตจอ LCD ด้วยเวลา สภาพอากาศ อุณหภูมิ และความชื้นปัจจุบัน โดยจะล้างการแสดงผลก่อนหน้าและวางเคอร์เซอร์ในตำแหน่งที่เหมาะสมสำหรับแต่ละบรรทัด
การสาธิต / สิ่งที่คาดหวัง
เมื่อเดินสายไฟและเขียนโปรแกรมสำเร็จ สถานีตรวจอากาศของคุณจะเชื่อมต่อกับ Wi-Fi และเริ่มดึงข้อมูลสภาพอากาศทุก 10 วินาที คุณจะเห็นอุณหภูมิ ความชื้น และสภาพอากาศปัจจุบันแสดงบนหน้าจอ LCD หาก ESP32 ไม่สามารถเชื่อมต่อกับ Wi-Fi ได้ มันจะพิมพ์ข้อความแสดงข้อผิดพลาดไปยังจอภาพอนุกรม
โปรดระวังขีดจำกัดการเรียกใช้ API เพื่อหลีกเลี่ยงการถูกบล็อกจากบริการ OpenWeatherMap หากคุณพบปัญหาใดๆ ในการดึงข้อมูล ให้ตรวจสอบคีย์ API ของคุณและตรวจสอบให้แน่ใจว่าระบุเมืองและรหัสประเทศของคุณอย่างถูกต้อง (ในวิดีโอที่ 15:45)
ไทม์สแตมป์ของวิดีโอ
- 00:00 เริ่มต้น
- 2:00 แนะนำโปรเจกต์
- 5:04 บัญชี OpenWeather
- 6:11 การเดินสายไฟ
- 8:05 อธิบายโค้ด Arduino
- 14:13 องค์ประกอบ JASON ในโค้ด
- 20:23 การเลือกบอร์ด ESP32 และพอร์ต COM ใน Arduino IDE
- 22:05 การสาธิตสถานีตรวจอากาศบน LCD1602
- 23:45 การสาธิตสถานีตรวจอากาศบน LCD2004
/*
Rui Santos
Complete project details at Complete project details at https://RandomNerdTutorials.com/esp32-http-get-open-weather-map-thingspeak-arduino/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/
#include <LiquidCrystal_I2C.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <Arduino_JSON.h>
// Replace the next variables with your SSID/Password combination
const char* ssid = "SSID";
const char* password = "PASSWORD";
// Your Domain name with URL path or IP address with path
String openWeatherMapApiKey = "openWeatherMapApiKey";
// Replace with your country code and city
// Fine the country code by https://openweathermap.org/find
String city = "CITY";
String countryCode = "COUNTRY CODE";
// THE DEFAULT TIMER IS SET TO 10 SECONDS FOR TESTING PURPOSES
// For a final application, check the API call limits per hour/minute to avoid getting blocked/banned
unsigned long lastTime = 0;
// Timer set to 10 minutes (600000)
//unsigned long timerDelay = 600000;
// Set timer to 10 seconds (10000)
unsigned long timerDelay = 10000;
String jsonBuffer;
// set the LCD number of columns and rows
int lcdColumns = 16;
int lcdRows = 2;
// set LCD address, number of columns and rows
// SDA -> GPIO21, SCL -> GPIO22
// lcd address is 0x27, run an I2C scanner sketch
LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows);
// NTP Server time
const char* ntpServer = "pool.ntp.org";
long gmtOffset_sec = 0;
int daylightOffset_sec = 0; //3600;
void setup() {
Serial.begin(115200);
// WiFi
WiFi.begin(ssid, password);
Serial.println("Connecting");
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to WiFi network with IP Address: ");
Serial.println(WiFi.localIP());
Serial.println("Timer set to 10 seconds (timerDelay variable), it will take 10 seconds before publishing the first reading.");
// initialize LCD
lcd.init();
// turn on LCD backlight
lcd.backlight();
}
void loop() {
// Send an HTTP GET request
if ((millis() - lastTime) > timerDelay) {
// Check WiFi connection status
if(WiFi.status()== WL_CONNECTED){
String serverPath = "http://api.openweathermap.org/data/2.5/weather?q=" + city + "," + countryCode + "&units=metric" + "&APPID=" + openWeatherMapApiKey;
jsonBuffer = httpGETRequest(serverPath.c_str());
Serial.println(jsonBuffer);
JSONVar myObject = JSON.parse(jsonBuffer);
// JSON.typeof(jsonVar) can be used to get the type of the var
if (JSON.typeof(myObject) == "undefined") {
Serial.println("Parsing input failed!");
return;
}
// Serial.print("JSON object = ");
// Serial.println(myObject);
// Serial.print("Temperature: ");
// Serial.println(myObject["main"]["temp"]);
// Serial.print("Pressure: ");
// Serial.println(myObject["main"]["pressure"]);
// Serial.print("Humidity: ");
// Serial.println(myObject["main"]["humidity"]);
// Serial.print("Wind Speed: ");
// Serial.println(myObject["wind"]["speed"]);
// Get time
gmtOffset_sec = myObject["timezone"];
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
// time =
String time = printLocalTime();
// LCD Print
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(time);
lcd.print(" ");
lcd.print(myObject["weather"][0]["main"]);
lcd.setCursor(0, 1);
lcd.print("T:");
lcd.print(myObject["main"]["temp"]);
lcd.print("\xDF"); // "°" char
lcd.print("C ");
lcd.print("H:");
lcd.print(myObject["main"]["humidity"]);
lcd.print("%");
}
else {
Serial.println("WiFi Disconnected");
}
lastTime = millis();
}
}
String printLocalTime(){
struct tm timeinfo;
if(!getLocalTime(&timeinfo)){
Serial.println("Failed to obtain time");
return "null";
}
// Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
// get time format HH:MM
char timeHour[3];
strftime(timeHour,3, "%H", &timeinfo);
char timeMinute[3];
strftime(timeMinute,3, "%M", &timeinfo);
String time = String(timeHour) + ":" + String(timeMinute);
Serial.println(time)
; return time;
}
String httpGETRequest(const char* serverName) {
WiFiClient client;
HTTPClient http;
// Your Domain name with URL path or IP address with path
http.begin(client, serverName);
// Send HTTP POST request
int httpResponseCode = http.GET();
String payload = "{}";
if (httpResponseCode>0) {
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
payload = http.getString();
}
else {
Serial.print("Error code: ");
Serial.println(httpResponseCode);
}
// Free resources
http.end();
return payload;
}
Common Course Links
Common Course Files
แหล่งข้อมูลและเอกสารอ้างอิง
-
เอกสารESP32 Tutorial 43/55 - SunFounder doc page for IoT Internet Weather Stationdocs.sunfounder.com
ไฟล์📁
ไม่มีไฟล์ที่พร้อมใช้งาน