산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

로라(LoRa) 기반 스마트시티 대기질 모니터링 시스템 – 태양광 자립형 IoT 노드

부품 및 자재

부품 수량
Arduino UNO 1개
Seeed Base Shield V2 1개
NodeMCU ESP8266 브레이크아웃 보드 1개
Seeed 라우드니스(소음) 센서 1개
Seeed Grove – 공기질 센서 v1.3 1개
Seeed Grove – 온습도 센서 (DHT11) 1개
Reyax LoRa 모듈 (RYLR998) 1개
Seeed 소형 태양광 패널 80x100mm 1W 1개
Seeed LiPo Rider Pro (충전/부스트 회로) 1개
리튬폴리머 배터리 3.7V 1개

필요한 도구 및 장비

소프트웨어 및 온라인 서비스

프로젝트 개요

스마트시티와 대기질

세계은행에 따르면 스마트시티는 기술을 활용해 고효율 공공 서비스와 지속가능한 도시 환경을 제공합니다. 이 비전의 핵심은 실시간 환경 모니터링으로, 오염원을 식별하고 데이터 기반 정책 결정(교통 흐름 최적화, 안전한 보행 경로 안내 등)을 지원합니다.

문제점과 해결책

도시 대기 오염은 심각한 건강 위험을 초래하며, 적시 데이터는 완화 대책에 필수적입니다. 저비용 센서 노드의 IoT 네트워크로 대기질과 기상 파라미터를 지속적으로 수집하고, 신뢰성 높고 저전력인 통신 계층과 결합하면 오염 핫스팟을 감지해 선제적으로 대응할 수 있습니다.

프로젝트 계획

본 솔루션은 소음, 온도, 습도, 공기질 주요 환경 지표를 모니터링하고 무선으로 클라우드 플랫폼에 전송합니다. 전체 노드는 1W 태양광 패널과 리튬이온 배터리 백업으로 자율 구동됩니다. 클라우드 대시보드에서 실시간 데이터 시각화가 가능해 즉각적인 인사이트와 장기 추세 분석을 지원합니다.

각 센서를 개별적으로 클라우드에 연결하면 전력 소모와 비용이 증가하므로, 여러 인접 노드의 데이터를 집계해 단일 LoRa 게이트웨이로 전송하는 방식을 채택했습니다. LoRa의 장거리·저전력 특성은 밀집된 도심 배포에 이상적입니다.

로라(LoRa) 기반 스마트시티 대기질 모니터링 시스템 – 태양광 자립형 IoT 노드
센서 노드 → LoRa → 게이트웨이(NodeMCU) → Wi-Fi → Grandeur 클라우드

백엔드 플랫폼으로 Grandeur를 선택한 이유는 아두이노, NodeMCU, 라즈베리파이용 사용자 친화적 SDK와 드래그앤드롭 대시보드 빌더를 제공하기 때문입니다.

태양광 발전은 원격 노드에 지속가능한 무보수 에너지원을 제공하며, 리튬이온 배터리는 일조량이 적은 기간에도 동작을 보장합니다.

센서 노드 제작

노드는 그로브 공기질 센서, 그로브 소음 센서, DHT11 온습도 센서를 통합하며, 모두 Seeed Base Shield에 납땜 없이 꽂기만 하면 되어 조립과 유지보수가 간편합니다.

로라(LoRa) 기반 스마트시티 대기질 모니터링 시스템 – 태양광 자립형 IoT 노드
Base Shield에 그로브 센서 3종 장착

전원 회로

1W 태양광 패널과 Seeed LiPo Rider Pro 충전 보드로 전원을 공급합니다. 이 보드에는 5V 부스트 컨버터가 내장되어 아두이노의 동작 전압 범위를 유지합니다.

LoRa 통신 모듈

