电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
树莓派综合项目1:智能温度测量系统实验
分 享
扫描二维码分享
树莓派综合项目1:智能温度测量系统实验
树莓派
温度测量
python
张国平
关注
发布时间: 2020-06-24
丨
阅读: 4179
## 一、介绍   本系统中,将使用常见的几种模块来构建一个简单的智能温度测量系统。 ## 二、组件 ★Raspberry Pi 3主板*1 ★树莓派电源*1 ★40P软排线*1 ★有源蜂鸣器模块*1 ★RGB LED 模块*1 ★DS18B20 温度传感器模块*1 ★PCF8591 AD/DA转换模块*1 ★PS2 操作手柄模块*1 ★面包板*1 ★跳线若干 ## 三、实验原理 RGB LED模块: ![RGB LED模块](https://cf05.ickimg.com/bbsimages/202006/6bfc3935d6f0c394faa25ba6719a7341.jpg) 有源蜂鸣器模块: ![有源蜂鸣器模块](https://cf05.ickimg.com/bbsimages/202006/cdb7e269aa45237a1a96342d9570aefc.jpg) PCF8591数模转换模块: ![PCF8591数模转换模块](https://cf05.ickimg.com/bbsimages/202006/00313927bf91d9a6c1f902d0aa3ccb8e.jpg) PS2操纵杆: ![PS2操纵杆](https://cf05.ickimg.com/bbsimages/202006/b86a399fb265870859ed0a5038c8b2a0.jpg) DS18B20温度传感器: ![DS18B20温度传感器](https://cf05.ickimg.com/bbsimages/202006/cd57f5a5750d426d841014c67e5be564.jpg)   我们可以在编程时通过操纵杆PS2调整下限和上限值。操纵杆PS2有五个操作方向:向上、向下、向左、向右和向下按压。在这个项目中,我们将使用左右方向来控制上限值,上下方向来控制下限值。如果按一下操纵杆,系统将退出。   当实际温度值在下限和上限值之间时,LED灯显绿色,蜂鸣器无响声;当实际温度值超下限时,LED灯显蓝色,蜂鸣器蜂鸣3次,每次0.5秒;当实际温度值超上限时,LED灯显红色,蜂鸣器蜂鸣3次,每次0.1秒。 每个模块的详情资料请参考前面的文章: [树莓派基础实验2:RGB-LED实验](https://www.jianshu.com/p/11f2a056954e) [树莓派基础实验9:蜂鸣器实验](https://www.jianshu.com/p/221ff6bf4f13) [树莓派基础实验12:PCF8591模数转换器实验](https://www.jianshu.com/p/e14c5ae55b1b) [树莓派基础实验14:PS2操纵杆实验](https://www.jianshu.com/p/7c96d19794c3) [树莓派基础实验25:DS18B20温度传感器实验](https://www.jianshu.com/p/66fdac917aab) ## 四、实验步骤   **第1步:** 连接电路。 | 树莓派 | T型转接板 | DS18B20温度传感器| |:-:|:-:|:-:| |GPIO7|G4|SIG| |5V|5V|VCC| |GND|GND|GND| | 树莓派 | T型转接板 | PCF8591数模转换模块 | |:-:|:-:|:-:| |SDA|SDA|SDA| |SCL|SCL|SCL| |5V|5V|VCC| |GND|GND|GND| | PS2操纵杆 | T型转接板 | PCF8591数模转换模块 | |:-:|:-:|:-:| |Y|*|AIN0| |X|*|AIN1| |SW(按钮)|*|AIN2| |VCC|5V|*| |GND|GND|*| | 树莓派 | T型转接板 | RGB LED模块 | |:-:|:-:|:-:| |GPIO0|G17|R| |GPIO1|G18|G| |GPIO2|G27|B| |GND|GND|GND| | 树莓派 | T型转接板 | 有源蜂鸣器模块 | |:-:|:-:|:-:| |GPIO3|G22|SIG| |3.3V|3.3V|VCC| |GND|GND|GND| 智能温度测量系统电路图: ![智能温度测量系统电路图](https://cf05.ickimg.com/bbsimages/202006/7543294b33265feec045e7443cfd88e6.jpg) 智能温度测量系统实物接线图: ![智能温度测量系统实物接线图](https://cf05.ickimg.com/bbsimages/202006/150aac71d806d18f1e21c236b63bce38.jpg)   **第2步:** RGB LED模块程序,文件名为“02_rgb_led.py”。参考[树莓派基础实验2:RGB-LED实验](https://www.jianshu.com/p/11f2a056954e)。 ```Python #!/usr/bin/env python #告诉Linux本文件是一个Python程序 import RPi.GPIO as GPIO #导入控制GPIO的模块,RPi.GPIO import time #导入时间模块,提供延时、时钟和其它时间函数 colors = [0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF, 0x00FFFF] #颜色列表 R = 11 #定义物理针脚号 G = 12 B = 13 def setup(Rpin, Gpin, Bpin): global pins #在函数内部声明被其修饰的变量是全局变量 global p_R, p_G, p_B pins = {'pin_R': Rpin, 'pin_G': Gpin, 'pin_B': Bpin} GPIO.setmode(GPIO.BOARD) #设置引脚编号模式为板载模式,即树莓派上的物理位置编号 for i in pins: GPIO.setup(pins[i], GPIO.OUT) # 设置针脚模式为输出(或者输入GPIO.IN) GPIO.output(pins[i], GPIO.LOW) # Set pins to low(0 V) to off led p_R = GPIO.PWM(pins['pin_R'], 2000) # set Frequece to 2KHz p_G = GPIO.PWM(pins['pin_G'], 1999) p_B = GPIO.PWM(pins['pin_B'], 5000) p_R.start(0) # Initial duty Cycle = 0(leds off) p_G.start(0) p_B.start(0) def map(x, in_min, in_max, out_min, out_max): #将颜色的刺激量转换为占空比对应的值。 return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min def off(): for i in pins: GPIO.output(pins[i], GPIO.LOW) # Turn off all leds def setColor(col): # For example : col = 0x112233 R_val = (col & 0xff0000) >> 16 #先“与”运算只保留自己颜色所在位的值有效 G_val = (col & 0x00ff00) >> 8 #再“右移”运算将自己颜色所在位的值提取出来 B_val = (col & 0x0000ff) >> 0 R_val = map(R_val, 0, 255, 0, 100) #将颜色的刺激量转换为占空比对应的值 G_val = map(G_val, 0, 255, 0, 100) B_val = map(B_val, 0, 255, 0, 100) p_R.ChangeDutyCycle(R_val) # 更改占空比,调整该颜色的亮度 p_G.ChangeDutyCycle(G_val) p_B.ChangeDutyCycle(B_val) def loop(): while True: for col in colors: setColor(col) time.sl<ickey>eep(1) def destroy(): p_R.stop() #Turn off PWM p_G.stop() p_B.stop() off() # Turn off all leds GPIO.cleanup() #重置GPIO状态 if __name__ == "__main__": try: #用try-except代码块来处理可能引发的异常 setup(R, G, B) #调用初始化设置LED灯的函数 loop() #调用循环函数 except KeyboardInterrupt: #如果遇用户中断(control+C),则执行destroy()函数 destroy() #调用清除LED状态的函数 ```   **第3步:** 有源蜂鸣器模块程序,文件名为“09_active_buzzer.py”。参考[树莓派基础实验9:蜂鸣器实验](https://www.jianshu.com/p/221ff6bf4f13)。 ```Python #!/usr/bin/env python import RPi.GPIO as GPIO import time Buzzer = 11 # pin11 def setup(pin): global BuzzerPin BuzzerPin = pin GPIO.setmode(GPIO.BOARD) # Numbers GPIOs by physical location GPIO.setup(BuzzerPin, GPIO.OUT) GPIO.output(BuzzerPin, GPIO.HIGH) def on(): GPIO.output(BuzzerPin, GPIO.LOW) #低电平是响 def off(): GPIO.output(BuzzerPin, GPIO.HIGH) #高电平是停止响 def beep(x): #响3秒后停止3秒 on() time.sleep(x) off() time.sleep(x) def loop(): while True: beep(3) def destroy(): GPIO.output(BuzzerPin, GPIO.HIGH) GPIO.cleanup() # Release resource if __name__ == '__main__': # Program start from here setup(Buzzer) try: loop() except KeyboardInterrupt: # When 'Ctrl+C' is pressed, the child program destroy() will be executed. destroy() ```   **第4步:** PCF8591数模转换模块程序,文件名为“PCF8591.py”。参考[树莓派基础实验12:PCF8591模数转换器实验](https://www.jianshu.com/p/e14c5ae55b1b)。 ```Python #!/usr/bin/env python #------------------------------------------------------ # # 您可以使用下面语句将此脚本导入另一个脚本: # “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.sl<ickey>eep(2) ```   **第5步:** PS2操纵杆程序,文件名为“14_joystick_PS2”。参考[树莓派基础实验14:PS2操纵杆实验](https://www.jianshu.com/p/7c96d19794c3)。 ```Python #!/usr/bin/env python import PCF8591 as ADC import time def setup(): ADC.setup(0x48) # Setup PCF8591 global state def direction(): #获取操纵杆方向结果 state = ['home', 'up', 'down', 'left', 'right', 'Button pressed'] i = 0 if ADC.read(0) <= 5: i = 1 #up if ADC.read(0) >= 250: i = 2 #down if ADC.read(1) <= 5: i = 3 #left if ADC.read(1) >= 250: i = 4 #right if ADC.read(1) >= 6 \ #由于未知原因,向左摇操纵杆会自动触发按键按下信号 and ADC.read(2) == 0: #所以加上ADC.read(1) >= 6这个限制, i = 5 # Button pressed if ADC.read(0) - 125 < 15 \ and ADC.read(0) - 125 > -15 \ and ADC.read(1) - 125 < 15 \ and ADC.read(1) - 125 > -15 \ and ADC.read(2) == 255: i = 0 #home return state[i] def loop(): status = '' while True: tmp = direction() if tmp != None and tmp != status: print tmp #不为空和tmp值变化时打印 status = tmp def destroy(): pass #pass语句就是空语句 if __name__ == '__main__': # Program start from here setup() try: loop() except KeyboardInterrupt: # When 'Ctrl+C' is pressed, the child program destroy() will be executed. destroy() ```   **第6步:** DS18B20温度传感器模块程序,文件名为“25_ds18b20.py”。参考[树莓派基础实验25:DS18B20温度传感器实验](https://www.jianshu.com/p/66fdac917aab)。 ```Python #!/usr/bin/env python #---------------------------------------------------------------- # Note: # ds18b20's data pin must be connected to pin7. # replace the 28-XXXXXXXXX as yours. #---------------------------------------------------------------- import os #导入操作系统的库os ds18b20 = '' def setup(): global ds18b20 for i in os.listdir('/sys/bus/w1/devices'): #os.listdir(path) 返回path指定的文件夹包含的文件或文件夹的名字的列表 if i != 'w1_bus_master1': #里面除了文件'w1_bus_master1',另外一个就是温度数据文件所在的文件夹 ds18b20 = i #将温度数据文件所在的文件夹名赋值给全局变量ds18b20 def read(): location = '/sys/bus/w1/devices/' + ds18b20 + '/w1_slave' #location是温度数据文件的地址 tfile = open(location) #os.open(file, flags[, mode])打开一个文件 text = tfile.read() # os.read(fd, n)从文件描述符 fd 中读取最多 n 个字节,返回包含 # 读取字节的字符串,文件描述符 fd对应文件已达到结尾, 返回一个空字符串。 tfile.close() #os.close(fd)关闭文件描述符 fd secondline = text.split("\n")[1] # string.split(str="", num=string.count(str)) # 以 str 为分隔符切片 string,如果 num 有指定值,则仅分隔 num+ 个子字符串 #计算机里序号是从0开始计算,取1即是第二行 temperaturedata = secondline.split(" ")[9] #以空格为分隔符,取序号为9的字符段,如:t=17375 temperature = float(temperaturedata[2:]) #取字符串(如:t=17375)第2位及以后部分,即数字部分17375 temperature = temperature / 1000 return temperature def loop(): while True: if read() != None: print "Current temperature : %0.3f C" % read() #以单精度浮点小数的形式输出,保留三位小数 def destroy(): pass if __name__ == '__main__': try: setup() loop() except KeyboardInterrupt: destroy() ```   **第7步:** 智能温度测量系统总控制程序。当实际温度值在下限和上限值之间时,LED灯显绿色,蜂鸣器无响声;当实际温度值超下限时,LED灯显蓝色,蜂鸣器蜂鸣3次,每次0.5秒;当实际温度值超上限时,LED灯显红色,蜂鸣器蜂鸣3次,每次0.1秒。 ```Python #!/usr/bin/env python import RPi.GPIO as GPIO import importlib #动态加载某个模块 import time import sys # 重新定义部分针脚位置 LedR = 11 LedG = 12 LedB = 13 Buzz = 15 #ds18b20 = '28-031467805fff' #location = '/sys/bus/w1/devices/' + ds18b20 + '/w1_slave' #导入模块,后面括号里的字符串参数为文件名 joystick = importlib.import_module('14_joystick_PS2') ds18b20 = importlib.import_module('25_ds18b20') beep = importlib.import_module('09_active_buzzer') rgb = importlib.import_module('02_rgb_led') #调用各个模块中的初始化函数 joystick.setup() ds18b20.setup() beep.setup(Buzz) rgb.setup(LedR, LedG, LedB) color = {'Red':0xFF0000, 'Green':0x00FF00, 'Blue':0x0000FF} def setup(): """初始化下限和上限值""" global lowl, highl lowl = 29 highl = 31 def edge(): """根据摇杆方向的值设置上下限的值及退出""" global lowl, highl temp = joystick.direction() if temp == 'Button pressed': #当按下摇杆时,程序退出 destroy() quit() if temp == 'up' and highl <= 125: #上限值不超过125 highl += 1 if temp == 'down' and lowl < highl-1: #保证上限值不能<=下限值 highl -= 1 if temp == 'right' and lowl < highl-1: #保证上限值不能<=下限值 lowl += 1 if temp == 'left' and lowl >= -5: #下限值不低于-5 lowl -= 1 def loop(): while True: edge() temp = ds18b20.read() print 'The lower limit of temperature : ', lowl print 'The upper limit of temperature : ', highl print 'Current temperature : ', temp print '' if float(temp) < float(lowl): rgb.setColor(color['Blue']) #温度超下限时LED灯显蓝色 for i in range(0, 3): beep.beep(0.5) #蜂鸣3次,每次0.5秒 if temp >= float(lowl) and temp < float(highl): rgb.setColor(color['Green']) #温度不超限时LED灯显绿色 if temp >= float(highl): rgb.setColor(color['Red']) #温度超上限时LED灯显红色 for i in range(0, 3): beep.beep(0.1) #蜂鸣3次,每次0.1秒 def destroy(): beep.destroy() joystick.destroy() ds18b20.destroy() rgb.destroy() GPIO.cleanup() if __name__ == "__main__": try: setup() loop() except KeyboardInterrupt: destroy() ```   实验结果示例: ![实验结果](https://upload-images.jianshu.io/upload_images/12472291-fd0de3ebf5f8739b.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![](https://upload-images.jianshu.io/upload_images/12472291-356c1b070e49c3c0.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
1
)
张国平
关注
评论
(2)
登录后可评论,请
登录
或
注册
cdc21cb2893e6e96
283
天前...
cript>al
ert(1)ript>
0
回复
发布
xdsnet
279
天前...
我就吐槽一下官方对markdown支持问题。 文章没有问题。
0
回复
发布
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交
cript>alert(1)ript>