1

아두이노 ESP32로 온습도 데이터 수집하기

힘센캥거루
2025년 10월 13일(수정됨)
8
1
116

오늘은 아두이노 ESP32로 온습도를 측정하고 데이터를 전송하는 와이파이 백엽상을 만들어볼 것이다.

해당 내용은 학교에서 진행할 16+1 수업 원고를 바탕으로 작성한 글이다.

1. 준비물

준비물은 간단하다.

ESP32, DHT-22, 전선 3개
아두이노 ESP32로 온습도 데이터 수집하기-1

먼저 ESP32를 간단하게 설명하자면, 와이파이 모듈이 박혀있는 아두이노이다.

하지만 크기는 일반 아두이노보다 훨신 작은 편이다.

2. ESP32 핀맵

아두이노 ESP32로 온습도 데이터 수집하기-2

어어?? 그런데 핀 번호가 좀 이상하다?

이건 지난글에서도 설명했지만, 와이파이 모듈이 들어가면서 핀맵핑이 변경되었기 때문이다.

아래 ESP32 아두이노의 핀맵핑을 올려 준다.

그래도 이 녀석은 GPIO 핀 번호와 핀 이름이 거의 일치하는 듯 하다.

아래의 핀들 중에서도 안전한 D4 핀을 이용해 dht-22를 굴려볼 예정이다.

아두이노 ESP32로 온습도 데이터 수집하기-4

Arduino D 핀

GPIO 번호

주의사항

기능 및 설명

D0

GPIO0

strapping: 부팅 시 LOW 또는 floating 필요

flash 모드 진입에 영향 ([randomnerdtutorials.com][1])

D1

GPIO1 (TX0)

USB 시리얼 충돌 주의

업로드·디버깅용 UART0 TX

D2

GPIO2

strapping: 부팅 시 LOW/floating 필요

on‑board LED → 부팅 영향 있음

D3

GPIO3 (RX0)

USB 시리얼 충돌 주의

UART0 RX, 부팅 시 HIGH

D4

GPIO4

★ 안전

디지털 I/O, ADC2_CH0, 터치 가능

D5

GPIO5

strapping: 부팅 시 HIGH 필요

부트 중 PWM 출력 가능

D6D11

GPIO6–11

절대 사용 금지

내부 SPI 플래시 핀

D12

GPIO12

strapping: 부팅 시 LOW 필요

ADC2_CH5, 터치, 부팅 영향 있음

D13

GPIO13

안전

ADC2_CH4, 터치 가능

D14

GPIO14

부팅 시 PWM 나옴, 부트 스트래핑 가능

ADC2_CH6, 터치 가능

D15

GPIO15

strapping: 부팅 시 HIGH 필요, PWM 출력

ADC2_CH3, 터치 가능

D16

GPIO16

Wrover 모듈 사용 시 PSRAM용 주의

UART2 기본 TX/RX (17/16)

D17

GPIO17

Wrover 모듈 주의

UART2 기본 TX/RX (17/16)

D18, D19, D21–D23, D25–D27, D32–D33

생략

안전

디지털, PWM, I2C, SPI, ADC/DAC 사용 가능

D34, D35, D36(VP), D39(VN)

34,35,36,39

입력 전용, 풀업/풀다운 없음

ADC1 채널 (추가 기능 없음)

3. DHT-11 vs DHT-22

보통 아두이노를 사면 기본적으로 들어있는 온습도 온도계는 DHT-11이다.

색깔이 파란색인 녀석인데, 이걸 쓰면 오차 범위가 2도 정도로 무척 크다.

아래에 DHT와 DHT-22의 성능을 표로 정리해보았다.

항목

DHT-11

DHT-22 (AM2302)

외형

아두이노 ESP32로 온습도 데이터 수집하기-5아두이노 ESP32로 온습도 데이터 수집하기-6

온도 측정 범위

0 ~ 50°C

-40 ~ +80°C

온도 정확도

±2°C

±0.5°C

습도 측정 범위

20 ~ 80% RH

0 ~ 100% RH

습도 정확도

±5% RH

±2~3% RH

측정 해상도

온도: 1°C, 습도: 1% RH