Reyax RYLR998 LoRa 트랜시버가 무선 전송을 담당합니다. 이 모듈은 3.6V 로직을 사용하므로, 아두이노의 5V TX 라인을 보호하기 위해 간단한 전압 분할 회로를 추가했습니다.

로라(LoRa) 기반 스마트시티 대기질 모니터링 시스템 – 태양광 자립형 IoT 노드
전압 분할기(저항 2개)로 5V → 3.3V 레벨 시프트

LoRa 모듈을 Base Shield에 연결할 때, Base Shield의 전원 스위치를 3.3V로 설정해야 합니다.

로라(LoRa) 기반 스마트시티 대기질 모니터링 시스템 – 태양광 자립형 IoT 노드
전원 선택 스위치: 3.3V 위치

조립 후 아두이노에서 LoRa 모듈로 AT 명령을 보내 통신을 검증합니다.

로라(LoRa) 기반 스마트시티 대기질 모니터링 시스템 – 태양광 자립형 IoT 노드
시리얼 모니터에서 AT 명령 응답 확인

펌웨어 업로드 및 테스트

제공된 아두이노 스케치를 업로드한 후 시리얼 모니터를 열어 센서 판독값이 정상적으로 전송되는지 확인합니다.

로라(LoRa) 기반 스마트시티 대기질 모니터링 시스템 – 태양광 자립형 IoT 노드
센서 데이터 전송 로그

케이스 조립

첨부된 STL 파일을 3D 프린터로 출력합니다. 피팅 확인 후 양면테이프나 핫글루로 구성품을 케이스 내부에 고정합니다. 태양광 패널은 상단에 장착하고 전원 케이블은 지정된 홀을 통해 배선합니다.

로라(LoRa) 기반 스마트시티 대기질 모니터링 시스템 – 태양광 자립형 IoT 노드
내부 부품 배치
로라(LoRa) 기반 스마트시티 대기질 모니터링 시스템 – 태양광 자립형 IoT 노드
상단 태양광 패널 마운트

모든 구성품 고정 후 현장 배포 준비 완료입니다.

로라(LoRa) 기반 스마트시티 대기질 모니터링 시스템 – 태양광 자립형 IoT 노드
필드 배포 준비 완료된 센서 노드

Grandeur 플랫폼 설정

Grandeur는 디바이스-유저 페어링과 실시간 대시보드를 제공하는 IoT 백엔드입니다. 다음 단계로 프로젝트를 설정하세요:

  1. grandeur.dev에서 새 프로젝트 생성
  2. 유저 계정 등록 (나중 디바이스 페어링에 사용)
  3. 디바이스 모델 정의 – JSON 스키마:
    {"temp":0, "humid":0, "air":0, "noise":0}
  4. 디바이스 인스턴스 생성 → 고유 ID와 액세스 토큰 확보 → 아두이노 펌웨어에 저장
  5. 대시보드 또는 API(pairDevice())로 디바이스-유저 페어링
  6. Canvas 대시보드 구성: 온도, 습도, 소음, 공기질 각각 그래프 위젯 추가 및 변수 바인딩

Canvas 인증 후 사용자는 로그인해 실시간 데이터를 조회할 수 있습니다. 게이트웨이 펌웨어에는 API 키와 디바이스 토큰이 필요합니다.

IoT LoRa 게이트웨이 구축

NodeMCU(ESP8266)가 LoRa 게이트웨이 역할을 합니다. 센서 노드에서 UART로 데이터를 수신해 Wi-Fi로 Grandeur에 전달합니다. 라즈베리파이도 가능하지만, NodeMCU가 프로젝트의 대역폭과 지연 요구사항을 충족하는 소형·저비용 솔루션입니다.

로라(LoRa) 기반 스마트시티 대기질 모니터링 시스템 – 태양광 자립형 IoT 노드
NodeMCU + LoRa 모듈 게이트웨이

게이트웨이 펌웨어 핵심 로직

