热敏电阻模块对环境较高温度很敏感,一般用来检测周围环境的较高温,通过对电位器的调节,可以改变高温度的检测阀值(即控制高温值),比如需要控温度为60度时,则模块在相应环境温度调到绿灯熄灭,DO此时输出高电平,如果高于此温度时,输出低电平绿灯亮。DO输出端可以与树莓派和单片机直接相连,通过单片机来检测高低电平,由此来检测环境的高温阈值,DO输出端还可以驱动5V继电器模块,由此可以组成一个温控开关,控制相关设备的工作温度,用于水温,水箱等的控制,也可以接风扇用来实现自动散热等,热敏电阻传感器温度检测范围为50-100摄氏度左右。
该模块基于热敏电阻的原理,其电阻随环境温度变化很大,当环境温度升高时热敏电阻的电阻降低,当环境温度降低时它的电阻增加。它可以实时检测周围的温度变化。
树莓派主板 | 热敏电阻传感器 |
5V | VCC |
GND | GND |
DO | GPIO1(BCM18) |
import RPi.GPIO as GPIO import time # 配置GPIO GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) GPIO_PIN = 18 # 初始化引脚为输入模式,启用下拉电阻 GPIO.setup(GPIO_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) try: print("实时监测高温...") last_status = None # 记录上次状态 while True: # 读取当前引脚状态 current_status = GPIO.input(GPIO_PIN) # 只在状态变化时更新显示 if current_status != last_status: if current_status == GPIO.HIGH: print("\r当前状态:正常", end="", flush=True) else: print("\r当前状态:高温", end="", flush=True) last_status = current_status time.sleep(0.1) # 降低CPU占用率 except KeyboardInterrupt: print("\n监测已终止") finally: GPIO.cleanup()
以上代码简单检查传感器的效果显示:正常,当探头接触到高温时显示: 高温, 如果我们要控制
如果我们用传感器来控制外设可以添加继电器模块, 在以上代码的基础上在编写个控制程序去打开继电器控制风扇。比如我们接入5V继电器+风扇后。将继电器IN引脚接入在树莓派GPIO4上,继电器在控制风扇,程序就可以这样写
import RPi.GPIO as GPIO import time # 设置GPIO模式 GPIO.setmode(GPIO.BCM) # 定义GPIO引脚 GPIO_INPUT_PIN = 18 # 监测引脚 GPIO_OUTPUT_PIN = 4 # 控制风扇的引脚 # 设置GPIO引脚的输入和输出模式 GPIO.setup(GPIO_INPUT_PIN, GPIO.IN) GPIO.setup(GPIO_OUTPUT_PIN, GPIO.OUT) try: while True: # 读取GPIO18的状态 input_state = GPIO.input(GPIO_INPUT_PIN) if input_state == GPIO.LOW: # 有低电平输入 GPIO.output(GPIO_OUTPUT_PIN, GPIO.HIGH) # 启动风扇 print("高温,风扇启动") else: # 无低电平输入 GPIO.output(GPIO_OUTPUT_PIN, GPIO.LOW) # 停止风扇 print("正常,风扇停止") time.sleep(1) # 每秒检查一次 except KeyboardInterrupt: # 捕获Ctrl+C退出程序 pass finally: # 清理GPIO设置 GPIO.cleanup()
如果需要使用AO模拟量信号,我们可使用模数转换器PCF8591将模拟信号转换为数字信号。但是在编程中,我们要通过数字信号值计算出热敏电阻的实时阻值,再来计算对应的温度值。
热敏电阻传感器,其内部电阻会随环境温度变化很大,当环境温度升高时热敏电阻的电阻降低,当环境温度降低时它的电阻增加。它可以实时检测周围的温度变化,在使用AO模拟量信号时我们需要使用到模数转换器PCF8591将模拟信号转换为数字信号。在编程中我们要通过数字信号值计算出热敏电阻的实时阻值,再来计算对应的温度值。 关于PCF8591数模转换模块的使用资料可参考:PCF8591模数AD模拟量教程
计算热敏电阻实时阻值:
1.通过函数 ADC.read(0) 取得传感器模拟输出A/D转化后的数字值:
analogVal = ADC.read(0)
2.利用上面的值计算热敏电阻的原始模拟电压值Vr :
Vr= 5 * float(analogVal) / 255
3.串联电路电流值相同,所以电流值相等:
热敏电阻电压 / 热敏电阻值=(5V-热敏电阻电压) / 另外一个分压电阻阻值
从上面的电路图可知,另外一个分压电阻阻值为10K,即10000,所以热敏电阻值:
Rt = 10000 * Vr / (5 - Vr)
热敏电阻公式:
NTC 热敏电阻温度计算公式,Steinhart-Hart公式,即温度-阻值关系等式,他是一个经验公式,是用来描述NTC 热敏电阻的阻值与温度关系的最好的数学表达式:
Rt = R*EXP(B*(1/T1-1/T2))
其中,T1和T2指的是K度,即开尔文温度。
Rt 是热敏电阻在T1温度下的阻值。
R是热敏电阻在T2常温下的标称阻值。10K的热敏电阻25℃的值为10K(即R=10000)。T2=(273.15+25)
EXP是e的n次方
B值是热敏电阻的重要参数,B=3950
通过转换可以得到温度T1与电阻Rt的关系T1=1/(ln(Rt/R)/B+1/T2)
对应的摄氏温度t=T1-273.15,同时+0.5的误差矫正。
在编程时需要先写个PCF8591.py库文件,后面再编写一个python程序引入这个库文件。PCF8591.py库文件就是PCF8591模块的程序,单独编写是为了便于重用。在下面的脚本中,我们使用了一个放大器用于模拟输入和一个LED灯用于模拟输出,模拟输入不能超过3.3V!该程序也可以单独运行,用于测试3个电阻模块的功能。需用短路帽连接AIN0和INPUT0(电位计模块),连接AIN1和INPUT1(光敏电阻模块),以及连接AIN2和INPUT2(热敏电阻模块)。连接LED灯,AIN0(模拟输入0)端口用于接收来自电位计模块的模拟信号,AOUT(模拟输出)用于将模拟信号输出到双色LED模块,以便改变LED的亮度。
AO模拟量参考代码
#!/usr/bin/env python #www.raspi.cc # # 您可以使用下面语句将此脚本导入另一个脚本: # “import PCF8591 as ADC” # # ADC.Setup(Address) # 查询PCF8591的地址:“sudo i2cdetect -y 1” # i2cdetect is a userspace program to scan an I2C bus for devices. # It outputs a table with the list of detected devices on the specified bus. # ADC.read(channal) # Channal范围从0到3 # ADC.write(Value) # Value范围从0到255 # #------------------------------------------------------ #SMBus (System Management Bus,系统管理总线) import smbus #在程序中导入“smbus”模块 import time # for RPI version 1, use "bus = smbus.SMBus(1)" # 0 代表 /dev/i2c-0, 1 代表 /dev/i2c-1 ,具体看使用的树莓派那个I2C来决定 bus = smbus.SMBus(1) #创建一个smbus实例 #在树莓派上查询PCF8591的地址:“sudo i2cdetect -y 1” def setup(Addr): global address address = Addr def read(chn): #channel 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) # 从设备读取单个字节,而不指定设备寄存器。 return bus.read_byte(address) #返回某通道输入的模拟值A/D转换后的数字值 def write(val): temp = val # 将字符串值移动到temp temp = int(temp) # 将字符串改为整数类型 # print temp to see on terminal else comment out bus.write_byte_data(address, 0x40, temp) #写入字节数据,将数字值转化成模拟值从AOUT输出 if __name__ == "__main__": setup(0x48) #在树莓派终端上使用命令“sudo i2cdetect -y 1”,查询出PCF8591的地址为0x48 while True: print '电位计 AIN0 = ', read(0) #电位计模拟信号转化的数字值 print '光敏电阻 AIN1 = ', read(1) #光敏电阻模拟信号转化的数字 print '热敏电阻 AIN2 = ', read(2) #热敏电阻模拟信号转化的数字值 tmp = read(0) tmp = tmp*(255-125)/255+125 # 125以下LED不会亮,所以将“0-255”转换为“125-255”,调节亮度时灯不会熄灭 write(tmp) time.sleep(2)
然后编写控制程序。屏幕不断打印输出实时温度的值。若温度大于33°,打印“Too Hot!”;如果温度小于31°,打印“Better~” 。31和33要根据实验时,实测温度范围调整。
#!/usr/bin/env python import PCF8591 as ADC import RPi.GPIO as GPIO import time import math DO = 17 GPIO.setmode(GPIO.BCM) def setup(): ADC.setup(0x48) GPIO.setup(DO, GPIO.IN) def Print(x): if x == 1: print '' print '***********' print '* Better~ *' print '***********' print '' if x == 0: print '' print '************' print '* Too Hot! *' print '************' print '' def loop(): status = 1 tmp = 1 while True: analogVal = ADC.read(0) #温度传感器模拟输出A/D转化后的数字值 Vr = 5 * float(analogVal) / 255 #Vr为数字值转化为热敏电阻的原始模拟电压值 Rt = 10000 * Vr / (5 - Vr) #Rt是热敏电阻在T1温度下的阻值,10000=10k为与热敏电阻串联的电阻的阻值 #查阅传感器电路图知,因为是串联,所以电流值相等 Vr/Rt=(5-Vr)/10000 temp = 1/(((math.log(Rt / 10000)) / 3950) + (1 / (273.15+25))) # T1=1/(ln(Rt/R)/B+1/T2) 对应的摄氏温度t=T1-273.15 # R=10k=10000 B=3950 T2=(273.15+25) temp = temp - 273.15 print 'temperature = ', temp, 'C' if temp > 33: tmp = 0; elif temp < 31: tmp = 1; if tmp != status: Print(tmp) status = tmp time.sleep(0.2) if __name__ == '__main__': try: setup() loop() except KeyboardInterrupt: pass
关于AO模拟量使用请结合pcf8591AD模块进行使用。