系列文章目录
树莓派科学小实验
001 点亮第一盏LED灯
002 点亮LED灯组
003_开关控制LED灯
004_获取温湿度
005_跑马灯(ws2812b))
006_数字温度传感器(PCF8591,LM393)
前言
在之前的文章中直接通过GPIO管脚获取传感器的信息来实现功能的例子做完了,那通过I2C接口呢?下面的这个例子就是通过I2C接口连接AD-DA转换芯片来获取信息并实现功能的实验。
提示:以下是本篇文章正文内容,下面案例可供参考
一、实验元件
带有PCF8591芯片的接口卡一块
带有LM393比较电路的温度传感器接口卡一块
在面包板上的连接图,注意其中PCF8591和树莓派以及传感器板是共地以及共同使用3.3v(如果使用单独的PCF8591接口板建议使用5v供电口)
1)由于我使用的是带有PCF8591芯片的接口板所有,从树莓派到AD-DA转换器的电路就不用再接了,但是如果使用的是独立的转换器,需要将主板的SCL和SDA口分别和PCF8591的对应接口相连,同时将GND以及5V供电接口和PCF8591相连。
2)PCF的AIN0口和温度传感器的A0接口相连
3)主板的IO17和传感器的D0口相连
实际接线
二、代码分析
1. 查看I2C接口上的设备地址
使用命令 i2cdetect 来查看i2c的设备
pi@raspberrypi:~/Code/Python/4B/Stus $ i2cdetect -l
我的树莓派有3组i2c接口。
pi@raspberrypi:~/Code/Python/4B/Stus $ sudo i2cdetect -r -y 1
在1号组上可以看到48这个地址位,这个是PCF8591的地址
2. PCF8591的代码
再次贴出PCF8591的代码:
# -*- coding: utf-8 -*-
"""
#类说明文件
author = "Derek Tian"
version = '0.0.1'
make day=2022-02-02
import PCF8591 as ADC
ADC.Setup(Address) # 通过 sudo i2cdetect -y -1 可以获取到IIC的地址
ADC.read(channal) # 通道选择范围为0-3
ADC.write(Value) # 值的范围为:0-255
"""
__docformat__ = "restructuredtext en"
__all__ = []
__license__ = "MIT license"
import smbus #调用smbus的快速I2c库
import time
bus = smbus.SMBus(1) #读取1号总线上的数据
# 初始化设备,传入总线地址:注意为16进制的地址位
def setup(Addr):
global address
address = Addr
# 字符串转16进制的地址位
def str_to_hex(s):
return ' '.join([hex(ord(c)).replace('0x', '') for c in s])
# 读取模拟量信息
def read(chn): #通道选择,范围是0-3之间
try:
if chn == 0:
bus.write_byte(address,0x40)
if chn == 1:
bus.write_byte(address,0x41)
if chn == 2:
bus.write_byte(address,0x42)
if chn == 3:
bus.write_byte(address,0x43)
bus.read_byte(address) # 开始进行读取转换
except Exception as e:
print ("Address: %s" % address)
print (e)
return bus.read_byte(address)
# 模块输出模拟量控制,范围为0-255
def write(val,chn):
try:
temp = val # 将数值赋给temmp 变量
temp = int(temp) # 强类型转换到int型
tchn=str_to_hex(chn)
bus.write_byte_data(address,tchn, temp) #向I2c的通道写入数据
except Exception as e:
print (e)
3. 温度传感器
温度传感器使用的是PT100的温敏电阻,各个温度的阻值可以上网查询到对应表 ,对于计算公式,使用通用的计算公式就可以:
热敏电阻的计算公式为:
Rt = R EXP(B(1/T1-1/T2))
对上面的公式解释如下:
Rt 是热敏电阻在T1温度下的阻值;
R是热敏电阻在T2常温下的标称阻值;
B值是热敏电阻的重要参数;
EXP是e的n次方;
这里T1和T2指的是K度即开尔文温度,K度=273.15(绝对温度)+摄氏度;
传感器的代码部分
# -*- coding: utf-8 -*-
"""
#类说明文件
author = "Derek Tian"
version = '0.0.1'
make day=2022-02-03
"""
__docformat__ = "restructuredtext en"
__all__ = []
__license__ = "MIT license"
import PCF8591 as ADC
import RPi.GPIO as GPIO
import time
import math
TempPin=17 # 设定使用IO17来接收PCF8591的数字输出端口值
I2CAdd=0x48 # 设定PCF8591使用的I2C地址值
GPIO.setmode(GPIO.BCM) #初始化使用GPIO的BCM方式
# 初始化温度传感器
def TempSetup():
ADC.setup(I2CAdd)
GPIO.setup(TempPin,GPIO.IN)
# 检查并显示数字值得判断
def ShowTemperatuer(Val):
if Val==1:
print("#############Temperature is nice !!!!!!")
else:
print("#############Alarm:TOO HOT!!!")
# 通过一个死循环来不停地获取温度值
def GetTemperatuer_Loop():
Status=1
m_DA_temp=1
while True:
TempVal=ADC.read(0)
print(f"get value from PCF:{TempVal}...............")
m_Vr=3.3 * float(TempVal) /255
print(f"To 3.3V :{m_Vr}......................")
m_Rv=10000 * m_Vr /(3.3-m_Vr)
print(f"Get resistance Value:{m_Rv}..........")
temp = 1 / (((math.log(m_Rv / 10000)) / 3950) + (1 / (273.15 + 25)))
temp = temp - 273.15
print(f"temperature = {temp} C")
m_DA_temp=GPIO.input(TempPin)
print(f"DA Temp value:{m_DA_temp}")
if m_DA_temp !=Status:
ShowTemperatuer(m_DA_temp)
Status=m_DA_temp
time.sleep(0.5)
if __name__=="__main__":
try:
TempSetup()
GetTemperatuer_Loop()
except KeyboardInterrupt:
pass
显示结果
调节可变电阻来控制数字比较器的值得改变: