BLE 기반 자동 관수 · 자동 조명 · 실시간 모니터링
(주)더바이오그룹 — 더 좋은 농장 프로젝트
전라북도 전주시 재배 시설에서 촬영한 실제 개발·운영 사진
Arduino Uno 기반 BLE 무선 제어 스마트 재배기
HC-05 블루투스 모듈, SoftwareSerial(D6/D7), 9600baud JSON 프로토콜
DHT22 온도(±0.5°C) 및 습도(±2%RH) 실시간 측정, D2 연결
DS1302 RTC 모듈, 관수/조명 자동 on/off, EEPROM 설정 유지
2채널 릴레이, CH1=D8 모터, CH2=D9 조명, Active-LOW 방식
Arduino Uno 핀 배치 및 주변기기 연결
| 부품 | 핀 번호 | 기능 | 방향 | 비고 |
|---|---|---|---|---|
| HC-05 RX | D6 | BLE 수신 | Arduino→BLE | SoftwareSerial |
| HC-05 TX | D7 | BLE 송신 | BLE→Arduino | SoftwareSerial |
| DHT22 | D2 | 온습도 센서 | Input | OneWire 데이터 |
| DS1302 SCK | D13 | RTC 클럭 | Output | Serial Clock |
| DS1302 IO | D12 | RTC 데이터 | I/O | Bidirectional |
| DS1302 RST | D11 | RTC 리셋 | Output | Chip Enable |
| 릴레이 CH1 | D8 | 모터(관수) | Output | Active-LOW |
| 릴레이 CH2 | D9 | 조명(LED) | Output | Active-LOW |
| GPIO 출력 | 릴레이 상태 | 회로 | 부하 |
|---|---|---|---|
| HIGH (1) | 열림 (OFF) | 개방 | 정지 |
| LOW (0) | 닫힘 (ON) | 통전 | 구동 |
핀 연결 및 전원 분배 상세 블록도
JSON 기반 양방향 BLE 4.0 통신 — 5개 메시지 타입
앱에서 3초 간격으로 디바이스 상태를 폴링합니다. 온습도 센서값, 모터/조명 설정값, 현재 동작 상태를 일괄 반환합니다.
{"type":"SENSOR_STATUS","values":[0,0]}
| 필드 | 타입 | 예시 | 설명 |
|---|---|---|---|
TYPE |
string | "SENSOR_STATUS" |
메시지 타입 식별자 |
DEVICE_NAME |
string | "TBF_02" |
디바이스 식별자 (BLE 광고명) |
TEMP |
float | 25.5 |
현재 온도 (°C) — DHT22 센서 |
HUM |
float | 50.0 |
현재 습도 (%) — DHT22 센서 |
MOTOR_INTERVAL_IN_SEC |
int | 40 |
모터 1회 가동 시간 (초) |
MOTOR_TIME_MAX_TICK |
int | 1800 |
모터 전체 주기 (초) — 30분 배수 |
LIGHT_RUN_INTERVAL |
int | 3600 |
조명 점등 시간 (초) — 1시간 단위 |
LIGHT_STOP_INTERVAL |
int | 3600 |
조명 소등 시간 (초) — 1시간 단위 |
MOTOR_STATUS |
int | 1 / 0 |
모터 현재 상태 — 1=ON, 0=OFF |
LIGHT_STATUS |
int | 1 / 0 |
조명 현재 상태 — 1=ON, 0=OFF |
{"TYPE":"SENSOR_STATUS",
"DEVICE_NAME":"TBF_02",
"TEMP":25.5,"HUM":50,
"MOTOR_INTERVAL_IN_SEC":40,
"MOTOR_TIME_MAX_TICK":1800,
"LIGHT_RUN_INTERVAL":3600,
"LIGHT_STOP_INTERVAL":3600,
"MOTOR_STATUS":1,
"LIGHT_STATUS":0}__FIN__
모터의 가동 시간과 전체 주기를 설정합니다. 설정값은 EEPROM에 즉시 저장되어 전원 복구 후에도 유지됩니다.
{"type":"SET_MOTOR","values":[intervalSec, cycleSec]}
cycleSec % 1800 === 0
— 30분 단위 필수
| 파라미터 | 범위 | 단위 | 설명 |
|---|---|---|---|
values[0] |
10 ~ 120 | 초 | 1회 가동 시간 |
values[1] |
1800 × N | 초 | 전체 주기 (30분 배수) |
{"TYPE":"SET_MOTOR","RESULT":"1"}__FIN__
조명(LED)의 점등/소등 주기를 설정합니다. 특수값 -1로 상시 ON 또는 상시 OFF를 지정할 수 있습니다.
{"type":"SET_LIGHT","values":[runSec, stopSec]}
값 % 3600 === 0
— 1시간 단위 필수 (특수값 제외)
runSec = -1
stopSec = -1
| 파라미터 | 범위 | 단위 | 설명 |
|---|---|---|---|
values[0] |
3600 ~ 43200 or -1 | 초 | 점등 시간 (1~12시간) |
values[1] |
3600 ~ 43200 or -1 | 초 | 소등 시간 (1~12시간) |
{"TYPE":"SET_LIGHT","RESULT":"1"}__FIN__
장비 점검용 단시간 모터 테스트 명령입니다. 운영 설정에 영향을 주지 않습니다.
{"type":"TEST_MOTOR","values":[3,6]}
{"TYPE":"TEST_MOTOR","RESULT":"1"}__FIN__
LED 동작 확인용 테스트 명령입니다. 운영 설정에 영향을 주지 않습니다.
{"type":"TEST_LIGHT","values":[3,3]}
{"TYPE":"TEST_LIGHT","RESULT":"1"}__FIN__
JSON 파싱 실패 시 오류 카운터가 증가합니다. 3회 연속 실패 시 자동으로 BLE 연결을 해제(disconnect)합니다. 정상 메시지를 수신하면 카운터는 즉시 0으로 리셋됩니다.
모든 BLE 메시지는 __FIN__ 종결자로 끝납니다. BLE 4.0의 20바이트 MTU 제한으로 인해 하나의 JSON 메시지가 여러 패킷으로 분할 전송됩니다. 수신 측에서는 __FIN__이 감지될 때까지 내부 버퍼에 데이터를 누적한 뒤, 종결자를 제거하고 완성된 JSON 문자열을 파싱합니다.
| 메시지 타입 | 방향 | 카테고리 | EEPROM 저장 | 설명 |
|---|---|---|---|---|
SENSOR_STATUS |
READ | 폴링 | — | 전체 상태 조회 (3초 주기) |
SET_MOTOR |
WRITE | 운영 | O | 모터 가동/주기 설정 |
SET_LIGHT |
WRITE | 운영 | O | 조명 점등/소등 주기 설정 |
TEST_MOTOR |
WRITE | 테스트 | — | 모터 단시간 점검 (3초/6초) |
TEST_LIGHT |
WRITE | 테스트 | — | LED 단시간 점검 (3초/3초) |
앱 ↔ BLE ↔ Arduino ↔ 센서/릴레이 간 통신 흐름
React Native 기반 크로스플랫폼 앱 (Android / iOS)
모터(관수)와 조명(LED)의 독립적 자동 스케줄링
// 매 1초 실행 MOTOR_TIME_TICK++ if (TICK < MOTOR_INTERVAL(40s)): MOTOR = ON if (TICK >= MOTOR_INTERVAL): MOTOR = OFF if (TICK >= MOTOR_MAX(1800s)): TICK = 0 // 리셋
// 매 1초 실행 LIGHT_TIME_TICK++ if (TICK < RUN_INTERVAL): LIGHT = ON if (TICK >= RUN && < RUN+STOP): LIGHT = OFF if (TICK >= RUN+STOP): TICK = 0 // 리셋 // 수동 모드 (-1) RUN = -1: 상시 ON (24시간) STOP = -1: 상시 OFF
전원 차단 시에도 설정값 유지 (4 × float, 16 bytes)
| 인덱스 | 주소 | 변수명 | 타입 | 기본값 | 설명 |
|---|---|---|---|---|---|
| 0 | 0x00-0x03 | MOTOR_TIME_MAX_TICK |
float | 1800 (30분) | 모터 전체 주기 |
| 1 | 0x04-0x07 | MOTOR_INTERVAL_IN_SEC |
float | 40 | 모터 가동 시간 |
| 2 | 0x08-0x0B | LIGHT_RUN_INTERVAL |
float | 60 | 조명 점등 시간 |
| 3 | 0x0C-0x0F | LIGHT_STOP_INTERVAL |
float | 60 | 조명 소등 시간 |
void EEPROM_READ() { EEPROM.get(0, MOTOR_TIME_MAX_TICK); EEPROM.get(4, MOTOR_INTERVAL_IN_SEC); EEPROM.get(8, LIGHT_RUN_INTERVAL); EEPROM.get(12, LIGHT_STOP_INTERVAL); }
void EEPROM_WRITE() { EEPROM.put(0, MOTOR_TIME_MAX_TICK); EEPROM.put(4, MOTOR_INTERVAL_IN_SEC); EEPROM.put(8, LIGHT_RUN_INTERVAL); EEPROM.put(12, LIGHT_STOP_INTERVAL); }
Arduino 메인 루프 기반 상태 전이
| 상태 | 트리거 | 동작 | 다음 상태 |
|---|---|---|---|
| INIT | 전원 ON | setup(), EEPROM 읽기, 핀 초기화 | IDLE |
| IDLE | - | 메인 루프 대기 | BLE_RECEIVE or TIMER_TICK |
| BLE_RECEIVE | btSerial.available() | JSON 파싱, 명령 분류 | SENSOR_READ or RELAY_UPDATE |
| SENSOR_READ | SENSOR_STATUS 명령 | DHT22, RTC 데이터 읽기 | BLE_SEND |
| TIMER_TICK | millis() >= 1000 | MOTOR/LIGHT_TICK 증가 | RELAY_UPDATE |
| RELAY_UPDATE | 타이머 or BLE 명령 | digitalWrite() 릴레이 제어 | IDLE |
| BLE_SEND | 응답 준비 완료 | JSON 직렬화, btSerial.print() | IDLE |
void loop() { // 1. BLE 수신 체크 if (btSerial.available()) { parseJSON(received); processCommand(type, values); } // 2. 1초 타이머 if (millis() - lastTick >= 1000) { lastTick = millis(); MOTOR_TIME_TICK++; LIGHT_TIME_TICK++; updateRelays(); } }
프로토타입 1대 기준 필요 부품
| # | 부품명 | 모델/사양 | 수량 | 역할 | 비고 |
|---|---|---|---|---|---|
| 1 | 메인보드 | Arduino Uno (ATmega328P) | 1 | 중앙 제어 | 16MHz, 32KB Flash |
| 2 | BLE 모듈 | HC-05 / HC-06 | 1 | 무선 통신 (9600baud) | BLE 4.0 |
| 3 | 온습도 센서 | DHT22 (AM2302) | 1 | 온도/습도 측정 | ±0.5°C, ±2%RH |
| 4 | RTC 모듈 | DS1302 | 1 | 실시간 시계 | CR2032 배터리 |
| 5 | 릴레이 모듈 | 5V 2채널 (Active-LOW) | 1 | 모터/조명 스위칭 | NO/COM/NC |
| 6 | 관수 펌프 | DC 12V 미니 워터펌프 | 1 | 양액 공급 | 30분 주기 |
| 7 | LED 성장등 | 12V LED 바 | 다수 | 광합성 조명 | 적색+청색 |
| 8 | 전원 공급 | 5V (Arduino) + 12V (릴레이) | 1 | 이중 전원 | DC 어댑터 |
| 9 | 점퍼 와이어 | M-M, M-F 세트 | 1 | 배선 | 듀폰 커넥터 |
| 10 | 브레드보드/PCB | 400홀 또는 커스텀 PCB | 1 | 회로 구성 | 양산 시 PCB |
| 프로젝트명 | 새싹인삼 스마트 재배기 |
| 의뢰처 | (주)더바이오그룹 — 더 좋은 농장 |
| 개발 기간 | 2020.02 ~ 2020.06 |
| 개발 범위 | 하드웨어 설계 + 펌웨어 + 모바일 앱 |
| 디바이스 ID | TBF_02 |
| 현장 | 전라북도 전주시 |
| 재배 품목 | 새싹인삼 (스프라우트) |
| 재배 방식 | LED 실내 다단 수경재배 |
| 관수 방식 | 자동 타이머 양액 공급 |
| 조명 방식 | 자동 타이머 LED 성장등 |