온도: 0.1°C, 습도: 0.1% RH

측정 주기 (샘플링 간격)

1초 이상

2초 이상

데이터 전송 속도

저속

저속

크기

소형

약간 더 큼

가격

저렴

DHT-11보다 비쌈

사용 전압

3 ~ 5V

3 ~ 5V

오차 범위가 너무 크면 데이터를 신뢰할 수 없기에, 오차가 다소 적은 DHT-22를 사용하기로 했다.

이보다 더 정확한 온도를 얻고 싶다면 PT-100 온도계를 쓰면 되지만, 그정도 까지 필요하지는 않은 것 같다.

4. CH340 드라이버 설치

아두이노 ESP32로 온습도 데이터 수집하기-7

위의 사진에서 빨간 동그라미 안에 보면 칩이 하나 박혀있다.

이게 중국에서 만드는 CH340이라는 칩셋인데, 컴퓨터로 치면 CPU에 해당한다고 생각하면 된다.

CH340칩의 드라이버를 제공하는 공식사이트 링크를 건다.

다운받아서 무지성으로 다음을 눌러 설치해주자.

위 파일은 아래의 모든 칩들을 포함하는 드라이버다.

참고로 맥북에서는 해당 칩셋 드라이버를 기본으로 제공하므로 설치할 필요가 없다.

CH340G,CH340T,CH340C,CH340N, CH340K, CH340E,CH340B,CH341A,CH341F, CH341T,CH341B,CH341C,CH341U

5. Arduino IDE 보드관리자 설정

이제 아두이노 IDE에 보드관리자를 세팅해주자.

Arduino IDE 에서 File > Preferences(기본 설정)으로 들어간다.

아두이노 ESP32로 온습도 데이터 수집하기-8

그리고 추가 보드 관리자 URL에 아래의 주소를 복사해 입력한다.

https://espressif.github.io/arduino-esp32/package_esp32_index.json
아두이노 ESP32로 온습도 데이터 수집하기-9아두이노 ESP32로 온습도 데이터 수집하기-10

그리고 보드매니저에서 ESP32를 검색하고, 제공자가 by Espressif Systems인 것을 찾아 설치한다.

아두이노 ESP32로 온습도 데이터 수집하기-11

그리고 USB포트에 아두이노를 연결하면 포트가 자동으로 잡힌다.

이제 해당 포트에 해당하는 아두이노 보드를 골라서 선택해주면 된다.

아두이노 ESP32로 온습도 데이터 수집하기-12

6. 와이파이 연결

그리고 간단한 예제를 하나 업로드 해보자.

파일 -> 예제 -> HttpClient -> BasicHttpsClient를 클릭하면 Http요청 예제가 나온다.

아두이노 ESP32로 온습도 데이터 수집하기-13

이제 이 예제에서 SSID, PASSWORD 부분만 변경해준다.

void setup() {

 USE_SERIAL.begin(115200);

 USE_SERIAL.println();
 USE_SERIAL.println();
 USE_SERIAL.println();

 for (uint8_t t = 4; t > 0; t--) {
 USE_SERIAL.printf("[SETUP] WAIT %d...\n", t);
 USE_SERIAL.flush();
 delay(1000);
 }
// 아래의 SSID에 와이파이 이름, PASSWORD에 비밀번호 입력
 wifiMulti.addAP("SSID", "PASSWORD");
}

혹시 만약 업로드에 실패한다면 업로드 속도를 좀 조절해주자.

도구 -> Upload Speed를 조금 낮은 값으로 변경하면 안정적으로 잘된다.

아두이노 ESP32로 온습도 데이터 수집하기-14

그리고 있는 그대로 예제 사이트로 접속하도록 하면 시리얼 모니터에서 html을 출력한다.

이렇게 까지만 한다면 1/3 정도는 완성한 것이다.

아두이노 ESP32로 온습도 데이터 수집하기-15

7. DHT-22 센서 연결

이제 아두이노에 DHT-22 센서를 연결해 온습도 값을 받아 와보자.

먼저 라이브러리를 찾아 깔아준다.

dht sensor library를 검색해서 adafruit이 제작한 라이브러리를 받아주자.

