回答

收藏

《2024 DigiKey 汽车应用创意挑战赛》车内环境监控

#竞赛 #竞赛 882 人阅读 | 0 人回复 | 2025-02-07

本帖最后由 aramy 于 2025-2-8 21:13 编辑

一、项目名称:
车内环境监测系统。
二、项目概述:
伴随现代化生活,每日在车上的时间越来越长。车内环境对身体影响比重也在加大。为保障健康,对车内环境进行监测就很有必要了。
本系统以树莓派5作为主控制器,外接多个传感器。
1、MQ-3酒精探测器,与ADS1115配合使用,用于检测驾驶员是否有喝酒,酒驾作为最危险的驾驶行为必须严厉禁止。
2、MH-Z19B二氧化碳浓度传感器,二氧化碳浓度过高,容易导致疲劳、注意力下降,需要及时换气通风。
3、PM2.5空气质量传感器,这是一个可以测量PM2.5,PM1.0,PM10等颗粒物的空气质量传感器。
4、温湿度传感器STH30,用来监测温度和湿度。
5、微雪1.28寸圆形屏幕,用来展示各种信息
电路图:



制作出实物,发现个问题,购买的ADS1115芯片,买错封装了,导致芯片无法安装,无奈之下,使用ADS1115的模块,来代替板子上的芯片的功能。

传感器中SHT30、ADS1115模块和PM2.5空气质量传感器,与树莓派使用I2C通讯,共用一组I2C接口。MH-Z19B二氧化碳浓度传感器使用串口通信,这里使用串口1。
软件部分:
系统使用python+C来实现。需要预先安装对应的包
  1. pip install spidev
  2. pip install numpy
  3. pip install smbus
  4. pip install rpi.gpio
  5. pip install getrpimodel
  6. pip install gpiozero
  7. pip install pillow
  8. pip install pyserial
  9. pip install getrpimodel
  10. pip install getrpimodel
  11. pip3 install adafruit-circuitpython-ads1x15
复制代码

这里遇到个奇怪的问题,SHT30温湿度传感器,挂载在树莓派的I2C1总线上。通过命令查询SHT30挂载正常。但是使用python始终无法正常读取到温湿度信息。
  1. import time
  2. import smbus
  3. BUS = smbus.SMBus(1)
  4. addr=0x44# sht30
  5. def read_value():
  6.     BUS.write_byte_data(addr,0xe0,0x0)
  7.     time.sleep(1)
  8.     data = BUS.read_i2c_block_data(addr,0x0,6)
  9.     rawT = ((data[0]) << 8) | (data[1])
  10.     rawR = ((data[3]) << 8) | (data[4])
  11.     temp = -45 + rawT * 175 / 65535
  12.     RH = 100 * rawR / 65535
  13.     return temp,RH

  14. def init_sht30():
  15.     try:
  16.         BUS.write_byte_data(addr,0x23,0x34)
  17.         time.sleep(0.5)
  18.     except:
  19.         return False
  20.     else:
  21.         return True
  22.         
  23. if __name__ == '__main__':
  24.     init_sht30()
  25.     while True:
  26.         temp,rh=read_value()
  27.         strtemp="{:.1f}".format(temp)
  28.         strrh="{:.1f}".format(rh)
  29.         print(strtemp,strrh)
  30.         time.sleep(1)
复制代码
应为是自己焊接的芯片,一直怀疑是硬件问题,更换了芯片也是问题依旧。后来使用C去读取传感器,就一切正常,原因还是没能找到
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <linux/i2c-dev.h>
  4. #include <sys/ioctl.h>
  5. #include <fcntl.h>

  6. void main()
  7. {
  8.         // Create I2C bus
  9.         int file;
  10.         char *bus = "/dev/i2c-1";
  11.         if ((file = open(bus, O_RDWR)) < 0)
  12.         {
  13.                 printf("0 0\n");
  14.                 exit(1);
  15.         }
  16.         char config[2] = {0x2C,0x06};
  17.         char data[6] = {0};
  18.         // 循环读取sht30数据
  19.         while(1){
  20.                 // Get I2C device, SHT30 I2C address is 0x44(68)
  21.                 ioctl(file, I2C_SLAVE, 0x44);               
  22.                 write(file, config, 2);
  23.                 sleep(1);
  24.                 // Read 6 bytes of data
  25.                 // Temp msb, Temp lsb, Temp CRC, Humididty msb, Humidity lsb, Humidity CRC        
  26.                 if(read(file, data, 6) != 6)
  27.                 {
  28.                         printf("0 0\n");
  29.                 }
  30.                 else
  31.                 {
  32.                         printf("%d %d\n",(data[0] * 256 + data[1]), (data[3] * 256 + data[14]));
  33.                 }
  34.                 fflush (stdout);
  35.                 sleep(1);
  36.         }
  37. }
