선을 없애면 프로젝트의 역할이 달라진다
지금까지의 아두이노 프로젝트는 대부분 책상 위에서 동작했다. 버튼을 누르면 LED가 켜지고, 센서값은 시리얼 모니터나 작은 화면에 표시되었다. 여기에 통신 기능을 더하면 장치의 성격이 달라진다. 스마트폰에서 명령을 보내고, 다른 방에 있는 센서값을 확인하고, 웹 대시보드에서 그래프를 볼 수 있다.
일상적인 비유로 보면 통신은 장치에 붙이는 "말하는 방법"이다. 시리얼 통신은 바로 옆 사람에게 짧은 문장을 주고받는 방식에 가깝다. 블루투스는 가까운 거리의 스마트폰이나 컴퓨터와 직접 대화하는 방법이다. Wi-Fi는 공유기를 통해 집 안 네트워크나 인터넷까지 나가는 길이다.
중요한 점은 통신을 붙인다고 회로 원칙이 사라지지 않는다는 것이다. LED에는 여전히 저항이 필요하고, 모터에는 여전히 드라이버와 별도 전원이 필요하다. 무선 통신은 출력 장치를 직접 구동하는 힘이 아니라, 어떤 동작을 할지 알려 주는 명령 통로다.
AI 생성 이미지
가까운 거리 제어: HC-05 블루투스 모듈
HC-05 같은 블루투스 모듈은 입문자가 스마트폰 제어를 실습하기 좋은 부품이다. 핵심은 간단하다. 스마트폰의 블루투스 터미널 앱에서 문자를 보내면, HC-05가 그 문자를 아두이노의 시리얼 입력처럼 전달한다. 그래서 아두이노 입장에서는 "무선으로 들어온 문자"도 Serial.read()로 읽는 문자와 거의 같은 방식으로 다룰 수 있다. HC-05는 마이크로컨트롤러와 UART 시리얼 통신으로 데이터를 주고받는 Bluetooth Classic SPP 방식의 모듈로 설명된다1.
다만 여기서 말하는 스마트폰 실습은 보통 안드로이드폰을 기준으로 생각하는 편이 안전하다. HC-05는 Bluetooth Low Energy, 즉 BLE 모듈이 아니라 Bluetooth Classic의 시리얼 포트 프로파일을 사용한다. 그래서 최신 iPhone에서는 일반적인 취미용 앱으로 HC-05에 직접 연결하기 어렵다. iOS 기기와 연결하고 싶다면 HM-10 같은 BLE 모듈이나 ESP32의 BLE 기능을 검토하는 편이 낫다.
기본 연결은 다음처럼 생각하면 된다.
| HC-05 핀 | Arduino Uno 연결 | 설명 |
|---|---|---|
| VCC | 5V | 모듈 보드에 따라 5V 입력을 받는 경우가 많지만, 제품 표시를 확인한다. |
| GND | GND | 반드시 공통 기준을 맞춘다. |
| TXD | D10 | HC-05가 보내는 데이터를 아두이노가 받는다. |
| RXD | D11 | 아두이노가 보내는 데이터를 HC-05가 받는다. 5V 신호는 전압 분배로 낮추는 것이 안전하다. |
여기서는 D10, D11을 사용해 소프트웨어 시리얼을 만든다. 아두이노 Uno의 하드웨어 시리얼 D0, D1은 USB 업로드와 시리얼 모니터에도 쓰이므로, 초보자는 먼저 다른 핀으로 분리해 실습하는 편이 문제를 줄인다.
HC-05의 RXD는 3.3V 논리 입력을 기준으로 하는 경우가 많다. Uno의 D11 출력은 5V이므로, D11과 HC-05 RXD 사이에 1kΩ과 2kΩ 정도의 저항으로 전압 분배를 만들어 신호를 낮추면 안전하다. 예를 들어 D11에서 1kΩ 저항을 지나 HC-05 RXD로 들어가고, 그 지점에서 2kΩ 저항을 GND로 내려 주면 약 3.3V 수준의 신호가 된다. 반대로 HC-05 TXD에서 Uno D10으로 들어오는 3.3V 신호는 대개 Uno가 HIGH로 읽을 수 있다.
먼저 LED 하나를 제어해 보자.
#include <SoftwareSerial.h>
const int btRxPin = 10; // Arduino가 받는 핀: HC-05 TXD 연결
const int btTxPin = 11; // Arduino가 보내는 핀: HC-05 RXD 연결
const int ledPin = 13;
SoftwareSerial bluetooth(btRxPin, btTxPin);
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
bluetooth.begin(9600);
Serial.println("Bluetooth ready");
}
void loop() {
if (bluetooth.available()) {
char command = bluetooth.read();
Serial.print("Command: ");
Serial.println(command);
if (command == '1') {
digitalWrite(ledPin, HIGH);
} else if (command == '0') {
digitalWrite(ledPin, LOW);
}
}
}스마트폰 블루투스 터미널 앱에서 1을 보내면 LED가 켜지고, 0을 보내면 꺼진다. 시리얼 모니터에는 받은 문자가 출력된다. 이 출력은 중요하다. LED가 반응하지 않을 때 "명령이 아두이노까지 도착했는지"를 먼저 확인할 수 있기 때문이다.
문제가 생기면 다음 순서로 점검한다.
스마트폰이나 컴퓨터가 HC-05와 페어링되었는가?
앱에서 연결 버튼을 눌렀는가?
iPhone으로 실습하고 있다면, HC-05가 아니라 BLE 모듈이 필요한 상황은 아닌가?
HC-05의 TXD와 Arduino의 RX 핀이 서로 교차 연결되었는가?
GND가 공통으로 연결되었는가?
코드의 통신 속도와 모듈 속도가 맞는가? 입문 예제는 보통 9600bps에서 시작한다.
업로드가 안 된다면 D0, D1을 사용하고 있지는 않은가?
서보모터를 붙일 때도 원리는 같다. 스마트폰이 A, B, C 같은 문자를 보내면 아두이노가 각도를 바꾼다. 다만 서보 전원은 이전 장에서 배운 것처럼 충분한 전류를 공급할 수 있어야 한다. 블루투스 명령은 신호일 뿐이고, 모터를 움직이는 힘은 전원에서 나온다.
Wi-Fi가 필요한 순간
블루투스는 가까운 거리의 직접 제어에 좋다. 하지만 집 밖에서 확인하거나, 여러 사용자가 웹 화면으로 센서값을 보거나, 데이터를 장기간 저장하려면 Wi-Fi가 더 적합하다.
기존 Arduino Uno R3에는 Wi-Fi가 기본으로 들어 있지 않다. 이때 선택지는 세 가지다.
첫째, Uno에 별도 Wi-Fi 모듈을 붙인다. 배선과 전원, 펌웨어, 명령 방식까지 신경 써야 하므로 입문 단계에서는 난도가 올라간다.
둘째, Arduino Uno R4 WiFi처럼 Wi-Fi 기능이 포함된 보드를 선택한다. Uno R4 WiFi는 Uno 형태를 유지하면서 Renesas RA4M1 마이크로컨트롤러와 ESP32-S3 기반 무선 기능을 함께 제공하는 보드로 소개된다2. Espressif도 Uno R4 WiFi의 ESP32-S3 보조 프로세서가 Wi-Fi와 Bluetooth Low Energy 연결을 담당한다고 설명한다3. 기존 Uno 스타일의 핀 배열과 실습 흐름을 유지하고 싶다면 좋은 선택이다.
셋째, ESP32 계열 보드를 처음부터 사용한다. ESP32는 Wi-Fi와 블루투스 기능을 내장한 보드가 많고 가격도 비교적 낮다. 다만 대부분 3.3V 논리 전압을 사용하므로 5V 센서나 모듈을 연결할 때 전압 호환성을 더 주의해야 한다.
간단히 정리하면 다음과 같다.
| 상황 | 추천 방향 |
|---|---|
| 스마트폰으로 같은 방에서 LED, 서보를 제어 | HC-05 같은 블루투스 모듈 |
| iPhone과 직접 연결하는 블루투스 실습 | BLE 모듈 또는 ESP32 BLE |
| 기존 Uno 실습을 이어가며 Wi-Fi 사용 | Uno R4 WiFi |
| 작고 저렴한 IoT 장치 제작 | ESP32 계열 보드 |
| 여러 센서값을 웹 대시보드로 확인 | Wi-Fi 보드 + 클라우드 또는 웹 서버 |
| 인터넷 없이 장치 내부 부품끼리 통신 | I2C, SPI, UART |
데이터를 보내기 전에 형식을 먼저 정한다
IoT 프로젝트에서 초보자가 자주 놓치는 부분은 "어떻게 보낼지"보다 "무엇을 어떤 모양으로 보낼지"다. 센서값을 무작정 자주 보내면 보기 어렵고, 통신도 불안정해진다.
예를 들어 온습도 장치를 만든다면 먼저 데이터 형식을 정한다.
temp=24.6,hum=51.2또는 웹과 클라우드에서 다루기 쉬운 JSON 형태로 보낼 수 있다.
{"temp":24.6,"hum":51.2,"unit":"C"}처음 실습에서는 temp=24.6 같은 단순한 형식이 읽기 쉽다. 나중에 서버나 앱과 연결할 때는 JSON이 편하다. 중요한 것은 값을 받는 쪽과 보내는 쪽이 같은 약속을 사용해야 한다는 점이다. temp가 섭씨인지 화씨인지, 습도가 정수인지 소수인지, 값이 몇 초마다 갱신되는지 정해 두어야 한다.
전송 주기도 함께 정한다.
온도, 습도: 5초~60초 간격으로도 충분한 경우가 많다.
조도, 거리: 화면 표시용이면 0.2초~1초 간격이 적당하다.
버튼 이벤트: 일정 주기보다 "상태가 바뀔 때" 보내는 편이 효율적이다.
모터 정지 명령: 지연되면 위험할 수 있으므로 즉시 처리해야 한다.
이때 앞에서 배운 millis() 구조가 그대로 쓰인다. Wi-Fi를 쓴다고 해서 loop()를 오래 멈추면 안 된다.
unsigned long previousSendTime = 0;
const unsigned long sendInterval = 5000;
void loop() {
unsigned long now = millis();
if (now - previousSendTime >= sendInterval) {
previousSendTime = now;
float temp = readTemperature(); // 사용하는 센서 라이브러리에 맞게 작성
float hum = readHumidity(); // 사용하는 센서 라이브러리에 맞게 작성
Serial.print("temp=");
Serial.print(temp, 1);
Serial.print(",hum=");
Serial.println(hum, 1);
// Wi-Fi나 클라우드 전송 코드는 이 위치에 둔다.
}
// 버튼, 화면, 모터 안전 조건도 계속 확인할 수 있다.
}위 코드의 readTemperature()와 readHumidity()는 설명을 위한 자리 표시자다. 실제로는 DHT, BME280 같은 센서 라이브러리에서 제공하는 읽기 함수를 쓰거나, 직접 만든 함수로 바꾸어야 한다.
클라우드 대시보드를 사용할 때도 구조는 비슷하다. 장치, 변수, 대시보드를 만들고, 코드에서 센서값을 변수에 넣은 뒤 주기적으로 동기화한다. Arduino IoT Cloud 예제 흐름도 장치 등록, Thing 생성, 클라우드 변수 추가, 대시보드 위젯 연결, 코드에서 ArduinoCloud.update() 호출이라는 순서로 설명된다4.
통신 방식별로 어울리는 자리가 있다
모든 통신을 Wi-Fi로 해결하려고 하면 오히려 복잡해진다. 가까운 부품끼리 빠르게 주고받을 때는 짧은 유선 통신이 안정적이다. 반대로 스마트폰이나 인터넷과 연결하려면 무선 통신이 필요하다.
| 통신 방식 | 거리 감각 | 주 용도 | 입문자가 주의할 점 |
|---|---|---|---|
| UART 시리얼 | 보드와 모듈 사이의 짧은 거리 | HC-05, GPS, 디버깅 | RX/TX 교차 연결, 보드레이트 일치 |
| I2C | 같은 장치 내부의 짧은 배선 | LCD, OLED, 센서 여러 개 | SDA/SCL 핀, 주소 충돌, 풀업 |
| SPI | 같은 장치 내부의 짧은 배선, 빠른 통신 | SD 카드, 고속 센서, 디스플레이 | 배선 수가 많고 CS 핀 관리 필요 |
| Bluetooth Classic | 같은 방 또는 가까운 거리 | HC-05를 이용한 스마트폰·PC 직접 제어 | 페어링, 앱 호환성, 명령 형식 |
| BLE | 같은 방 또는 가까운 거리 | iOS/Android 앱 연동, 저전력 장치 | 기존 시리얼 통신과 사용 방식이 다를 수 있음 |
| Wi-Fi | 공유기 범위, 인터넷 확장 가능 | 웹 서버, 클라우드, 원격 모니터링 | 비밀번호 관리, 연결 끊김 처리, 보안 |
I2C와 SPI는 인터넷에 연결하는 기술이 아니다. 센서나 화면처럼 한 장치 안의 부품을 연결하는 데 적합하다. Bluetooth Classic은 HC-05처럼 간단한 무선 시리얼 링크가 필요할 때 편하고, BLE는 스마트폰 앱 호환성과 저전력 동작이 중요할 때 자주 선택된다. Wi-Fi는 인터넷이나 클라우드로 나가야 할 때 선택한다.
IoT 보안은 나중 일이 아니다
LED 하나를 켜는 실습에서는 보안이 멀게 느껴질 수 있다. 하지만 원격 제어 대상이 문 잠금장치, 히터, 펌프, 모터라면 이야기가 달라진다. 잘못된 명령이 실제 위험으로 이어질 수 있다.
입문 단계에서 지킬 기본 원칙은 다음과 같다.
첫째, 비밀번호를 코드에 그대로 공개하지 않는다. 예제 공유나 깃허브 업로드를 할 때 Wi-Fi SSID와 비밀번호가 들어간 파일을 함께 올리지 않는다. 클라우드 도구의 Secret 저장 기능이나 별도 설정 파일을 사용한다.
둘째, 공개 Wi-Fi에서 중요한 장치를 제어하지 않는다. 카페나 학교의 공개 네트워크는 누가 같은 네트워크에 있는지 알기 어렵다. 실습은 개인 공유기나 안전한 테스트망에서 시작한다.
셋째, 원격 명령은 허용 목록 방식으로 처리한다. 들어온 문자를 그대로 실행하지 말고, 1, 0, STOP, OPEN처럼 정해 둔 명령만 받는다. 알 수 없는 명령은 무시하고 시리얼 모니터에 기록한다.
넷째, 위험한 출력에는 안전 기본값을 둔다. 통신이 끊기면 모터를 멈추고, 센서값이 비정상적이면 히터를 끄고, 일정 시간 새 명령이 없으면 자동 정지하는 식이다.
다섯째, 인터넷 공유기에서 포트를 함부로 열지 않는다. 외부에서 직접 접속하게 만드는 포트 포워딩은 편해 보이지만, 보안 설정을 이해하지 못한 상태에서는 위험하다. 처음에는 인증 기능이 있는 클라우드 서비스나 로컬 네트워크 실습부터 시작하는 편이 안전하다.
작은 IoT 프로젝트 설계 순서
무선 기능을 붙일 때는 부품부터 고르기보다 프로젝트 질문을 먼저 정한다.
누가 값을 보거나 명령을 보낼 것인가? 스마트폰 한 대인가, 웹 사용자 여러 명인가?
거리는 어느 정도인가? 같은 책상, 같은 방, 집 밖 중 어디인가?
무엇을 보낼 것인가? 온도, 습도, 버튼 상태, 경고 메시지 중 무엇인가?
얼마나 자주 보낼 것인가? 0.1초마다 필요한가, 10초마다 충분한가?
잘못된 명령이나 연결 끊김이 생기면 장치는 어떻게 멈출 것인가?
이 질문에 답하면 기술 선택이 쉬워진다. 같은 방에서 안드로이드폰으로 서보 각도를 바꾸는 프로젝트라면 HC-05와 문자 명령으로 충분하다. iPhone과 직접 연결해야 한다면 BLE 모듈이나 ESP32 BLE를 고려한다. 집 밖에서 화분의 토양 습도를 확인하려면 Wi-Fi 보드와 대시보드가 필요하다. 여러 센서와 화면이 한 상자 안에 들어 있다면 I2C나 SPI로 내부 부품을 묶고, Wi-Fi는 외부 보고용으로만 쓰면 된다.
통신은 프로젝트를 멋있게 보이게 하는 장식이 아니다. 입력, 처리, 출력 사이에 "거리"를 넣는 방법이다. 이제 아두이노는 손이 닿는 곳에서만 반응하는 실험 장치가 아니라, 멀리 있는 사람에게 상태를 알려 주고 명령을 받아 움직이는 작은 시스템이 된다.
참고
1HC-05 6-Pin Bluetooth Module, No Button | ShillehTek Product Manual
2Arduino® UNO R4 WiFi – 32-bit MCU with WiFi & Bluetooth — Arduino Official Store
3Arduino UNO R4 WiFi Featuring ESP32-S3 Coprocessor | Espressif Systems
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.