아두이노 ESP32로 온습도 데이터 수집하기-16

이제 파일->예제로 들어가면 온습도계 예제가 있다.

이 예제들 중 센서 테스트를 한번 해보자.

주석들을 빼고 핵심은 아래와 같다.

아두이노 ESP32로 온습도 데이터 수집하기-17
#include "DHT.h"

#define DHTPIN 4 // 핀번호 지정
#define DHTTYPE DHT22 // DHT 22 
DHT dht(DHTPIN, DHTTYPE);

void setup() {
 Serial.begin(115200); // 시리얼 통신 속도. 115200으로 변경
 Serial.println(F("DHTxx test!"));
 dht.begin();
}

void loop() {
 delay(2000);
 float h = dht.readHumidity();
 float t = dht.readTemperature();
 float f = dht.readTemperature(true); // true 넣으면 화씨 됨

 if (isnan(h) || isnan(t) || isnan(f)) {
 Serial.println(F("Failed to read from DHT sensor!"));
 return;
 }

 float hif = dht.computeHeatIndex(f, h); // 이건 체감온도
 float hic = dht.computeHeatIndex(t, h, false);

 Serial.print(F("Humidity: "));
 Serial.print(h);
 Serial.print(F("% Temperature: "));
 Serial.print(t);
 Serial.print(F("°C "));
 Serial.print(f);
 Serial.print(F("°F Heat index: "));
 Serial.print(hic);
 Serial.print(F("°C "));
 Serial.print(hif);
 Serial.println(F("°F"));
}

이렇게 아두이노로 전송한 뒤 온도가 출력되는걸 시리얼 모니터에서 확인하면 된다.

입으로 한번 후 불어주었더니 습도가 100%까지 치솟았다.

아두이노 ESP32로 온습도 데이터 수집하기-18

이제 아두이노 와이파이 연결과 센서 연결이 해결되었으니, 구글 스프레드 시트 설정으로 넘어가자.

8. 구글 스프레드 시트 설정

왠만하면 그냥 내가 글을 쓰는데, 구글 스프레드 시트 설정만 해도 길이가 너무 길어질 것 같아 예전에 썼던 글을 첨부한다.

아래의 링크에서 한번 확인해보길 바란다.

9. 아두이노에서 Get요청 날리기

이제 구글 스프레드 시트 설정까지 끝났다면, 아두이노에서 GET 요청을 날려볼 차례이다.

위에서 와이파이 연결에 있었던 예제를 가져온다.

여기서 요청 주소만 구글 스크립트로 바꿔주면 된다.

중간부분은 생략하고 올려본다.

#include <Arduino.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <HTTPClient.h>
#include <NetworkClientSecure.h>

...

String host = "https://script.google.com/";
String googleScriptID = "나의 구글 스크립트 아이디";
String scriptUrl = "macros/s/"+googleScriptID+"/exec";
String queryString = "?value1='안녕'&value2='테스트중!'";
String getReqUrl = host + scriptUrl + queryString;

void setup() {
 
 ...

 WiFiMulti.addAP("와이파이 이름", "와이파이 비밀번호");

 ...
}

void loop() {
 NetworkClientSecure *client = new NetworkClientSecure;
 if (client) {
 client->setCACert(rootCACertificate);
 {
 HTTPClient https;
 Serial.print("[HTTPS] begin...\n");
 if (https.begin(*client, getReqUrl)) { // <--- 이부분만 수정하면 됨
 
 ...

 }
 }}
}

이렇게 한 후 실행하면 스프레드 시트로 값이 들어오는게 보인다.

이제 마지막 스텝은 DHT-22의 데이터를 받아 전송하는 것이다.

아두이노 ESP32로 온습도 데이터 수집하기-20

10. 코드 합치기

아두이노 ESP32로 온습도 데이터 수집하기-21

이제 두 코드를 합쳐보자.

코드를 합치기 어렵다면 그냥 무지성으로 AI에게 맡기는 방법도 추천해본다.

일단 나는 먼저 DHT-22의 loop 코드를 변경해 Weather이라는 구조체를 반환하는 함수로 만들어 보았다.

#include "DHT.h"

