본문 바로가기

라즈베리파이

온습도 센서 DHT11 - 비동기 방식으로 값을 얻는 C코드

반응형

온습도 센서 DHT11 - 비동기 방식으로 값을 얻는 C코드

온습도 센서 dht11 이나 dht22 에 대한 자료는 검색하여 참고하고 여기는 소스코드만 옮긴다.   

아래 연결도는 dht22 로 그려놓고, 설명은 dht11 로 하니 좀 혼동된다. 정리가 필요하다.

아래 코드는 pigpio 라이브러리를 이용해 비동기 방식으로 DHT11 센서를 제어하는 C언어 코드이다. 결과는 정확한 값을 에러없이 출력한다. 빌드는 아래 첨부한 메이크 파일을 같은 폴더에 카피하여 $make 실행한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
 *  dht11.c:
 *    Simple test program to test the wiringPi functions
 *    DHT11 test
 */
 
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/resource.h>
#include <errno.h>
#include <stdbool.h>
#include <signal.h>
#include <pigpio.h>
 
#define MAXTIMINGS    85
#define DHTPIN        4
#define HIGH_LOW        8
#define HIGH        1
#define LOW        0
int dht11_dat[5= { 00000 };
int phase = 0;
 
 
void my_ctrl_c_handler(int sig){ // can be called asynchronously
    gpioTerminate();
    exit(0);
}
 
/*
0 : 1 -> 0 (start signal 보냄)
1 : 0 -> 1 (low : 18ms -> high)
2 : 1 -> 0 (high: 40us -> low)
3 : 0 -> 1 (low : 80us -> high by DHT)
4 : 1 -> 0 (high :80us -> low by DHT) 
5 : 0 -> 1 (low : 50us -> high by DHT : bit data comming soon) 
6 : 1 -> 0 (high : 20us ~ 70us  -> low by DHT : bit data) 
.............
*/
void myInterrupt (int gpio, int level, uint32_t tick)
{
    static int i;
    static uint32_t prev, gap;
    gap = tick - prev;
 
//    printf("%d: gpio %d became %d at %d, %d\n", phase, gpio, level, gap);
 
    if((phase >= 6&& (phase <= 84&& !(phase % 2)){    //6,8,10... 84, ... 0,2,4...78, 0,1,2, ...39 
        i = (phase - 6/ 2;
        dht11_dat[i / 8<<= 1;
        if ( gap > 50 )
                dht11_dat[i / 8|= 1;
    }
    if(phase == 84){    //마지막 데이터 .Pull up시켜줘야 함
        gpioSetMode(DHTPIN, PI_OUTPUT);
        gpioWrite(DHTPIN, HIGH);
    }
    phase++;
    prev = tick;
}
 
unsigned long read_dht11_dat()
{
    dht11_dat[0= dht11_dat[1= dht11_dat[2= dht11_dat[3= dht11_dat[4= 0;
 
    gpioSetMode(DHTPIN, PI_OUTPUT);
    gpioWrite(DHTPIN, LOW);
    gpioDelay(18 * 1000);
    gpioWrite(DHTPIN, HIGH);
    gpioSetMode(DHTPIN, PI_INPUT);
    gpioDelay(40);
 
 
    return 0;
}
 
int main( void )
{
    unsigned long ret;
    int loop = 0, i;
    float f;
    printf"Raspberry Pi pigpio DHT11 Temperature test program\n" );
 
    setpriority(PRIO_PROCESS, 0-20);    
    gpioCfgClock(211);
    if (gpioInitialise()<0return 1;
    gpioSetSignalFunc(SIGINT, my_ctrl_c_handler);    //Ctrl + C Handler
//    gpioSetAlertFunc(DHTPIN, NULL);
    gpioSetMode(DHTPIN, PI_OUTPUT);
    gpioWrite(DHTPIN, HIGH);
    gpioDelay(1000 * 1000);
 
    i = gpioSetAlertFunc(DHTPIN, myInterrupt);
    while ( 1 )
    {
        phase = 0;
        ret = read_dht11_dat();
        gpioSleep(PI_TIME_RELATIVE,  0,  10000); /* wait 1sec to refresh */
        if(86 != phase){
            printf"Read Error[%d]\n", phase );
        }
        else{
            if(dht11_dat[4== (dht11_dat[0+ dht11_dat[1+ dht11_dat[2+ dht11_dat[3]) & 0xFF){
                f = (float)dht11_dat[2* 9. / 5. + 32;
                printf"Humidity = %d.%d %% Temperature = %d.%d *C (%.1f *F)\n"
                        dht11_dat[0], dht11_dat[1], dht11_dat[2], dht11_dat[3], f );
            }
            else{
                printf"CRC Error\n" );
            }
        }        
        gpioSleep(PI_TIME_RELATIVE,  2,  0); /* wait 1sec to refresh */
        if(loop++ == 100break;
//        break;
 
    }
 
    return(0);
}
 
cs

아래는 파이선 소스코드.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#!/usr/bin/env python
#-*- coding: utf-8 -*-
# original source from : https://github.com/netikras/r-pi_DHT11
 
import RPi.GPIO as GPIO
import time, sys
 
data = []
effectiveData = []
bits_min=999
bits_max=0
HumidityBit = ""
TemperatureBit = ""
crcBit = ""
crc_OK = False
Humidity = 0
Temperature = 0
crc = 0
pin=4
 
def bin2dec(string_num):
  return int(string_num, 2)
 
def pullData():
  global data, effectiveData, pin
 
  data = []
  effectiveData = []
 
  GPIO.setup(pin,GPIO.OUT)
  GPIO.output(pin,GPIO.HIGH)
  time.sleep(0.025)
  GPIO.output(pin,GPIO.LOW)
  time.sleep(0.14)
  GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
 
  start = time.time()
  for i in range(01500):  #1000 ->1500으로 늘림
    data.append(GPIO.input(pin))
  end = time.time()
  #print 'gap', (end - start) * 1000000 # 이 시간이 4000을 넘어야 한다.
 
 
def analyzeData():
  seek=0
  bits_min=9999
  bits_max=0
 
  global HumidityBit, TemperatureBit, crcBit, crc, Humidity, Temperature
 
  HumidityBit = ""
  TemperatureBit = ""
  crcBit = ""
  index = 0
 
  # 데이터를 보내기전의 첫번째 펄스는 넘어간다.
  while(seek < len(data) and data[seek] == 0):
    seek+=1
  while(seek < len(data) and data[seek] == 1):
    seek+=1
 
  #High 비트 40개를 모두 저장한다.
  for i in range(040):
    index = 0
    buffer = ""
 
    while(seek < len(data) and data[seek] == 0):
      seek+=1
      index += 1
 
    while(seek < len(data) and data[seek] == 1):
      seek+=1
      buffer += "1"
 
    #40개의 값 중에서 가장 긴 것과 가장 짧은 것을 계산한다.
    if (len(buffer) < bits_min):
      bits_min = len(buffer)
 
    if (len(buffer) > bits_max):
      bits_max = len(buffer)
 
    effectiveData.append(buffer)
    #print "%s " % buffer
 
  # ((bits_max + bits_min)/2)을 기준으로 LOW, HIGH 를 정한다.
  for i in range(0len(effectiveData)):
    if (len(effectiveData[i]) < ((bits_max + bits_min)/2)):
      effectiveData[i] = "0"
    else:
      effectiveData[i] = "1"
 
  for i in range(08):
    HumidityBit += str(effectiveData[i])
 
  for i in range(1624):
    TemperatureBit += str(effectiveData[i])
 
  for i in range(3240):
    crcBit += str(effectiveData[i])
 
  Humidity = bin2dec(HumidityBit)
  Temperature = bin2dec(TemperatureBit)
  crc = bin2dec(crcBit)
  #print "HumidityBit=%s, TemperatureBit=%s, crc=%s" % (HumidityBit, TemperatureBit, crc)
 
def isDataValid():
  global Humidity, Temperature, crc
  if ((Humidity + Temperature) == crc):
      return True
  else:
      return False
 
def printData():
  f = Temperature * 9. / 5. + 32
  print "Humidity = %d.%d %% Temperature = %d.%d *C (%.1f *F)"%( Humidity, 0, Temperature, 0, f)
 
GPIO.setmode(GPIO.BCM)
try:
  while (True):
    pullData()
    analyzeData()
    if (isDataValid()):
      printData()
    else:
      print 'CRC Error'
    time.sleep(4)
except:
  print 'Now Exit'
 
cs


반응형