반응형
온습도 센서 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] = { 0, 0, 0, 0, 0 }; 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(2, 1, 1); if (gpioInitialise()<0) return 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++ == 100) break; // 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(0, 1500): #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(0, 40): 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(0, len(effectiveData)): if (len(effectiveData[i]) < ((bits_max + bits_min)/2)): effectiveData[i] = "0" else: effectiveData[i] = "1" for i in range(0, 8): HumidityBit += str(effectiveData[i]) for i in range(16, 24): TemperatureBit += str(effectiveData[i]) for i in range(32, 40): 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 |
반응형
'라즈베리파이' 카테고리의 다른 글
HC-SR04 초음파 거리센서 실습 파이선 코드와 C코드 (0) | 2019.04.02 |
---|---|
온습도 센서 DHT11 실습 python 코드 (0) | 2019.04.02 |
라즈베리파이 카메라 사용법 상세한 자료 파이선 코드 [링크] (0) | 2019.04.01 |
FSR402센서, FSR (Force Sensing Resistors) 힘 감지 센서 라즈베리파이 파이선 코드 (0) | 2019.03.27 |
라즈베리파이 BMP180 대기압 측정센서 C와 Python 코드 (0) | 2019.03.26 |