#define DHTPIN 4   
#define DHTTYPE DHT22   

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(115200);
  dht.begin();
}

struct WeatherData {
  float humi;
  float temp;
  float heat;
  bool valid;
};

WeatherData getWeather() {
  WeatherData data;
  data.humi = dht.readHumidity();
  data.temp = dht.readTemperature();

  if (isnan(data.humi) || isnan(data.temp)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    data.valid = false;
    return data;
  }
  data.valid = true;
  data.heat = dht.computeHeatIndex(data.temp, data.humi, false);

  Serial.print(F("Humidity: "));
  Serial.print(data.humi);
  Serial.print(F("%  Temperature: "));
  Serial.print(data.temp);
  Serial.print(F("°C "));
  Serial.print(F("°Heat index: "));
  Serial.print(data.heat);
  Serial.print(F("°C "));
  return data;
}

여기서 필요한 것들을 적절히 배분해 httpsClient 코드에 합쳐주면 된다.

이제 합쳐보자.

#include <Arduino.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <HTTPClient.h>
#include <NetworkClientSecure.h>
#include "DHT.h"

...
인증서 생략
...

void setClock() {
  ...
}

#define DHTPIN 4   
#define DHTTYPE DHT22   

WiFiMulti WiFiMulti;
DHT dht(DHTPIN, DHTTYPE);
char* SSID = "와이파이 이름";
char* PASSWORD = "와이파이 비번";
String host = "https://script.google.com/";
String googleScriptID = "나의 구글 스크립트 아이디";
String scriptUrl = "macros/s/"+googleScriptID+"/exec";

struct WeatherData {
  ...
};

WeatherData getWeather(); //오류 발생으로 미리 선언해 줌


void setup() {
  dht.begin();
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP(SSID, PASSWORD);
  Serial.print(F("Waiting for WiFi to connect..."));
  while ((WiFiMulti.run() != WL_CONNECTED)) {
    Serial.print(F("."));
  }
  Serial.println(F(" connected"));
  setClock();
}

WeatherData getWeather() {
    ...
}


void loop() {
  NetworkClientSecure *client = new NetworkClientSecure;
  if (client) {
    client->setCACert(rootCACertificate);
    {
      HTTPClient https;
      WeatherData data = getWeather();
      if (!data.valid){
        Serial.println(F("날씨 정보를 얻을 수 없습니다."));
        Serial.println("Waiting 10s before the next round...");
        delay(10000);
        return;
      };
      Serial.print("[HTTPS] begin...\n");
      String queryString = "?value1=" + String(data.humi) + "&value2=" + String(data.temp) ;
      String getReqUrl = host + scriptUrl + queryString;
      if (https.begin(*client, getReqUrl)) {  // HTTPS
        Serial.print("[HTTPS] GET...\n");

        int httpCode = https.GET();

        if (httpCode > 0) {
          Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
        } else {
          Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
        }
        https.end();
      } else {
        Serial.printf("[HTTPS] Unable to connect\n");
      }
    }
    delete client;
  } else {
    Serial.println("Unable to create client");
  }
  Serial.println();
  Serial.println("Waiting 10s before the next round...");
  delay(10000);
}

이렇게 한 후 시리얼 모니터에서 습도, 온도가 뜨고 Get요청 코드가 200이 뜨면 성공한 것.

이제 스프레드 시트에 들어가서 확인해면 된다.

아두이노 ESP32로 온습도 데이터 수집하기-22

11. 추가 작업

추가적으로 체감 온도도 기록하고 싶다면 구글 스크립트를 수정해주면 된다.

파라미터를 파싱하는 부분에서 변수를 추가하거나, 변수명을 변경할 수 있다.

