DHT11

김준혁·2026년 4월 1일
#include "DHT.h"

#define DHTPIN 2     // Digital pin connected to the DHT sensor

// Uncomment whatever type you're using!
//#define DHTTYPE DHT11   // DHT 11
#define DHTTYPE DHT11   // DHT 11  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(9600);
  Serial.println(F("DHTxx test!"));

  dht.begin();
}

void loop() {
  // Wait a few seconds between measurements.
  delay(2000);


  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);

  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print(F("°C "));
  Serial.print(f);
  Serial.print(F("°F  Heat index: "));
  Serial.print(hic);
  Serial.print(F("°C "));
  Serial.print(hif);
  Serial.println(F("°F"));
}

아두이노 우노와 연결해서 시리얼 모니터에 온/습도 측정

AVR변환 코드

#ifndef F_CPU
#define F_CPU 16000000UL // 16MHz 클럭 설정
#endif

#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include <string.h>
#include "UART0.h" //기존에 했던 헤더파일, uart통신 관련 선언이 들어있음 UART0.c와 함께 사용
// --- 설정: DHT11 연결 핀 (아두이노 D2 = PORTD 2) ---
#define DHT_PIN     PD2
#define DHT_DDR     DDRD
#define DHT_PORT    PORTD
#define DHT_PIN_REG PIND

uint8_t bits[5]; // 습도 정수, 습도 소수, 온도 정수, 온도 소수, 체크섬 저장


// [4] DHT11 데이터 수신 로직
int8_t dht11_read() {
    uint8_t j = 0, i = 0;
    memset(bits, 0, sizeof(bits));

    // 1. Start Signal
    DHT_DDR |= (1 << DHT_PIN);    // 출력 모드
    DHT_PORT &= ~(1 << DHT_PIN);  // LOW로 내림
    _delay_ms(18);                // 최소 18ms 유지
    DHT_PORT |= (1 << DHT_PIN);   // HIGH로 올림
    _delay_us(40);                // 20~40us 대기
    DHT_DDR &= ~(1 << DHT_PIN);   // 입력 모드로 전환 (Pull-up에 의해 HIGH 유지)

    // 2. Sensor Response 확인
    _delay_us(40);
    if (DHT_PIN_REG & (1 << DHT_PIN)) return -1; // Response LOW가 안 오면 에러
    _delay_us(80);
    if (!(DHT_PIN_REG & (1 << DHT_PIN))) return -1; // Response HIGH가 안 오면 에러
    _delay_us(80);

    // 3. 40비트 데이터 읽기
    for (j = 0; j < 5; j++) {
        for (i = 0; i < 8; i++) {
            while (!(DHT_PIN_REG & (1 << DHT_PIN))); // HIGH가 될 때까지 대기
            _delay_us(30); // 30us 대기 후 핀 상태 확인

            if (DHT_PIN_REG & (1 << DHT_PIN)) {
                bits[j] |= (1 << (7 - i)); // 30us 후에도 HIGH면 비트 '1'
            }
            while (DHT_PIN_REG & (1 << DHT_PIN)); // 다시 LOW가 될 때까지 대기
        }
    }

    // 4. 체크섬 확인 (바이트 0+1+2+3 == 바이트 4)
    if (bits[0] + bits[1] + bits[2] + bits[3] == bits[4]) return 0;
    return -2; // 체크섬 오류
}

int main(void) {
    char buf[64];
    UART0_init();
    UART0_print_string("--- DHT11 AVR System Start ---\r\n");

    while (1) {
        int8_t result = dht11_read();

        if (result == 0) {
            // 성공 시 출력 (정수 부분만 사용해도 DHT11은 충분합니다)
            sprintf(buf, "Hum: %d.%d%%  Temp: %d.%dC\r\n", 
                    bits[0], bits[1], bits[2], bits[3]);
            UART0_print_string(buf);
        } else if (result == -1) {
            UART0_print_string("Sensor No Response!\r\n");
        } else {
            UART0_print_string("Checksum Error!\r\n");
        }

        _delay_ms(2000); // 센서 안정화를 위해 2초 대기
    }
}

UART0.c

#include "UART0.h"


void UART0_init(void)
{
    UBRR0H = 0x00;
    UBRR0L = 207;           // 9,600 보율 설정
    UCSR0A |= _BV(U2X0);    // 2배속 모드
    UCSR0C = 0x06;          // 비동기, 8비트 데이터, 패리티 없음, 1비트 정지 비트
    UCSR0B |= _BV(RXEN0);   // 수신 가능
    UCSR0B |= _BV(TXEN0);   // 송신 가능
}

void UART0_transmit(char data)
{
    while(!(UCSR0A & (1<<UDRE0))); // 송신 대기
    UDR0 = data;
}

unsigned char UART0_receive(void)
{
    while(!(UCSR0A & (1<<RXC0))); // 수신 대기
    return UDR0;
}

void UART0_print_string(char *str)
{
    for(int i = 0; str[i]; i++)
        UART0_transmit(str[i]);
}

void UART0_print_1_byte_number(uint8_t n)
{
    char numString[4] = "0";
    int i, index = 0;
    if(n > 0) {
        for(i = 0; n != 0; i++) {
            numString[i] = n % 10 + '0';
            n = n / 10;
        }
        numString[i] = '\0';
        index = i - 1;
    }
    for(i = index; i >= 0; i--)
        UART0_transmit(numString[i]);
}

profile
임베디드

0개의 댓글