ESP32 튜토리얼 43/55 - IoT 인터넷 날씨 스테이션 | SunFounder의 ESP32 IoT 학습 키트
이 튜토리얼에서는 SunFounder의 ESP32와 카메라 확장 보드를 사용하여 인터넷에 연결된 기상 관측소를 구축합니다. 이 프로젝트는 ESP32가 온도와 습도를 포함한 실시간 날씨 데이터를 검색하고 LCD 화면에 표시할 수 있게 합니다. 이 애플리케이션은 ESP32의 기능을 보여줄 뿐만 아니라 외부 API에서 데이터를 가져오고 파싱하는 방법을 시연합니다.

튜토리얼을 진행하면서 구성 요소를 배선하고, 코드를 구성하고, 모든 것이 원활하게 함께 작동하는지 확인합니다. 최종 결과는 10초마다 판독값을 업데이트하여 현재 기상 조건을 명확하고 간결하게 표시하는 완전한 기능의 기상 관측소가 됩니다(비디오 00:30에서 확인 가능).
하드웨어 설명
이 프로젝트에 사용된 주요 구성 요소는 ESP32 마이크로컨트롤러, LCD 디스플레이 및 필요한 배선입니다. ESP32에는 내장 Wi-Fi와 Bluetooth가 장착되어 있어 인터넷에 연결하고 데이터를 검색할 수 있습니다. LCD 디스플레이는 온도와 습도를 포함한 현재 날씨 정보를 표시합니다.
사용 중인 LCD는 16x2 문자 디스플레이로, 각각 16자의 두 줄을 표시할 수 있습니다. 이는 날씨 정보 출력에 충분합니다. ESP32는 I2C를 통해 LCD와 통신하므로 두 개의 데이터 라인만 사용하여 배선을 단순화합니다.
데이터시트 세부 정보
| 제조업체 | 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 인터페이스를 사용하므로 LCD의 SDA 핀을 ESP32의 GPIO21에 연결하고 SCL 핀을 GPIO22에 연결하세요. LCD의 전원 및 접지 핀을 각각 ESP32의 5V 및 GND 핀에 연결해야 합니다.
다음으로 포함된 리튬 배터리 또는 USB 연결을 사용하여 ESP32에 올바르게 전원을 공급하세요. 배터리는 휴대성을 제공하고 USB 연결은 프로그래밍 및 디버깅에 유용합니다. 마지막으로 모든 연결이 안전한지 확인하여 기능을 방해할 수 있는 느슨한 배선 문제를 피하세요.
코드 예제 및 설명
프로그램의 설정 단계에서 직렬 통신을 초기화하고 제공된 SSID와 비밀번호를 사용하여 Wi-Fi 네트워크에 연결합니다. 다음 코드 스니펫은 Wi-Fi 연결을 처리합니다:
WiFi.begin(ssid, password);
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("IP 주소로 Wi-Fi 네트워크에 연결됨: ");
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());
여기서 도시, 국가 코드 및 API 키를 포함하는 API 요청 URL을 구성합니다. 그런 다음 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"); // "°" 문자
lcd.print("C ");
lcd.print("H:");
lcd.print(myObject["main"]["humidity"]);
lcd.print("%");
이 코드 스니펫은 현재 시간, 기상 조건, 온도 및 습도로 LCD 디스플레이를 업데이트합니다. 이전 표시를 지우고 각 줄의 적절한 위치에 커서를 설정합니다.
시연 / 기대 효과
배선과 프로그래밍이 성공적으로 완료되면 기상 관측소가 Wi-Fi에 연결되고 10초마다 날씨 데이터를 가져오기 시작합니다. LCD 화면에 현재 온도, 습도 및 기상 조건이 표시되는 것을 볼 수 있습니다. ESP32가 Wi-Fi에 연결하지 못하면 직렬 모니터에 오류 메시지가 출력됩니다.
OpenWeatherMap 서비스에서 차단되지 않도록 API 호출 한도에 유의하세요. 데이터 검색에 문제가 발생하면 API 키를 확인하고 도시 및 국가 코드가 올바르게 지정되었는지 확인하세요(영상 15:45 참조).
영상 타임스탬프
- 00:00 시작
- 2:00 프로젝트 소개
- 5:04 OpenWeather 계정
- 6:11 배선
- 8:05 Arduino 코드 설명
- 14:13 코드의 JSON 요소
- 20:23 Arduino IDE에서 ESP32 보드 및 COM 포트 선택
- 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
파일📁
파일이 없습니다.