[树莓派]我是一只会发光的温度计

0

夏任务105:做一个桌面温湿度计

浙江大学计算机科学与技术学院 / 课程:嵌入式系统 / 指导教师:翁恺

用RPi采集温度、湿度和气压传感器的数据,在LCD显示

前情提要:上次用了蛋疼的热敏电阻来获得温度,这次用DHT11啦~话说木有气压传感器,所以就省略气压这步了。注意,因为之前已经安装过wiringPi的库,在本篇中不再重复。关于如何驱动LCD请参考《[树莓派]桌面时钟》

1.       连接并驱动DHT11

正确连接DHT11与树莓派,连线方法如下(此处参考了某位同学的报告~)

lt_wire

建立一个dht11.c的文件,贴入以下内容

//

//mydht11.c

//

#include <wiringPi.h>

#include <stdio.h>

#include <stdlib.h>

typedef unsigned char uint8;

typedef unsigned int  uint16;

typedef unsigned long uint32;

#define HIGH_TIME 32

int wiringPiSetup (void) ;

int pinNumber = 7;  //use gpio1 to read data

uint32 databuf;

uint8 readSensorData(void)

{

    uint8 crc;

    uint8 i;

    pinMode(pinNumber,OUTPUT); // set mode to output

    digitalWrite(pinNumber, 0); // output a high level

    delay(25);

    digitalWrite(pinNumber, 1); // output a low level

    pinMode(pinNumber, INPUT); // set mode to input

    pullUpDnControl(pinNumber,PUD_UP);

    delayMicroseconds(27);

    if(digitalRead(pinNumber)==0) //SENSOR ANS

       {

         while(!digitalRead(pinNumber)); //wait to high

      for(i=0;i<32;i++)

       {

       while(digitalRead(pinNumber)); //data clock start

       while(!digitalRead(pinNumber)); //data start

          delayMicroseconds(HIGH_TIME);

          databuf*=2;

           if(digitalRead(pinNumber)==1) //1

           {

                databuf++;

           }

        }

      for(i=0;i<8;i++)

       {

       while(digitalRead(pinNumber)); //data clock start

       while(!digitalRead(pinNumber)); //data start

          delayMicroseconds(HIGH_TIME);

          crc*=2;

          if(digitalRead(pinNumber)==1) //1

           {

                crc++;

           }

        }

    return 1;

       }

   else

        {

        return 0;

         }

}

int main (void)

{

  printf(“Use GPIO1 to read data!\n”);

  if (-1 == wiringPiSetup()) {

    printf(“Setup wiringPi failed!”);

    return 1;

  }

  pinMode(pinNumber, OUTPUT); // set mode to output

  digitalWrite(pinNumber, 1); // output a high level

  printf(“Enter OS——-\n”);

  int i;

  for(i = 0; i < 2; i++)

  {

    pinMode(pinNumber,OUTPUT); // set mode to output

    digitalWrite(pinNumber, 1); // output a high level

    delay(1000);

    if(readSensorData())

    {

       printf(“Congratulations ! Sensor data read ok!\n”);

       printf(“RH:%d.%d\n”,(databuf>>24)&0xff,(databuf>>16)&0xff);

       printf(“TMP:%d.%d\n”,(databuf>>8)&0xff,databuf&0xff);

       databuf=0;

     }

    else

     {

        printf(“Sorry! Sensor dosent ans!\n”);

       databuf=0;

      }

  }

  return 0;

}

因为DHT11相当之不靠谱,所以可以看见获取温度的时候重复了两次,尽量保证能够拿到数据。编译的时候需要注意一些额外的参数

gcc -o dht11 dht11.c -lwiringPi -lpthread -lm

运行一下应该可以看到这样的内容(第一次失败了吧,我就说这货不靠谱)

lt_dht

2.       获取温度、湿度数据并在LCD上显示

因为DHT是用C驱动的,而LCD我又是用python驱动的,所以只能辛苦python一下,让它从C程序的输出中找到温度和湿度了。

建立一个lcd_clock.py,并贴入以下内容

#!/usr/bin/python

#

# based on code from lrvick and LiquidCrystal

# lrvic – https://github.com/lrvick/raspi-hd44780/blob/master/hd44780.py

# LiquidCrystal – https://github.com/arduino/Arduino/blob/master/libraries/LiquidCrystal/LiquidCrystal.cpp

#

import subprocess

import re