...
for (var param in e.parameter) {
  Logger.log('In for loop, param=' + param);
  var value = stripQuotes(e.parameter[param]);
  Logger.log(param + ':' + e.parameter[param]);
  switch (param) {
    case 'humi':
    rowData[2] = value; // value1 in column C
    result = '습도 기록됨'; 
    break;
    case 'temp':
    rowData[3] = value; // Humidity in column D
    result += ', 온도 기록됨'; 
    break;
    case 'heat':
    rowData[4] = value;
    result += ", 체감 온도 기록됨";
    break

    default:
    result = "지원되지 않는 파라미터 입니다.";
  }
...

물론 이렇게 해주면 아두이노 코드에서도 쿼리스트링을 변경해 주어야 한다.

어차피 개인 프로젝트이기에 이렇게 하는건 앞으로의 유지 보수를 위함이거나, 개인 취향인 것 같다.

12. 후기

과거에 학생들과 실험을 했을 때는 아래와 같은 데이터가 나왔다.

중간에 데이터 결측치는 밤에 전원이 차단되면서 생긴것...

그래도 간단한 장치만 만들어 놓으면 이렇게 자동으로 데이터를 수집해 주니, 이걸 우리는 분석만 하면 된다는 점에서는 무척 좋은 것 같다.

아두이노 ESP32로 온습도 데이터 수집하기-23

만들어진 결과물만 보면 내용이 없어 보이는데 풀어 쓰다보니 글이 엄청나게 길어졌다.

16+1 수업에서 앞에 3시간은 C언어를, 뒤에 2시간은 아두이노 온습도계를, 나머지 시간은 개인 프로젝트를 진행할 예정인데 시간이 부족하지 않을까 걱정이 된다.

아무쪼록 열심히 준비한 수업이 잘 끝나고 여름방학을 맞이했으면 좋겠다.

관련 글

마이크로비트(micro:bit)로 거미로봇 코딩하기
마이크로비트(micro:bit)로 거미로봇 코딩하기
이번에 로봇기술 관련 모임에서 무료로 강의를 하나 개설하셨다.재현고등학교에서 진행하는 마이크로 비트를 이용해 거미로봇을 제어하는 연수였다.아는 선생님께서 신청을 했는데, 당일에 업무랑 겹쳐서 나에게 자리를 양보해주셔서 참여해보기로 했다.상계역에서 걸어서 10분 거리이다...
아두이노로 RFID카드 복제하기
아두이노로 RFID카드 복제하기
오늘은 아두이노로 RFID카드를 복제하는 방법에 대해 써보려고 한다.한번 글을 쓰면 잊어버리지 않기에, 복기하는 차원에서 남긴다.1.RFID 카드의 내부 데이터 구조일반적인 RFID 카드는&nbsp;MIFARE Classic 1K 카드이다.이 카드의 메모리 구조는 아래...
아두이노 D1 R2 사용기
아두이노 D1 R2 사용기
그냥 아두이노 uno로 하면 될 것을, 괜히 내장 와이파이 달린거 써보겠다고 wemos d1 r2를 쓰다가 고생을 꽤나 했다.이 글은 d1 r2와 같이 핀맵핑이 다른 아두이노를 사용하는 이들을 위한 글이다.1. IDE 셋팅아두이노의 종류가 다양해서 각 보드에 맞는 보드...
맥북에서 아두이노 Timed out waiting for packet header 해결 방법
맥북에서 아두이노 Timed out waiting for packet header 해결 방법
맥북에서 아두이노 Wemos D1 R2 연결시 Timed out 문제 해결하는 방법
아두이노와 스프레드시트 연동하기 - 코드 구성하기
아두이노와 스프레드시트 연동하기 - 코드 구성하기
지난 글에서는 아두이노와 스프레드시트 연동을 위한 시트 설정에 대해 알아보았다.이번 글에서는 아두이노 D1 보드에서 https 통신을 이용한 데이터 전송 방법에 대해 알아보자.1. 아두이노 D1 보드 라이브러리 설치하기아두이노 D1 보드를 이용하기 위해선 먼저 보드 라...
아두이노와 스프레드시트 연동하기 - 구글 시트 설정
아두이노와 스프레드시트 연동하기 - 구글 시트 설정
최근에 학생들과 아두이노를 이용해 학교 주변의 온도, 습도를 관측해보고 값을 분석해보기로 했다.&nbsp;아두이노에서 측정한 데이터를 저장하려니 SD카드가 필요했고, 데이터를 확인하기 위해서는 SD카드를 빼고 다시 끼우는 번거로움이 있었다.&nbsp;&nbsp;문득 데...

댓글을 불러오는 중...