LoRa 모듈에서 수신한 콤마 구분 페이로드를 파싱해 각 값을 float로 변환하고, Grandeur SDK로 전송합니다.

void process_received_data() {
  start_pos = inputString.indexOf(start_val);
  end_pos = inputString.indexOf(end_val);
  String data_string = inputString.substring(start_pos + 1, end_pos - 1);
  
  int firstCommaIndex = data_string.indexOf(',');
  int secondCommaIndex = data_string.indexOf(',', firstCommaIndex + 1);
  int thirdCommaIndex = data_string.indexOf(',', secondCommaIndex + 1);
  
  String temperature = data_string.substring(0, firstCommaIndex);
  String humidity = data_string.substring(firstCommaIndex + 1, secondCommaIndex);
  String noise_level = data_string.substring(secondCommaIndex + 1, thirdCommaIndex);
  String air_quality = data_string.substring(thirdCommaIndex + 1);
  
  temp = temperature.toFloat();
  humid = humidity.toFloat();
  noise = noise_level.toFloat();
  air = air_quality.toFloat();
  
  inputString = "";
  stringComplete = false;
}

대시보드 화면

로라(LoRa) 기반 스마트시티 대기질 모니터링 시스템 – 태양광 자립형 IoT 노드
실시간 센서 데이터 시각화
로라(LoRa) 기반 스마트시티 대기질 모니터링 시스템 – 태양광 자립형 IoT 노드
장기 추세 분석 차트

펌웨어 소스 코드

센서 노드 (Arduino UNO)

#include "AirQuality.h"  // Grove 공기질 라이브러리
#include "Arduino.h"
#include "DHT.h"

#define DHTPIN 4       // DHT11 디지털 핀
#define DHTTYPE DHT11  // 센서 모델
DHT dht(DHTPIN, DHTTYPE);

AirQuality airqualitysensor;
int current_quality = -1;
const int sampleWindow = 50;  // 20Hz 샘플링
unsigned int sample;
float noise;
float temp, humid;
int airQuality;

void setup() {
  Serial.begin(115200);  // LoRa 통신용 UART
  airqualitysensor.init(14);
  dht.begin();
}

void loop() {
  noise = calculate_sound_in_db();
  airQuality = calculate_air_quality();
  calculate_temp_humid();
  
  String values = String(temp) + "," + String(humid) + "," + String(noise) + "," + String(airQuality);
  String cmd = "AT+SEND=0," + String(values.length()) + "," + values;
  Serial.println(cmd);
  delay(15000);  // 15초 간격 전송
}

float calculate_sound_in_db() {
  unsigned long startMillis = millis();
  float peakToPeak = 0;
  unsigned int signalMax = 0;
  unsigned int signalMin = 1024;
  
  while (millis() - startMillis < sampleWindow) {
    sample = analogRead(A1);
    if (sample < 1024) {
      if (sample > signalMax) signalMax = sample;
      else if (sample < signalMin) signalMin = sample;
    }
  }
  peakToPeak = signalMax - signalMin;
  float db = map(peakToPeak, 0, 1000, 48, 120);
  return db;
}

int calculate_air_quality() {
  current_quality = airqualitysensor.slope();
  return current_quality;
}

void calculate_temp_humid() {
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  if (isnan(h) || isnan(t)) return;
  temp = t;
  humid = h;
}

// 공기질 센서용 타이머 인터럽트
ISR(TIMER1_OVF_vect) {
  if (airqualitysensor.counter == 61) {
    airqualitysensor.last_vol = airqualitysensor.first_vol;
    airqualitysensor.first_vol = analogRead(A0);
    airqualitysensor.counter = 0;
    airqualitysensor.timer_index = 1;
    PORTB = PORTB ^ 0x20;
  } else {
    airqualitysensor.counter++;
  }
}

게이트웨이 (NodeMCU ESP8266)

/* SDK 및 WiFi 라이브러리 포함 */
#include 
#include 
#include 