import sys

from time import sleep

from datetime import datetime

class Adafruit_CharLCD:

    # commands

    LCD_CLEARDISPLAY     = 0x01

    LCD_RETURNHOME       = 0x02

    LCD_ENTRYMODESET     = 0x04

    LCD_DISPLAYCONTROL       = 0x08

    LCD_CURSORSHIFT      = 0x10

    LCD_FUNCTIONSET      = 0x20

    LCD_SETCGRAMADDR     = 0x40

    LCD_SETDDRAMADDR     = 0x80

    # flags for display entry mode

    LCD_ENTRYRIGHT       = 0x00

    LCD_ENTRYLEFT     = 0x02

    LCD_ENTRYSHIFTINCREMENT = 0x01

    LCD_ENTRYSHIFTDECREMENT = 0x00

    # flags for display on/off control

    LCD_DISPLAYON     = 0x04

    LCD_DISPLAYOFF       = 0x00

    LCD_CURSORON      = 0x02

    LCD_CURSOROFF     = 0x00

    LCD_BLINKON       = 0x01

    LCD_BLINKOFF      = 0x00

    # flags for display/cursor shift

    LCD_DISPLAYMOVE      = 0x08

    LCD_CURSORMOVE       = 0x00

    # flags for display/cursor shift

    LCD_DISPLAYMOVE      = 0x08

    LCD_CURSORMOVE       = 0x00

    LCD_MOVERIGHT     = 0x04

    LCD_MOVELEFT      = 0x00

    # flags for function set

    LCD_8BITMODE      = 0x10

    LCD_4BITMODE      = 0x00

    LCD_2LINE         = 0x08

    LCD_1LINE         = 0x00

    LCD_5x10DOTS      = 0x04

    LCD_5x8DOTS       = 0x00

    def __init__(self, pin_rs=14, pin_e=15, pins_db=[17, 18, 27, 22], GPIO = None):

    # Emulate the old behavior of using RPi.GPIO if we haven’t been given

    # an explicit GPIO interface to use

    if not GPIO:

        import RPi.GPIO as GPIO

   self.GPIO = GPIO

        self.pin_rs = pin_rs

        self.pin_e = pin_e

        self.pins_db = pins_db

        self.GPIO.setmode(GPIO.BCM)

        self.GPIO.setup(self.pin_e, GPIO.OUT)

        self.GPIO.setup(self.pin_rs, GPIO.OUT)

        for pin in self.pins_db:

            self.GPIO.setup(pin, GPIO.OUT)

    self.write4bits(0x33) # initialization

    self.write4bits(0x32) # initialization

    self.write4bits(0x28) # 2 line 5×7 matrix

    self.write4bits(0x0C) # turn cursor off 0x0E to enable cursor

    self.write4bits(0x06) # shift cursor right

    self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF

    self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS

    self.displayfunction |= self.LCD_2LINE

    “”” Initialize to default text direction (for romance languages) “””

    self.displaymode =  self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT

    self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) #  set the entry mode

        self.clear()

    def begin(self, cols, lines):

    if (lines > 1):

       self.numlines = lines

           self.displayfunction |= self.LCD_2LINE

       self.currline = 0

    def home(self):

    self.write4bits(self.LCD_RETURNHOME) # set cursor position to zero

    self.delayMicroseconds(3000) # this command takes a long time!

    def clear(self):

    self.write4bits(self.LCD_CLEARDISPLAY) # command to clear display

    self.delayMicroseconds(3000)    # 3000 microsecond sleep, clearing the display takes a long time

    def setCursor(self, col, row):

    self.row_offsets = [ 0x00, 0x40, 0x14, 0x54 ]

    if ( row > self.numlines ):

       row = self.numlines – 1 # we count rows starting w/0

    self.write4bits(self.LCD_SETDDRAMADDR | (col + self.row_offsets[row]))

    def noDisplay(self):

    “”” Turn the display off (quickly) “””

    self.displaycontrol &= ~self.LCD_DISPLAYON

    self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)

    def display(self):

    “”” Turn the display on (quickly) “””

    self.displaycontrol |= self.LCD_DISPLAYON

    self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)

    def noCursor(self):

    “”” Turns the underline cursor on/off “””

    self.displaycontrol &= ~self.LCD_CURSORON

    self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)

    def cursor(self):

    “”” Cursor On “””

    self.displaycontrol |= self.LCD_CURSORON

    self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)

    def noBlink(self):

    “”” Turn on and off the blinking cursor “””

    self.displaycontrol &= ~self.LCD_BLINKON

    self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)

    def noBlink(self):

    “”” Turn on and off the blinking cursor “””

    self.displaycontrol &= ~self.LCD_BLINKON

    self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)

    def DisplayLeft(self):

    “”” These commands scroll the display without changing the RAM “””

    self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT)

    def scrollDisplayRight(self):

    “”” These commands scroll the display without changing the RAM “””

    self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVERIGHT);

    def leftToRight(self):

    “”” This is for text that flows Left to Right “””

    self.displaymode |= self.LCD_ENTRYLEFT

    self.write4bits(self.LCD_ENTRYMODESET | self.displaymode);

    def rightToLeft(self):

    “”” This is for text that flows Right to Left “””

    self.displaymode &= ~self.LCD_ENTRYLEFT

    self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)

    def autoscroll(self):

    “”” This will ‘right justify’ text from the cursor “””

    self.displaymode |= self.LCD_ENTRYSHIFTINCREMENT

    self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)

    def noAutoscroll(self):

    “”” This will ‘left justify’ text from the cursor “””

    self.displaymode &= ~self.LCD_ENTRYSHIFTINCREMENT

    self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)

    def write4bits(self, bits, char_mode=False):

        “”” Send command to LCD “””

    self.delayMicroseconds(1000) # 1000 microsecond sleep

        bits=bin(bits)[2:].zfill(8)

        self.GPIO.output(self.pin_rs, char_mode)

        for pin in self.pins_db:

            self.GPIO.output(pin, False)

        for i in range(4):

            if bits[i] == “1”:

                self.GPIO.output(self.pins_db[::-1][i], True)

    self.pulseEnable()

        for pin in self.pins_db:

            self.GPIO.output(pin, False)

        for i in range(4,8):

            if bits[i] == “1”:

                self.GPIO.output(self.pins_db[::-1][i-4], True)

    self.pulseEnable()

    def delayMicroseconds(self, microseconds):

    seconds = microseconds / float(1000000)   # divide microseconds by 1 million for seconds

    sleep(seconds)

    def pulseEnable(self):

    self.GPIO.output(self.pin_e, False)

    self.delayMicroseconds(1)       # 1 microsecond pause – enable pulse must be > 450ns

    self.GPIO.output(self.pin_e, True)

    self.delayMicroseconds(1)       # 1 microsecond pause – enable pulse must be > 450ns

    self.GPIO.output(self.pin_e, False)

    self.delayMicroseconds(1)       # commands need > 37us to settle

    def message(self, text):

        “”” Send string to LCD. Newline wraps to second line”””

        for char in text:

            if char == ‘\n’:

                self.write4bits(0xC0) # next line

            else:

                self.write4bits(ord(char),True)

