樹莓派使用DHT11溫溼度傳感器

1、相關介紹
html

DHT11介紹:
java

DHT11是一款比較便宜的溫溼度傳感器模塊。讀取數據只須要佔用一個IO口。可以同時測量溫度和相對溼度。git

DHT11的數據手冊能夠看這裏:http://wenku.baidu.com/view/1955cc70a417866fb84a8e7b.htmlshell

須要注意的是,文檔中寫明一句話:小數部分用於擴展,現只能讀出0。因此小數部分目前永遠是0!
編程


樹莓派IO口介紹ubuntu

我使用的是B版樹莓派,接口以下圖。其中的NAME一列是樹莓派實際的IO口功能。PIN#一列是後面要介紹的wiringpi和pi4j庫文件編程使用的接口編號。api


wiringpi介紹ui

wiringpi是經過C語言控制樹莓派GPIO口的頭文件。在C語言中包含這個頭文件以後能夠很簡單的調用已經封裝好的方法來控制樹莓派GPIO口。程序須要先安裝。this

wiringpi官網:http://wiringpi.com/spa

wiringpi下載和安裝:http://wiringpi.com/download-and-install/

wiringpi文檔:http://wiringpi.com/reference/

編譯和運行:

寫好C文件後,經過以下命令進行編譯:

gcc -Wall -o executefilename cfilename.c -lwiringPi

gcc是編譯器,-Wall是在編譯時顯示警告信息,-o executefilename cfilename.c是將cfilename.c文件編譯成文件名爲executefilename的可執行文件,-lwiringPi是將wiringPi頭文件包含在可執行文件中。

編譯完以後會生成文件名爲executefilename的文件,使用root權限執行以下命令便可運行:

sudo ./executefilename


pi4j介紹

pi4j是基於wiringpi開發的經過java來控制樹莓派GPIO口的庫文件。在java程序中引入相關類就可使用已經封裝好的方法控制樹莓派GPIO口。

pi4j官網:http://pi4j.com/

pi4j下載:http://pi4j.com/download.html

pi4j安裝:http://pi4j.com/install.html

pi4j文檔:http://pi4j.com/apidocs/index.html

編譯和運行:

使用了pi4j後,編譯.java文件和運行.class文件時,須要使用root權限。例如:

編譯:

sudo javac -classpath .:classes:/opt/pi4j/lib/'*' YourJavaFile.java

運行:

sudo java -classpath .:classes:/opt/pi4j/lib/'*' YourClassFile.class

若是使用sudo編譯和運行時提示找不到javac和java,這是因爲root用戶沒有加載環境變量,因此找不到java的執行命令。可使用以下命令切換到帶有環境變量的root用戶後,再執行編譯和運行:

sudo su - root


2、硬件鏈接

因爲本人較懶,並且目前是新手狀態使用ubuntu,不知道用什麼軟件來作圖,因此用文字簡單描述一下硬件的鏈接。

DHT11引腳有格子空的爲正面,引腳朝下,從左數4個引腳分別爲

DHT11引腳名稱
DHT11引腳功能
鏈接到樹莓派的GPIO
1.VCC
正極,鏈接3.3V或5V
物理接口1,即3.3V
2.DATA
數據輸入輸出
物理接口7,即GPIO 7
3.NC
懸空(就是不連任何地方)
不連
4.GND
負極
物理接口 6,即GND

此外按照DHT11數據手冊要求,我在DATA和VCC之間鏈接了一個4.7K歐姆的電阻,起到上拉做用。


3、軟件編寫

使用wiringpi編寫C程序:

以下程序借鑑了網上一老外的程序,忘了原帖地址在哪。

#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define MAX_TIME 85
#define DHT11PIN 7
#define ATTEMPTS 5                 //retry 5 times when no response
int dht11_val[5]={0,0,0,0,0};
 
int dht11_read_val(){
    uint8_t lststate=HIGH;         //last state
    uint8_t counter=0;
    uint8_t j=0,i;
    for(i=0;i<5;i++)
        dht11_val[i]=0;
        
    //host send start signal    
    pinMode(DHT11PIN,OUTPUT);      //set pin to output 
    digitalWrite(DHT11PIN,LOW);    //set to low at least 18ms 
    delay(18);
    digitalWrite(DHT11PIN,HIGH);   //set to high 20-40us
    delayMicroseconds(40);
    
    //start recieve dht response
    pinMode(DHT11PIN,INPUT);       //set pin to input
    for(i=0;i<MAX_TIME;i++)         
    {
        counter=0;
        while(digitalRead(DHT11PIN)==lststate){     //read pin state to see if dht responsed. if dht always high for 255 + 1 times, break this while circle
            counter++;
            delayMicroseconds(1);
            if(counter==255)
                break;
        }
        lststate=digitalRead(DHT11PIN);             //read current state and store as last state. 
        if(counter==255)                            //if dht always high for 255 + 1 times, break this for circle
            break;
        // top 3 transistions are ignored, maybe aim to wait for dht finish response signal
        if((i>=4)&&(i%2==0)){
            dht11_val[j/8]<<=1;                     //write 1 bit to 0 by moving left (auto add 0)
            if(counter>16)                          //long mean 1
                dht11_val[j/8]|=1;                  //write 1 bit to 1 
            j++;
        }
    }
    // verify checksum and print the verified data
    if((j>=40)&&(dht11_val[4]==((dht11_val[0]+dht11_val[1]+dht11_val[2]+dht11_val[3])& 0xFF))){
        printf("RH:%d,TEMP:%d\n",dht11_val[0],dht11_val[2]);
        return 1;
    }
    else
        return 0;
}
 
int main(void){
    int attempts=ATTEMPTS;
    if(wiringPiSetup()==-1)
        exit(1);
    while(attempts){                        //you have 5 times to retry
        int success = dht11_read_val();     //get result including printing out
        if (success) {                      //if get result, quit program; if not, retry 5 times then quit
            break;
        }
        attempts--;
        delay(2500);
    }
    return 0;
}
上述程序保存爲.c文件後編譯成可執行文件,運行後會在屏幕打印溫度和溼度。


程序中的數據接收處理部分細節以下:

        if((i>=4)&&(i%2==0)){         //前3次分別是:1低電平,2高電平(即響應信號),3低電平(即數據第一個低電平)
                                      //i%2==0 是由於每次都是循環讀取低電平和高電平,每次要循環2次纔讀出一個bit處理
            dht11_val[j/8]<<=1;       //讀到後,j/8能夠限制一個數的8個位,左移1位自動補0,至關於讀出0
            if(counter>16)            //counter計數若是超過16,則高電平長,應讀1.
                dht11_val[j/8]|=1;    //故再將上面數與1位或,使最後一位變成1 
            j++;                      //j++8個換成下一個數據
        }
if((j>=40)&&(dht11_val[4]==((dht11_val[0]+dht11_val[1]+dht11_val[2]+dht11_val[3])& 0xFF))){

//這其中(dht11_val[0]+dht11_val[1]+dht11_val[2]+dht11_val[3])& 0xFF)是將5個數相加,和1與。
//目的是防止讀出數據都爲0,和爲0,0和1與後得0,因此if判斷條件不成立,返回讀取失敗碼。
//若是讀出數據是不爲0的正常數據,和1與後還得原數。



使用pi4j編寫java程序:

在使用pi4j編寫DHT11要求的時序時,始終收不到DHT11迴應信號,我的感受是java達不到DHT11要求的微秒級時序,因此java程序沒有成功。若是有哪位大神成功用java寫出DHT11程序,但願能賜教一下。

相關文章
相關標籤/搜索