SoftwareSerial LORA(D7, D8);  // RX, TX

/* 설정값 - 실제 값으로 교체 필요 */
String deviceID = "your device id";
String apiKey = "your api key";
String token = "your device token";
String ssid = "your wifi ssid";
String password = "your wifi password";

/* Grandeur 객체 */
Grandeur::Project project;
Grandeur::Project::Device device;

/* 연결 상태 및 시간 추적 */
int connected = 0;
uint32_t lastUpdate = 0;
String inputString = "";
boolean stringComplete = false;
char start_val = ':';
char end_val = '%';
int start_pos = 0;
int end_pos = 0;
float temp = 0;
float humid = 0;
float air = 0;
float noise = 0;

/* 디바이스 연결 상태 콜백 */
void onConnection(bool status) {
  switch (status) {
    case CONNECTED:
      Serial.println("Device is connected to the cloud.");
      connected = 1;
      lastUpdate = millis();
      return;
    case DISCONNECTED:
      Serial.println("Device is disconnected from the cloud.");
      connected = 0;
      return;
  }
}

/* WiFi 연결 */
void connectWiFi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println(WiFi.localIP());
}

/* 데이터 업데이트 확인 콜백 */
void dataCallback(const char* code, Var res) {
  if (code == "DEVICE-DATA-UPDATED") {
    double temp_data = (double)res["update"]["temp"];
    double humid_data = (double)res["update"]["humid"];
    double noise_data = (double)res["update"]["noise"];
    double air_data = (double)res["update"]["air"];
    Serial.printf("Temperature: %f Humidity: %f Noise Level: %f Air Quality: %f\n",
                  temp_data, humid_data, noise_data, air_data);
    return;
  }
  Serial.println("Failed to Update DATA");
  return;
}

/* 센서 데이터 클라우드 전송 */
void sendUpdate() {
  Var data;
  data["temp"] = temp;
  data["humid"] = humid;
  data["noise"] = noise;
  data["air"] = air;
  device.data().set("temp", temp, dataCallback);
  device.data().set("humid", humid, dataCallback);
  device.data().set("noise", noise, dataCallback);
  device.data().set("air", air, dataCallback);
}

void setup() {
  Serial.begin(9600);
  LORA.begin(115200);
  inputString.reserve(200);
  connectWiFi();
  project = grandeur.init(apiKey, token);
  device = project.device(deviceID);
  project.onConnection(onConnection);
}

void loop() {
  serialEvent();
  project.loop(WiFi.status() == WL_CONNECTED);
  if (stringComplete) {
    process_received_data();
    if (connected) sendUpdate();
  }
}

void serialEvent() {
  while (LORA.available()) {
    char inChar = (char)LORA.read();
    if (inChar == '\n') {
      stringComplete = true;
    } else {
      inputString += inChar;
    }
  }
}

주요 구현 포인트

제조공정

  1. 초소형 PM2.5 및 VOC 센서, 실시간 개인 공기질 모니터링 실현
  2. Bosch Sensortec, AI 탑재 BME688 공기질 센서로 바이러스 전파 위험 저감
  3. 르네사스, 임베디드 AI로 실내 공기질 센서 플랫폼 향상 - 냄새 감지 강화
  4. 아두이노와 파이썬으로 OpenSensors를 활용한 공기질 측정 가이드
  5. DIY 공기질 모니터: 비용 효율적인 EPA 준수 검출기
  6. 헬륨 기반 태양광 전원 공기질 센서: 설계 및 배포 가이드
  7. IoT 센서가 혁신하는 대기 오염 모니터링과 공중 보건
  8. IoT 기반 실외 공기질 모니터링: 안전, 생산성, 지속가능성 강화
  9. 산업용 IoT 대기질 모니터링: 생산성 증대·비용 절감
  10. 고급 탄소 기반 NO₂ 센서로 실내 공기 질 모니터링 향상