if __name__ == ‘__main__’:

    lcd = Adafruit_CharLCD()

    lcd.noBlink()

    while True:

        sleep(1)

        output = subprocess.check_output([“./dht11”]);

        #print output

        matches = re.search(“TMP:([0-9.]+)”,output)

        if (not matches):

            sleep(1)

            continue

        temp = float(matches.group(1))

        #print temp

        matches = re.search(“RH:([0-9.]+)”, output)

        if (not matches):

            sleep(1)

            continue

        humidity = float(matches.group(1))

        #print humidity

        lcd.clear()

        lcd.message(‘TMP:%s’ % ( temp ))

        lcd.message(‘ HM:%s’ % ( humidity ))

        lcd.message(datetime.now().strftime(‘\n%Y-%m-%d %H:%M:%S’))

保存并sudo执行

sudo python lcd_clock.py #需要后台运行就加个&,然后你就有了一只钟……

运行效果是这样的:

WP_20130527_005

这个实验如果在做过LCD和温度传感器的基础上做其实还是相当简单的。因为除了驱动DHT11的C程序之外,最后的lcd_clock.py和上次最后列出的那个python脚本相比,差别只是在于最后的lcdmessage里面多了一个re.search然后调整了一下输出的内容和格式。不过这次倒是确实真的学到了知识,python用来抓输出真是太方便了~然后我现在就有了一只相当好用的温度计+钟……

Acknowledgement

http://blog.csdn.net/liang890319/article/details/8739683

Comments

您的电子邮箱地址不会被公开。 必填项已用*标注