Python通过GPIO读取DHT11温湿度传感器,并存入H2数据库

从事IOT行业,难免需要与硬件打交道;

今天正好领导要求,让我使用树莓派通过GPIO从DHT11温湿度传感器上采集温湿度信息,并将温湿度信息存到一个指定的H2DB中;

一、学习本章节的基础

  • 首先,你得懂python,至少得能看懂我的代码,知道如何使用pip安装依赖包;

  • 其次,你得懂树莓派,树莓派其实就是一个简单的Linux系统(ubuntu);

  • 再然后,你得懂GPIO,知道如何去接线,知道哪些针应该连到哪个触角上;

  • 最后,你还得懂H2DB,这个数据库虽然不难,有点类似于mysql,但毕竟工作中用的少!


二、直接上手开干

1、了解DHT11温湿度传感的线路图:

可以参考本篇文章:https://blog.csdn.net/weixin_54039182/article/details/124854207

1669195332595752.png

2、了解GPIO的引脚对应表:

1669195542634582.png

其中土黄色圈出来的引脚,是我选择使用的引脚!

3、编写python脚本(包含DHT11的读取和数据库写入的逻辑):

import RPi.GPIO as GPIO
import jaydebeapi
import time

DHTPIN = 17

GPIO.setmode(GPIO.BCM)

MAX_UNCHANGE_COUNT = 100

STATE_INIT_PULL_DOWN = 1
STATE_INIT_PULL_UP = 2
STATE_DATA_FIRST_PULL_DOWN = 3
STATE_DATA_PULL_UP = 4
STATE_DATA_PULL_DOWN = 5

def read_dht11_dat():
   GPIO.setup(DHTPIN, GPIO.OUT)
   GPIO.output(DHTPIN, GPIO.HIGH)
   time.sleep(0.05)
   GPIO.output(DHTPIN, GPIO.LOW)
   time.sleep(0.02)
   GPIO.setup(DHTPIN, GPIO.IN, GPIO.PUD_UP)

   unchanged_count = 0
   last = -1
   data = []
   while True:
      current = GPIO.input(DHTPIN)
      data.append(current)
      if last != current:
         unchanged_count = 0
         last = current
      else:
         unchanged_count += 1
         if unchanged_count > MAX_UNCHANGE_COUNT:
            break

   state = STATE_INIT_PULL_DOWN

   lengths = []
   current_length = 0

   for current in data:
      current_length += 1

      if state == STATE_INIT_PULL_DOWN:
         if current == GPIO.LOW:
            state = STATE_INIT_PULL_UP
         else:
            continue
      if state == STATE_INIT_PULL_UP:
         if current == GPIO.HIGH:
            state = STATE_DATA_FIRST_PULL_DOWN
         else:
            continue
      if state == STATE_DATA_FIRST_PULL_DOWN:
         if current == GPIO.LOW:
            state = STATE_DATA_PULL_UP
         else:
            continue
      if state == STATE_DATA_PULL_UP:
         if current == GPIO.HIGH:
            current_length = 0
            state = STATE_DATA_PULL_DOWN
         else:
            continue
      if state == STATE_DATA_PULL_DOWN:
         if current == GPIO.LOW:
            lengths.append(current_length)
            state = STATE_DATA_PULL_UP
         else:
            continue
   if len(lengths) != 40:
      return False

   shortest_pull_up = min(lengths)
   longest_pull_up = max(lengths)
   halfway = (longest_pull_up + shortest_pull_up) / 2
   bits = []
   the_bytes = []
   byte = 0

   for length in lengths:
      bit = 0
      if length > halfway:
         bit = 1
      bits.append(bit)
   for i in range(0, len(bits)):
      byte = byte << 1
      if (bits[i]):
         byte = byte | 1
      else:
         byte = byte | 0
      if ((i + 1) % 8 == 0):
         the_bytes.append(byte)
         byte = 0
   checksum = (the_bytes[0] + the_bytes[1] + the_bytes[2] + the_bytes[3]) & 0xFF
   if the_bytes[4] != checksum:
      return False

   return the_bytes[0], the_bytes[2]

def main():
   print("启动从GPIO获取温湿度信息,并写入h2db的程序")
   driver = 'org.h2.Driver'
   url = 'jdbc:h2:tcp://172.16.10.213:9123/mem:kuradb;DB_CLOSE_DELAY=-1'
   username = 'sa'
   password = ''
   originSql = 'insert into telemetry(temperature, humidity) values(%.2f, %.2f)'
   jar = '/jiguiquan/h2-1.4.200.jar'
   conn = jaydebeapi.connect(driver, url, [username, password], jar)
   curs = conn.cursor()

   try:
      while True:
         result = read_dht11_dat()
         if result:
            humidity, temperature = result
            insertSql = originSql % (temperature, humidity / float(100))
            curs.execute(insertSql)
            if curs.rowcount > 0:
               print("本轮插入h2db成功,温度为:%.2f,湿度为:%.2f" % (temperature, humidity / float(100)))
            else:
               print("本轮插入h2db失败,温度为:%.2f,湿度为:%.2f" % (temperature, humidity / float(100)))
         time.sleep(1)
   finally:
      curs.close()
      conn.close()

def destroy():
   GPIO.cleanup()

if __name__ == '__main__':
   try:
      main()
   except KeyboardInterrupt:
      destroy()

4、要想运行的上面的python程序,需要我们安装一些依赖:

# 检查一下环境
root@raspberrypi:~# python -V
Python 3.9.2
root@raspberrypi:~# pip -V
pip 20.3.4 from /usr/lib/python3/dist-packages/pip (python 3.9)

## 安装RPi.GPIO
root@raspberrypi:~# pip install RPi.GPIO

## 安装jaydebeapi
root@raspberrypi:~# pip install jaydebeapi

5、由于使用的jdbc连接h2db,所以还需要使用到连接h2的jar包:

root@raspberrypi:/jiguiquan# pwd
/jiguiquan
root@raspberrypi:/jiguiquan# ls
h2-1.4.200.jar	jiguiquan.py

6、在h2db数据库中创建我们需要的telemetry表:

CREATE TABLE telemetry(id INTEGER AUTO_INCREMENT PRIMARY KEY, temperature DOUBLE, humidity DOUBLE, ts timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP);

7、nohup运行jiguiquan.py,并查看日志:

nohup python -u jiguiquan.py > jiguiquan.log 2>&1 &
# 因为python的输出有缓冲,导致nohup.out并不能够马上看到输出,所以我们可以通过 -u关闭python缓冲!

## 查看nohup日志:
root@raspberrypi:/jiguiquan# tail -f -n 50 jiguiquan.log 
启动从GPIO获取温湿度信息,并写入h2db的程序
本轮插入h2db成功,温度为:25.00,湿度为:0.46
本轮插入h2db成功,温度为:25.00,湿度为:0.46
本轮插入h2db成功,温度为:25.00,湿度为:0.46

8、我们去h2db数据库看看,数据是否写入成功:image.png

有些时候,我们为了节约h2db的存储空间,还可以使用update代替insert!

update telemetry set temperature= %.2f, humidity = %.2f, ts = CURRENT_TIMESTAMP where id =1;

jiguiquan@163.com

文章作者信息...

留下你的评论

*评论支持代码高亮<pre class="prettyprint linenums">代码</pre>

相关推荐