复制代码

最终妥协为,SHT30使用C代码去读取,并用管道与python代码连接。其余传感器都是用python获取。
  1. # 温湿度信息由SHT30提供,使用线程 通过管道获取
  2. class Sht30(threading.Thread):
  3.     def __init__(self):
  4.         threading.Thread.__init__(self)
  5.         self.sht =Popen('sht30',shell=True,stdin=PIPE,stdout=PIPE)

  6.     def run(self):
  7.         while True:
  8.             line = self.sht.stdout.readline()
  9.             if not line:  #空则跳出
  10.                 break
  11.             # print(type(line.decode("GBK").replace('\n', '').split()),line.decode("GBK").replace('\n', '').split())
  12.             valuelist=line.decode("GBK").replace('\n', '').split()
  13.             airinfo['temperature']=-45 + (175 * int(valuelist[0]) / 65535.0)
  14.             airinfo['humidity'] = 100 * int(valuelist[0]) / 65535.0;
  15.         print("look up!!! EXIT ===")   #跳出
复制代码
酒精监测也是本项目重点关注的点。使用半导体MQ-3酒精传感器。MQ-3酒精传感器所使用的气敏材料是在清洁空气中电导率较低的二氧化锡(SnO2)。当酒精传感器所处环境中存在酒精蒸汽时,气体传感器的电导率随空气中酒精气体浓度的增加而增大。使用简单的电路即可将电导率的变化转换为与该气体浓度相对应的输出信号。由于树莓派没有ADC的电路,这里使用ADS1115,一个10位的AD转换芯片来读取MQ-3的输出。
参考着资料和网上**们的经验,使用拟合方式计算酒精浓度。公式:ppm=pow((6.467*10*V)/(5-V),(1.0/0.3962))(变量V为ADC采集到的电压值
但是通过上边公式计算出来的值的单位是PPM,如何转换为交警同志认可的酒精血液浓度,没找到相关资料,这里仅仅使用PPM来做处理,通过实际测量,10000以下仅仅是淡淡的酒精味道,当酒味稍微浓郁一些时,空气中酒精浓度的PPM就超过10000了,程序里先使用10000作为阈值。
  1. #读取其它传感器 二氧化碳传感器,酒精传感器 空气质量传感器
  2. airqualitysensor = DFRobot_AirQualitySensor()
  3. i2c = busio.I2C(board.SCL, board.SDA)
  4. ads = ADS.ADS1015(i2c)
  5. alcoholval = AnalogIn(ads, ADS.P3)    #使用P3管脚
  6. def readDevice():
  7.     #读取二氧化碳传感器  单位 PPM
  8.     co2dic=read_all()
  9.     airinfo['co2']=co2dic['co2']
  10.     #读取空气质量信息 单位 指定颗粒物类型的浓度 PM1.0 PM2.5 PM10    浓度(ug/m3)
  11.     airinfo['PM25']=airqualitysensor.read_standard()
  12.     #酒精浓度 大致为 ppm=pow((6.467*10*V)/(5-V),(1.0/0.3962)) 单位ppm
  13.     airinfo['alcohol']=pow((6.467*10*alcoholval.voltage)/(5.0-alcoholval.voltage),(1.0/0.3962))
  14.     # print("{:>5}\t{:>5.3f}".format(alcoholval.value, alcoholval.voltage))
复制代码
三、作品实物图
四、项目文档
carairinfo.zip (9.98 MB, 下载次数: 1)
五、视频

分享到:
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条