项目场景:
随着项目的越做越多,每次笔者新做一个项目都需要买很多传感器模块,将原来写过的代码又重新学一遍,模块又要重新安装,遇到问题还得再次查找各种各样的资料,造成了时间成本的极大浪费。针对此类问题,笔者主要讲解树莓派传感器模块Sense HAT (B)的使用(多传感器集合 通过一个.py文件运行),方便将传感器数据一次性采集。
模块样式:
该模块为Sense HAT (B),集成了陀螺仪、磁力计、气压计、温湿度传感器、I2C接口以及4通道12位精度ADC,非常契合项目中环境信息采集的需求。笔者已经在很多项目都用到这个模块,主要是因为ADC采样很给力,其他的ADC采样模块组装都十分的复杂,而且价格也跟这个差不多。
https://www.waveshare.net/wiki/Sense_HAT_(B)
链接里面也有相应模块的代码资料,与模块代码的使用步骤。本博客主要介绍如何将这些模块代码拼合到一个.py文件中运行。
安装python库:
关于树莓派环境的搭建请看笔者的博客(树莓派4B环境搭建+电脑远程连接+打开文件管理闪退(上))即可。
(1)接下来是对该模块需要的库进行配置:
sudo apt-get install python-pip
sudo pip install RPi.GPIO
sudo pip install spidev
sudo apt-get install python-imaging
sudo apt-get install python-smbus
(2)开启I2C接口:
sudo raspi-config
代码特性:
这个模块提供的python代码都是已经类化的,都可以将(if name == ‘main’:)以下的代码注释掉后,在其他的py文件中引用。如果模块提供的代码不是类化的,可以参考本博主写的树莓派读取DHT11温湿度传感器并将其转化为类
以LPS22HB.py为例:
如上图所示,为大气压传感器模块代码。我们可以注释后将py文件的名字改为LPS(绝对不能和类的名字LPS22HB一样),并在同一文件目录中创建main.py文件,如下图所示:
main.py文件代码:
# coding=UTF-8
from LPS import LPS22HB,LPS_STATUS,LPS_PRESS_OUT_XL,LPS_PRESS_OUT_L,LPS_PRESS_OUT_H
import time
import math
def SendVideo():
PRESS_DATA = 0.0
u8Buf=[0,0,0]
lps22hb=LPS22HB()
while True:
time.sleep(0.1)
lps22hb.LPS22HB_START_ONESHOT()
if (lps22hb._read_byte(LPS_STATUS)&0x01)==0x01: # a new pressure data is generated
u8Buf[0]=lps22hb._read_byte(LPS_PRESS_OUT_XL)
u8Buf[1]=lps22hb._read_byte(LPS_PRESS_OUT_L)
u8Buf[2]=lps22hb._read_byte(LPS_PRESS_OUT_H)
PRESS_DATA=((u8Buf[2]<<16)+(u8Buf[1]<<8)+u8Buf[0])/4096.0
FD='Pressure-is= '+str(round(PRESS_DATA,2))+' hPa'
print(FD)
#F3=FD.encode('utf-8')
#sock.send(str.encode(str(len(F3)).ljust(16)));
#sock.send(F3)
if __name__ == '__main__':
SendVideo()
代码中读取的数据包括大气压以及温度数据(作为辅助),笔者只需要大气压数据,故将温度数据注释掉。主函数中多了(from LPS import LPS22HB,LPS_STATUS,LPS_PRESS_OUT_XL,LPS_PRESS_OUT_L,LPS_PRESS_OUT_H)这样一串代码,用来引用LPS文件中的类以及相应的各个变量。
注意:
main.py代码中创建了(def SendVideo())函数,多写了部分代码并注释掉。这些东西是为了之后与Web端进行通信做准备的。现在这个代码直接运行也可以出来数据。若不需要通信的。可以写成下面的代码:
# coding=UTF-8
from LPS import LPS22HB,LPS_STATUS,LPS_PRESS_OUT_XL,LPS_PRESS_OUT_L,LPS_PRESS_OUT_H
import time
import math
PRESS_DATA = 0.0
u8Buf=[0,0,0]
lps22hb=LPS22HB()
while True:
time.sleep(0.1)
lps22hb.LPS22HB_START_ONESHOT()
if (lps22hb._read_byte(LPS_STATUS)&0x01)==0x01: # a new pressure data is generated
u8Buf[0]=lps22hb._read_byte(LPS_PRESS_OUT_XL)
u8Buf[1]=lps22hb._read_byte(LPS_PRESS_OUT_L)
u8Buf[2]=lps22hb._read_byte(LPS_PRESS_OUT_H)
PRESS_DATA=((u8Buf[2]<<16)+(u8Buf[1]<<8)+u8Buf[0])/4096.0
FD='Pressure-is= '+str(round(PRESS_DATA,2))+' hPa'
print(FD)
其他传感器:
上面讲述了大气压模块代码的引用,以此类推,其他传感器方法如下:
(1)温湿度
文件:
main.py代码:
# coding=UTF-8
from SHTC import SHTC3
import time
import math
def SendVideo():
shtc3=SHTC3()
while 1:
# 收集温湿度数据
Temp=shtc3.SHTC3_Read_Temperature()
Humid=shtc3.SHTC3_Read_Humidity()
# 数据处理与发送
FA="Temperature-is:"+str(round(Temp,2))+"C "
FB="Humidity-is:"+str(round(Humid,2))+"% "
# F0=FA.encode('utf-8')
# F1=FB.encode('utf-8')
# sock.send(str.encode(str(len(F0)).ljust(16)));
# sock.send(F0)
# sock.send(str.encode(str(len(F1)).ljust(16)));
# sock.send(F1)
print(FA+" "+FB)
#print(FB)
time.sleep(2)
if __name__ == '__main__':
SendVideo()
(2)陀螺仪
文件:
main.py代码:
# coding=UTF-8
from ICM import ICM20948
from ICM import Gyro,Accel,Mag
import time
import math
icm20948=ICM20948()
while True:
#收集并计算陀螺仪模块
icm20948.icm20948_Gyro_Accel_Read()
icm20948.icm20948MagRead()
# 数据处理
FC="Acceleration-is:"+str(Accel[0])+"-"+str(Accel[1])+"-"+str(Accel[2])+" "
FD="Gyroscope-is:"+str(Gyro[0])+"-"+str(Gyro[1])+"-"+str(Gyro[2])+" "
FE="Magnetic-is:"+str(Mag[0])+"-"+str(Mag[1])+"-"+str(Mag[2])+" "
print(FC)
print(FD)
print(FE)
(3)ADC采样
这块代码比较复杂,他需要外接模块,且模块数据传输方式最好为模拟信号(模块中有AOUT或AO引脚)才行。数模转换就是把模拟信号按照一定精度进行采样,变成有限多个数字量,这个过程就是数模转换,数字化之后就可以在计算机中用数字来描述模拟量。
本博客以气体传感器MQ-135_Gas_Sensor为例
MQ135气体传感器所使用的气敏材料是在清洁空气中电导率较低的二氧化锡(SnO2)。电源说是连3.3V/5V,但我连3.3v时有点异常。故连到了5v。GND/AOUT/VCC连接顺序分别如下图1/2/3所示(此时AOUT连到了AIN0处):
文件:
main.py代码:
# coding=UTF-8
from ADC import ADS1015
from ADC import ADS_POINTER_CONFIG
import time
import math
import smbus
def SendVideo():
ads1015=ADS1015()
state=ads1015._read_u16(ADS_POINTER_CONFIG) & 0x8000 # 风向传感器连接确立
if(state!=0x8000):
print("\nADS1015 Error\n")
# 收集数据
while 1:
AIN0_DATA=ads1015.ADS1015_SINGLE_READ(0)
AIN0_DATA=(AIN0_DATA/409.6)*3.3
FG="The current Gas AD value:"+str(round(AIN0_DATA,2))+" fV"
#FG=AIN0_DATA
print(FG)
time.sleep(0.1)
# F6=FG.encode('utf-8')
# sock.send(str.encode(str(len(F6)).ljust(16)));
# sock.send(F6)
if __name__ == '__main__':
SendVideo()
代码经过上述处理后,就有个各个相应的模块源代码以及主函数的调用代码。接下来笔者用其中三个代码文件进行代码的集合,以实现大气压、气体以及温湿度的同步监测:
代码集合:
任选其中一个主函数main.py进行编辑,将其他两个main.py中不一样的部分复制过来。
文件:
main.py代码:
# coding=UTF-8
import RPi.GPIO as GPIO
from ADC import ADS1015
from ADC import ADS_POINTER_CONFIG
from SHTC import SHTC3
from LPS import LPS22HB,LPS_STATUS,LPS_PRESS_OUT_XL,LPS_PRESS_OUT_L,LPS_PRESS_OUT_H
import time
import math
import smbus
def SendVideo():
shtc3=SHTC3()
PRESS_DATA = 0.0
u8Buf=[0,0,0]
lps22hb=LPS22HB()
ads1015=ADS1015()
state=ads1015._read_u16(ADS_POINTER_CONFIG) & 0x8000 # 气体传感器连接确立
if(state!=0x8000):
print("\nADS1015 Error\n")
# 收集气体数据
while 1:
#收集温湿度数据
Temp=shtc3.SHTC3_Read_Temperature()
Humid=shtc3.SHTC3_Read_Humidity()
# 数据处理与发送
FA="Temperature-is:"+str(round(Temp,2))+"C "
FB="Humidity-is:"+str(round(Humid,2))+"% "
lps22hb.LPS22HB_START_ONESHOT()
if (lps22hb._read_byte(LPS_STATUS)&0x01)==0x01: # a new pressure data is generated
u8Buf[0]=lps22hb._read_byte(LPS_PRESS_OUT_XL)
u8Buf[1]=lps22hb._read_byte(LPS_PRESS_OUT_L)
u8Buf[2]=lps22hb._read_byte(LPS_PRESS_OUT_H)
PRESS_DATA=((u8Buf[2]<<16)+(u8Buf[1]<<8)+u8Buf[0])/4096.0
FD='Pressure-is= '+str(round(PRESS_DATA,2))+' hPa'
AIN0_DATA=ads1015.ADS1015_SINGLE_READ(0)
AIN0_DATA=(AIN0_DATA/409.6)*3.3 #计算气体浓度
else:
FF="The current Gas AD value:"+str(round(AIN0_DATA,2))+" fV"
print(FA)
print(FB)
print(FD)
print(FF)
time.sleep(1)
# F0=FA.encode('utf-8')
# F1=FB.encode('utf-8')
# F3=FD.encode('utf-8')
# F6=FF.encode('utf-8')
# sock.send(str.encode(str(len(F0)).ljust(16)));
# sock.send(F0)
# sock.send(str.encode(str(len(F1)).ljust(16)));
# sock.send(F1)
# sock.send(str.encode(str(len(F3)).ljust(16)));
# sock.send(F3)
# sock.send(str.encode(str(len(F6)).ljust(16)));
# sock.send(F6)
if __name__ == '__main__':
SendVideo()
运行结果展示:
总结:
笔者这次只是将代码进行简单的集合。其中ADC一共是有4个通道,因此我们可以一次性扩展最多4个ADC模块。笔者做的每个项目用到ADC的模块都会有两个以上,多个ADC模块可共用一个代码源ADC,只要将里面的通道1/2/3/4定义成不同的即可,可以说是非常的方便了。
希望本博客能给读者一定的帮助,省下找各种解决方案的时间成本,笔者现在水平还是比较一般的,感谢观看,如有不足,欢迎在评论内留言与讨论。如果觉得写得好,可以给我点赞+收藏+关注哦,再次感谢各位!