파이어베이스로 두 아두이노 간 온습도 데이터 전송하기
부품 및 소모품
| Arduino UNO | × | 2 |
| ESP8266 ESP-01 | × | 2 |
| DHT11 온습도 센서 (3핀) | × | 1 |
| DFRobot I2C 16×2 LCD 디스플레이 | × | 1 |
| 브레드보드 (범용) | × | 2 |
| 수/암 점퍼 와이어 | × | 1 |
앱 및 온라인 서비스
| Arduino IDE |
| Google Firebase |
프로젝트 개요
이 IoT 튜토리얼에서는 DHT11 센서로 온습도를 읽어 첫 번째 아두이노 우노에서 ESP8266을 통해 파이어베이스로 전송하고, 두 번째 아두이노 우노가 파이어베이스에서 데이터를 읽어 I2C LCD에 표시합니다. 시리얼 통신, Wi-Fi 네트워킹, 클라우드 데이터 저장 등 현대 임베디드 개발자에게 필수적인 기술을 실습할 수 있습니다.
1단계 – 각 보드의 역할 이해
우노는 센서 인터페이스 역할을, ESP8266은 Wi-Fi 게이트웨이 역할을 합니다. 두 보드는 시리얼 포트로 통신하며, ESP8266은 인터넷에 직접 연결되지 않고 Wi-Fi 모듈만 연결합니다. 각 보드용 코드를 분리해 혼란을 방지하세요.
2단계 – 우노에 LCD 연결
핀 수를 줄이기 위해 I2C 방식을 사용합니다. DFRobot 모듈의 20×4 LCD 예제가 바로 작동합니다. 20×4 디스플레이 사용 시 생성자를 LiquidCrystal_I2C lcd(0x3F, 20, 4);로 변경하세요.
3단계 – 두 번째 우노에 DHT11 연결
공식 아두이노 DHT11 튜토리얼을 참고해 배선하고 라이브러리를 설치하세요. 센서는 단일 데이터 핀만 필요합니다(예제에서는 A0).
4단계 – ESP8266을 파이어베이스와 연동
스케치에 Wi-Fi 자격증명과 파이어베이스 프로젝트 세부사항을 설정하세요. 파이어베이스 실시간 데이터베이스는 심플한 JSON 트리를 제공하며, ESP8266은 temperature와 humidity 노드에 값을 기록합니다. 초보자는 튜토리얼 영상을 참고하세요.
5단계 – 시리얼 통신 마스터하기
시리얼 전송 시 필요한 문자열만 출력하세요. 디버깅용 추가 출력은 프로토콜을 깨뜨릴 수 있습니다. 우리 구현에서는 센서 우노가 콤마 구분 문자열(예: 25.3,60.1)을 ESP8266으로 전송하고, ESP8266이 파싱해 파이어베이스로 전달합니다.
6단계 – 업로드 및 테스트
첫 번째 우노에 센서 스케치, 첫 번째 ESP8266에 센서-ESP8266 스케치, 두 번째 ESP8266에 LCD-ESP8266 스케치를 업로드하세요. LCD가 몇 초마다 새로운 측정값으로 업데이트되는지 확인하세요. 점퍼 와이어 분리 전 아두이노 USB 케이블을 먼저 뽑아 의도치 않은 쇼트를 방지하세요.
자주 발생하는 문제 및 해결책
- ESP8266 업로드 실패: IDE에서 제너릭 ESP8266 보드 선택. 그래도 안 되면 보드 리셋, 모듈 재장착 후 재시도.
- 우노 업로드 실패: 업로더 실행 전 USB 케이블 연결 확인. 프로그래밍 중 ESP8266의 GPIO-0(IO0)을 GND에서 분리.
- 시리얼 불일치: ESP8266 TX → 우노 RX, ESP8266 RX → 우노 TX (크로스 연결). 통신 중 비데이터 문자열 출력 금지.
- LCD 글리치: 시리얼 지연으로 LCD에 임의 문자 표시될 수 있음. 새 값 출력 전
lcd.clear() 실행으로 대부분 해결.
코드 스니펫
- lcd_arduino.ino
- lcd_esp8266.ino
- sensor_arduino.ino
- sensor_esp8266.ino
lcd_arduino.ino (아두이노)
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
LiquidCrystal_I2C lcd(0x3F, 20, 4);
String sensorData;
void setup() {
Serial.begin(9600);
lcd.begin(20, 4);
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Temperature: ");
lcd.setCursor(18, 0);
lcd.print("C");
lcd.setCursor(0, 1);
lcd.print("Humidity: ");
lcd.setCursor(15, 1);
lcd.print("%");
}
void loop() {
if (Serial.available()) {
sensorData = Serial.readString();
String temp = sensorData.substring(0, sensorData.indexOf(','));
String hum = sensorData.substring(sensorData.indexOf(',') + 1);
lcd.clear();
lcd.setCursor(13, 0);
lcd.print(temp);
lcd.setCursor(10, 1);
lcd.print(hum);
}
delay(2000);
}
lcd_esp8266.ino (ESP8266)
#include <ESP8266WiFi.h>
#include <FirebaseArduino.h>
#define FIREBASE_HOST "YOUR_FIREBASE_LINK"
#define FIREBASE_AUTH "YOUR_FIREBASE_TOKEN"
#define WIFI_SSID "YOUR_WIFI_SSID"
#define WIFI_PASSWORD "YOUR_WIFI_PASSWORD"
void setup() {
Serial.begin(9600);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) delay(500);
Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
}
void loop() {
String temp = Firebase.getString("temperature");
String hum = Firebase.getString("humidity");
Serial.flush();
Serial.print(temp + "," + hum);
delay(2000);
}
sensor_arduino.ino (아두이노)
#include <SoftwareSerial.h>
#include <dht.h>
#define DHT_PIN A0
DHT dht;
void setup() {
Serial.begin(9600);
}
void loop() {
dht.read11(DHT_PIN);
String data = String(dht.temperature) + "," + String(dht.humidity);
Serial.flush();
Serial.print(data);
delay(2000);
}
sensor_esp8266.ino (ESP8266)
#include <ESP8266WiFi.h>
#include <FirebaseArduino.h>
#define FIREBASE_HOST "YOUR_FIREBASE_LINK"
#define FIREBASE_AUTH "YOUR_FIREBASE_TOKEN"
#define WIFI_SSID "YOUR_WIFI_SSID"
#define WIFI_PASSWORD "YOUR_WIFI_PASSWORD"
void setup() {
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) delay(500);
Serial.begin(9600);
Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
}
void loop() {
if (Serial.available()) {
String payload = Serial.readString();
int comma = payload.indexOf(',');
String temp = payload.substring(0, comma);
String hum = payload.substring(comma + 1);
Firebase.setString("temperature", temp);
Firebase.setString("humidity", hum);
if (Firebase.failed()) {
Serial.println("Failed to write to Firebase");
}
}
delay(2000);
}