아두이노

온습도 센서(D11) openCR 에러

haniru 2026. 4. 9. 01:45

온습도 센서를 openCR에서 라즈베리로 보내주면 계속 에러가 났다

 

처음에는 온습도가 문제인지도 모르고 코드랑 주소만 바꿨다

 

IDLE을 쓰면 해결된다 했는데, There is no status packet! 에러가 늦게 뜰 뿐 여전히 에러가 남

 

비차단(Non-blocking) 방식의 핵심은 **"데이터가 올 때까지 CPU가 delay()하며 기다리지 않고, 다른 일을 하다가 데이터가 준비되면 낚아채는 것"**입니다.

사용자님의 환경(OpenCR + DHT11)에 맞춰서 DHT_NonBlocking 라이브러리를 사용하는 방식과 이를 상태 머신으로 관리하는 통합 코드를 짜드릴게요.


1. 사전 준비 (라이브러리 설치)

아두이노 IDE의 **라이브러리 관리자(Ctrl+Shift+I)**에서 DHT_NonBlocking (작성자: Ole Wolf)을 검색해서 설치하세요.


2. Turtlebot3Sensor.h (헤더 파일 수정)

기존 DHT 포인터를 새로운 라이브러리 클래스로 교체해야 합니다.

C++
 
// turtlebot3_sensor.h 내부
#include <dht_nonblocking.h> // 라이브러리 변경

class Turtlebot3Sensor {
private:
  DHT_NonBlocking *p_dht; // 클래스명 변경
  int dht_pin_;

public:
  void initDHT(void);
  bool readDHT(float &temp, float &humi); // 이제 한 번에 온습도를 읽는 방식으로 변경
};

3. Turtlebot3Sensor.cpp (함수 구현 수정)

readDHT 함수는 데이터가 준비되었을 때만 true를 반환하도록 설계합니다.

C++
 
// turtlebot3_sensor.cpp

void Turtlebot3Sensor::initDHT(void) {
  dht_pin_ = 4; 
  p_dht = new DHT_NonBlocking(dht_pin_, DHT_TYPE_11); // DHT11 지정
}

// 비차단 방식으로 온습도를 읽는 함수
bool Turtlebot3Sensor::readDHT(float &temp, float &humi) {
  // measure 함수는 내부적으로 타이머를 체크하여 
  // 데이터 읽기가 완료된 순간에만 true를 리턴합니다. (내부 delay 없음)
  if (p_dht->measure(&temp, &humi)) {
    return true; 
  }
  return false;
}

4. turtlebot3.cpp (상태 머신 적용)

가장 중요한 부분입니다. update_analog_sensors에서 "데이터가 준비됐을 때만" 제어표(Control Table)를 갱신합니다.

C++
 
void update_analog_sensors(uint32_t interval_ms)
{
  static uint32_t pre_time = 0;
  
  // [Part 1] 빠른 센서 (가스, 불꽃 등 - 30ms 주기)
  if(millis() - pre_time >= interval_ms){
    pre_time = millis();
    // (기존 가스, 불꽃 센서 로직 유지)
    control_items.flame_digital_status = (analogRead(A2) <= 300) ? 1 : 0;
    control_items.gas_digital_status = (digitalRead(12) == LOW) ? 1 : 0;
  }

  // [Part 2] 비차단 온습도 업데이트 (상태 머신)
  float temp, humi;
  // readDHT는 내부 타이머에 따라 약 2~4초마다 한 번씩만 true를 반환합니다.
  // 그 외의 시간에는 0.001초도 멈추지 않고 바로 false를 뱉고 지나갑니다.
  if (sensors.readDHT(temp, humi)) {
    // 데이터가 준비된 찰나에만 값을 업데이트합니다.
    control_items.dht_temp = (int32_t)(temp * 100.0f);
    control_items.dht_humi = (int32_t)(humi * 100.0f);

    // 디버깅용 로그 (필요할 때만 확인)
    // DEBUG_PRINT("[DHT Success] T: "); DEBUG_PRINT(temp);
    // DEBUG_PRINT(" H: "); DEBUG_PRINTLN(humi);
  }
  
  // 이 함수가 종료되면 즉시 dxl_slave.processPacket()이 실행될 수 있으므로
  // 다이나믹셀 통신이 끊기지 않습니다.
}

💡 이 코드의 작동 원리 (왜 안 멈추나?)

  1. 기존 방식: readTemperature() 호출 → 데이터 올 때까지 CPU가 멍하니 기다림(Blocking) → 라즈베리파이가 부르는데 대답 못 함 → 에러 발생
  2. 비차단 방식: readDHT() 호출 → "아직 시간 안 됐네?" 또는 "읽는 중이야" 하고 바로 리턴 → 메인 루프 돌면서 dxl_slave.processPacket() 실행 → 라즈베리파이와 사이좋게 대화 → 통신 유지

이렇게 수정하면 온습도 센서 때문에 전체 시스템이 기절하는 현상을 완벽하게 막을 수 있습니다.

지금 바로 DHT_NonBlocking 라이브러리를 설치하고 코드를 적용해 보시겠어요? 설치 중에 막히는 부분이 있으면 바로 말씀해 주세요!

'아두이노' 카테고리의 다른 글

아두이노 - 도트 매트릭스  (0) 2026.03.29
아두이노 millis  (0) 2026.03.29
아두이노 - 7세그먼트  (0) 2026.03.26
아두이노 - 서보모터, 초음파  (0) 2026.03.23
아두이노 - Timer (빛, 부저)  (0) 2026.03.23