로보테크AI

융합_로보테크 AI 자율주행 로봇 개발자 과정-26/03/04

steezer 2026. 3. 4. 18:30

어제 만든 board2(온습도+조도+소리)에 미세먼지 모듈 추가해보기

ㄴ전력 부족으로 아두이노 우노 자체 전원이 안 들어옴

ㄴ현재 와이파이 모듈 전부 사용 중이라 와이파이 연결 불가능

 

/*
 * ============================================================
 *  BOARD3 — 미세먼지 전용 모듈 (GP2Y1010AU0F)
 *  Arduino Uno R3 단독 · WiFi 없음 · 시리얼 모니터 출력
 * ============================================================
 *
 *  [센서 핀 배열] — 6핀 플랫 케이블 (왼쪽→오른쪽)
 *    핀1: LED  → 150Ω 저항 → Arduino D3
 *    핀2: VCC  → Arduino 5V
 *    핀3: GND  → Arduino GND
 *    핀4: OUT  → Arduino A0
 *    핀5: VCC  → Arduino 5V  (핀2와 같은 5V)
 *    핀6: GND  → Arduino GND (핀3와 같은 GND)
 *
 *  [필수 외부 부품]
 *    - 150Ω 저항 (없으면 220Ω 대체 가능)
 *      : D3 와 센서 핀1(LED) 사이에 직렬 연결
 *      : 없으면 LED 핀 과전류로 센서 영구 손상
 *    - 220μF 전해 콘덴서
 *      : 센서 VCC(핀2) — GND(핀3) 사이에 병렬 연결
 *      : + 극을 VCC 쪽에, - 극을 GND 쪽에 연결
 *      : 없으면 측정값이 튀거나 불안정
 *
 *  [시리얼 출력 예시]
 *    ==============================
 *      BOARD3  미세먼지 센서
 *    ==============================
 *    [측정] 전압: 0.823 V  |  농도:  44.6 μg/m³  |  등급: 보통
 *    [측정] 전압: 0.761 V  |  농도:  32.2 μg/m³  |  등급: 보통
 *
 *  [등급 기준 — WHO / 환경부]
 *    좋음    :   0 ~ 30  μg/m³
 *    보통    :  31 ~ 80  μg/m³
 *    나쁨    :  81 ~ 150 μg/m³
 *    매우나쁨: 151 이상   μg/m³
 * ============================================================
 */

// ── 핀 정의 ────────────────────────────────────────────────
#define DUST_LED_PIN  3    // 센서 내부 LED 제어 핀 (디지털 출력)
#define DUST_OUT_PIN  A1   // 센서 아날로그 전압 출력 핀

// ── 타이밍 상수 (데이터시트 필수 준수, 단위: 마이크로초 μs) ──
//  ┌── LED ON ──────────────────┐
//  │  280μs 후 ADC 읽기         │
//  │  40μs 더 기다린 후 LED OFF  │
//  └─────────────────────────── ┘
//  그 후 9680μs 대기 → 총 1주기 = 10ms
const int SAMPLING_TIME = 280;   // LED ON 후 이 시간(μs) 뒤에 ADC 읽기
const int DELTA_TIME    =  40;   // ADC 읽은 후 추가 대기 (μs)
const int SLEEP_TIME    = 9680;  // LED OFF 후 다음 사이클까지 대기 (μs)

// ── 보정 상수 ──────────────────────────────────────────────
// 먼지가 전혀 없을 때 센서 출력 전압 (약 0.6V, 환경마다 다를 수 있음)
const float V_NO_DUST = 0.6;
// 전압 → 농도 변환 기울기: 0.5V 증가 = 100 μg/m³ 증가
const float K_FACTOR  = 0.5;

// ── 측정 평균 횟수 ─────────────────────────────────────────
// 한 번에 N회 읽어서 평균 → 노이즈(잡음) 줄이기
const int SAMPLE_COUNT = 5;

// ── 출력 주기 ──────────────────────────────────────────────
const unsigned long PRINT_INTERVAL = 1000; // 1000ms = 1초마다 출력
unsigned long lastPrintMs = 0;

// ── 함수 선언 ──────────────────────────────────────────────
float       readDustVoltage();           // 센서에서 전압 읽기 (평균)
float       voltToDensity(float v);      // 전압 → μg/m³ 변환
const char* getDustLevel(float density); // 농도 → 등급 문자열
void        printResult(float v, float d); // 시리얼 출력

