一、项目名称:
基于Teensy4.1的车内环境质量监控器
二、项目概述:
本项目旨在开发一款智能车内环境质量监控器,基于高性能的Teensy 4.1微控制器,结合瑞萨 RRH62000多合一环境传感器,实时监测车内的温湿度、颗粒物浓度(PM1/PM2.5/PM10)、eCO2(等效二氧化碳浓度)、TVOC(总挥发性有机化合物)以及空气质量指数(AQI)等关键环境参数。所有数据通过3.5寸LCD触摸屏显示,界面基于LVGL图形库设计,提供直观、美观的用户交互体验。
本项目不仅是一款实用的车内环境监控设备,更是一个可扩展的智能平台,未来可通过软硬件升级,满足更多场景需求。通过实时监测和智能提示,帮助用户打造更健康、更舒适的车内环境。
核心功能
多参数环境监测:
实时采集车内温湿度、颗粒物浓度、eCO2、TVOC及空气质量指数。
通过RRH62000传感器的高精度检测,确保数据的准确性和可靠性。
直观的GUI界面:
基于LVGL设计的图形用户界面,支持触摸操作。
主界面显示所有参数的实时数值,辅以图标、颜色和动态效果,提升用户体验。
报警与提示功能:
当某项环境参数超出预设安全范围时,系统会通过屏幕信息警告、LED指示灯发出提示。
数据存储与导出:
LCD屏模块板载TF卡座,可将环境数据存储至TF卡,便于**分析与导出。
三、作品实物图
硬件设计
主控芯片:Teensy 4.1
板载NXP的高性能ARM Cortex-M7处理器RT1062,主频高达600MHz,满足多任务处理需求。
丰富的外设接口(I2C、SPI、UART等),便于连接传感器和显示屏。
环境传感器:瑞萨 RRH62000
集成温湿度、颗粒物、eCO2、TVOC等多种检测功能,减少硬件复杂度。
显示模块:DFROBOT 的3.5寸LCD触摸屏
分辨率320x480,支持触控操作。
使用LVGL库实现流畅的图形界面和交互逻辑。
扩展功能模块:
根据环境数据,可主动或自动调节车内空调或空气净化器。
可控制车内灯光。
软件设计
1.LVGL图形界面:
-设计简洁美观的主界面,实时显示各项环境参数。
-支持多级菜单,用户可查看历史数据、设置报警阈值等。
2.数据采集与处理:
-定时从RRH62000传感器读取数据,并进行滤波和校准。
-通过算法计算空气质量指数(AQI),提供更直观的环境评估。
3.扩展控制:
-实时监测环境参数,根据环境数据,可主动调节车内空调或空气净化器。
-支持用户控制车内照明灯光。
项目亮点
1.高集成度:
-采用多合一环境传感器,减少硬件复杂度,降低成本。
-Teensy 4.1强大的处理能力支持多任务并行处理。
2.用户友好:
-基于LVGL的图形界面,操作直观,支持触摸交互。
-提供实时数据和报警提示,满足用户多样化需求。
3.可扩展性强:
-支持自动控制等扩展功能。
-模块化设计,便于**功能升级和维护。
4.实用性与环保:
-帮助用户实时了解车内环境质量,提升驾驶舒适性和健康保障。
-通过数据分析和提示,促进用户改善车内环境,减少污染。
本项目基于arduino开发。部分软件代码如下:
#include <TimerOne.h>
#include <ILI9488_t3.h>
#include <lvgl.h>
#include "src/gui_guider.h"
#include "src/events_init.h"
#include "src/custom.h"
#include "RRH62000.h"
RRH62000 rrh=RRH62000(&Wire2);
#define SCREEN_WIDTH 480
#define SCREEN_HEIGHT 320
ILI9488_t3 tft = ILI9488_t3(&SPI, 10, 40, 41);
static lv_disp_draw_buf_t disp_buf;
static lv_color_t buff[SCREEN_WIDTH * 10];
static void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
uint32_t w = (area->x2 - area->x1 + 1);
uint32_t h = (area->y2 - area->y1 + 1);
tft.writeRect(area->x1,area->y1,w,h,(const unsigned uint16_t*)&color_p->full);
lv_disp_flush_ready(disp);
}
void timer_callback(void)
{
lv_tick_inc(5);
}
extern "C"
{
float RRH62000_getTemperature()
{
float t = rrh.getTemperature();
Serial.println(String(t));
return t;
}
float RRH62000_getHumidity()
{
float rh =rrh.getHumidity();
Serial.println(String(rh));
return rh;
}
float RRH62000_getPM1()
{
float dat =rrh.getPM1();
Serial.println(String(dat));
return dat;
}
float RRH62000_getPM2_5()
{
float dat =rrh.getPM2_5();
Serial.println(String(dat));
return dat;
}
float RRH62000_getPM10()
{
float dat =rrh.getPM10();
Serial.println(String(dat));
return dat;
}
float RRH62000_getPM1_smoke()
{
float dat =rrh.getPM1_smoke();
Serial.println(String(dat));
return dat;
}
float RRH62000_getPM2_5_smoke()
{
float dat =rrh.getPM2_5_smoke();
Serial.println(String(dat));
return dat;
}
float RRH62000_getPM10_smoke()
{
float dat =rrh.getPM10_smoke();
Serial.println(String(dat));
return dat;
}
float RRH62000_getIAQ()
{
float dat =rrh.getIAQ();
Serial.println(String(dat));
return dat;
}
float RRH62000_getTVOC()
{
float dat =rrh.getTVOC();
Serial.println(String(dat));
return dat;
}
float RRH62000_getECO2()
{
float dat =rrh.getECO2();
Serial.println(String(dat));
return dat;
}
}
lv_ui guider_ui;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
tft.begin();
tft.setRotation(1); // 180
rrh.begin(); // Start RRH62000
lv_init();
lv_disp_draw_buf_init(&disp_buf, buff, NULL, SCREEN_WIDTH * 10);
/*Initialize the display*/
static lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
/*Set the resolution of the display*/
disp_drv.hor_res = SCREEN_WIDTH;
disp_drv.ver_res = SCREEN_HEIGHT;
/*Used to copy the buffer's content to the display*/
disp_drv.flush_cb = my_disp_flush;
/*Set a display buffer*/
disp_drv.draw_buf = &disp_buf;
/*Finally register the driver*/
lv_disp_drv_register(&disp_drv);
static lv_indev_drv_t indev_drv;
/*Register a touchpad input device*/
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = my_touchpad_read;
lv_indev_drv_register(&indev_drv);
setup_ui(&guider_ui);
events_init(&guider_ui);
custom_init(&guider_ui);
Timer1.initialize(5000);
Timer1.attachInterrupt(timer_callback); // blinkLED to run every 0.15 seconds
}
void loop() {
// put your main code here, to run repeatedly:
rrh.refreshData(); // collect new data from RRH62000
lv_task_handler(); /* let the GUI do its work */
delay(5);
}
视频与资料:
参见附件