// ══════════════════════════════════════════════════════════
void setup() {
  Serial.begin(9600);

  // LED 제어 핀: 출력 모드, 초기값 HIGH (Active LOW → HIGH = LED 꺼짐)
  pinMode(DUST_LED_PIN, OUTPUT);
  digitalWrite(DUST_LED_PIN, HIGH);

  Serial.println(F("=============================="));
  Serial.println(F("   BOARD3  미세먼지 센서      "));
  Serial.println(F("   GP2Y1010AU0F  Serial Only  "));
  Serial.println(F("=============================="));
  Serial.println(F("단위: μg/m³ | 보드레이트: 9600"));
  Serial.println(F("------------------------------"));

  delay(2000); // 센서 전원 안정화 대기 (2초)
  Serial.println(F("[준비] 측정 시작!\n"));
}

// ══════════════════════════════════════════════════════════
// void loop() {
//   unsigned long now = millis();
//   // 1초마다 측정 및 출력
//   if (now - lastPrintMs < PRINT_INTERVAL) return;
//   lastPrintMs = now;

//   float voltage = readDustVoltage();      // 전압 읽기
//   float density = voltToDensity(voltage); // μg/m³ 변환

//   printResult(voltage, density);          // 시리얼 출력
// }

void loop() {
  int raw = analogRead(DUST_OUT_PIN);
  float v = raw * (5.0 / 1023.0);
  Serial.print("RAW: "); Serial.print(raw);
  Serial.print("  V: "); Serial.println(v, 3);
  delay(500);
}

// ══════════════════════════════════════════════════════════
//  센서 전압 읽기
//  - LED를 규정 타이밍대로 켜고 ADC 값을 읽음
//  - SAMPLE_COUNT 회 반복 후 평균 전압 반환
// ══════════════════════════════════════════════════════════
float readDustVoltage() {
  long adcSum = 0;

  for (int i = 0; i < SAMPLE_COUNT; i++) {

    // ① LED 켜기 (Active LOW: LOW 신호 = LED ON)
    digitalWrite(DUST_LED_PIN, LOW);
    delayMicroseconds(SAMPLING_TIME); // 280μs 대기

    // ② 아날로그 값 읽기 (0 ~ 1023)
    adcSum += analogRead(DUST_OUT_PIN);

    // ③ LED ON 구간 나머지 채우기
    delayMicroseconds(DELTA_TIME);    // 40μs 추가 대기

    // ④ LED 끄기
    digitalWrite(DUST_LED_PIN, HIGH);

    // ⑤ 다음 사이클까지 대기
    delayMicroseconds(SLEEP_TIME);    // 9680μs 대기
  }

  // ADC 평균 → 전압 변환
  // Arduino Uno: 10비트 ADC (0~1023), 기준전압 5V
  float adcAvg = (float)adcSum / SAMPLE_COUNT;
  float voltage = adcAvg * (5.0f / 1023.0f);

  return voltage;
}

// ══════════════════════════════════════════════════════════
//  전압 → 먼지 농도 변환 (선형 근사)
//  density(μg/m³) = (V - V_no_dust) / K_FACTOR * 100
//  음수 결과는 0으로 처리 (공기가 매우 깨끗한 상태)
// ══════════════════════════════════════════════════════════
float voltToDensity(float v) {
  float density = (v - V_NO_DUST) / K_FACTOR * 100.0f;
  return (density < 0.0f) ? 0.0f : density;
}

// ══════════════════════════════════════════════════════════
//  농도 → 등급 문자열
// ══════════════════════════════════════════════════════════
const char* getDustLevel(float density) {
  if (density <= 30.0f)  return "좋음    ";
  if (density <= 80.0f)  return "보통    ";
  if (density <= 150.0f) return "나쁨    ";
  return                        "매우나쁨";
}

// ══════════════════════════════════════════════════════════
//  시리얼 모니터 출력
//  형식: B3, V:0.823, D:44.6, LV:보통
// ══════════════════════════════════════════════════════════
void printResult(float v, float d) {
  // 한 줄 포맷 출력 (나중에 Python으로 파싱하기 쉬운 형식)
  Serial.print(F("B3,V:"));
  Serial.print(v, 3);           // 전압 (소수점 3자리)
  Serial.print(F(",D:"));
  Serial.print(d, 1);           // 농도 (소수점 1자리)
  Serial.print(F(",LV:"));
  Serial.println(getDustLevel(d)); // 등급
}

미세먼지 모듈 고장

 

GUI -> LCD 모니터 차체에 표시