这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » 软件与操作系统 » Chaos-nano操作系统在手持式VOC检测设备上的应用

共1条 1/1 1 跳转至

Chaos-nano操作系统在手持式VOC检测设备上的应用

菜鸟
2025-11-24 18:59:47     打赏

Chaos-nano 操作系统在手持式 VOC 检测设备上的应用

产品开发背景VOC 的危害

VOC(挥发性有机化合物)是常温下易挥发的有机化学物质,广泛存在于室内装修材料(甲醛、苯)、家具板材、汽车内饰、日用化学品(清洁剂、香水)等场景中,对人体健康具有显著危害。尤其对老人与孕妇这两类特殊群体,VOC 危害更为突出

  • 孕妇:孕期免疫力较低,长期接触 VOC 可能影响胎儿正常发育,增加胎儿畸形、早产、流产的风险,其中甲醛、苯等物质已被证实具有明确的生殖毒性;

  • 老人:身体机能衰退,呼吸系统、心血管系统及肝脏肾脏功能较弱,VOC 刺激易引发呼吸道感染、头晕胸闷、血压波动等症状,长期暴露可能加重慢性疾病(如哮喘、冠心病)。

此外,VOC 还会导致室内空气质量下降,引发眼睛干涩、皮肤瘙痒等不适,影响特殊群体的日常生活质量。

产品开发的必要性

随着居民对健康重视程度的提升,老人与孕妇的居住环境安全成为家庭核心关注点,但传统 VOC 检测存在明显痛点:

  1. 专业检测机构服务价格高昂(单次检测费用数百至数千元),且检测周期长,无法满足日常高频监测需求;

  2. 大型实验室仪器体积庞大、操作复杂,老人与孕妇难以独立使用,更无法随身携带;

  3. 普通家用检测工具体积大多数续航较短,无法支撑长时间外出检测;

针对老人与孕妇群体的使用需求,需要一款可以随身携带、可以长时间工作的 VOC 检测设备;同时需要具备操作极简、数据直观、安全无辐射等核心特性。基于该思路开发面向老人与孕妇的手持式 VOC 检测设备,具有极强的现实必要性与社会价值。


产品介绍

voc.PNG

该产品以“极致便携+长续航”为核心设计目标:

  • 为了能够满足便携,在外观设计上采用了这种直径 4 cm 的圆形的外观设计;

  • 为了能够长时间工作,在器件选择上选用了低功耗的 8 位单片机 STM8L151F3 ,并且在系统软件设计上采用了 Chaos-nano 操作系统——该系统是轻量级的异步协作式操作系统,可以在任务不执行的时候阻塞任务,且可以在合适的时候进入到低功耗状态——进一步降低了产品的功耗。

产品结构

手持式 VOC 检测设备基于 Chaos-nano 操作系统与 STM8L151F3 芯片构建,针对老人与孕妇的使用习惯,采用“极简设计+核心功能聚焦”的模块化结构,核心组成包括:

  1. 硬件层

    • 控制核心:STM8L151F3 微控制器(小巧封装,降低设备体积);

    • 传感模块:高精度低功耗 VOC 传感器,温湿度传感器 SHT21;

    • 显示模块:0.95 英寸 OLED 显示屏;

    • 操作模块:一键式操作按键(仅保留开机/唤醒、显示切换 2 个核心按键,简化操作);

    • 电源模块:限于产品体积,该产品采用了 150 mAh ,并采用 usb-micro 接口(支持 5V 充电,适配家庭常用充电器);

  2. 系统层:搭载 Chaos-nano 操作系统,提供轻量化任务调度、中断处理、低功耗管理等核心功能,适配 STM8L151F3 的硬件资源限制,确保设备运行稳定、续航持久。

  3. 应用层:聚焦老人与孕妇的核心需求,包含快速检测、数据精准显示、安全报警、一键校准等功能模块,简化冗余操作,同时通过深度功耗优化,确保 150 mAh 电池支撑持续工作 8 小时以上。

核心优势:极致便携性设计

依托 150 mAh 紧凑锂电池与 STM8L151F3 芯片的小巧封装,以及轻量级的 Chaos-nano 操作系统,设备实现“口袋级便携”:

  • 尺寸:长 40 mm × 宽 40 mm × 厚 10 mm,并配有钥匙孔,便于老人与孕妇可轻松放入口袋、手提包或随身悬挂,几乎无携带负担;

  • 材质:外壳采用 ABS 塑料表面防滑处理,手感舒适,便于握持;边角圆润无棱角,避免磕碰伤害;与铝合金铝块结合,使整体不显单调;

  • 续航适配: usb-micro 接口支持充电宝、手机充电器、电脑 USB 口等多种充电方式,外出时可随时补充电量,配合 8 小时以上持续工作能力,满足全天外出检测需求(如就医、购物、探访亲友等场景)。

核心芯片:STM8L151F3 详细介绍

STM8L151F3 是意法半导体推出的超低功耗 8 位微控制器,基于 STM8 内核架构,专为电池供电的便携式智能设备设计,其特性与“150 mAh 电池+8 小时续航”的产品定位及老人、孕妇的使用需求高度适配,是设备的理想控制核心:

  • 内核与主频:采用 STM8 增强型内核,最高工作频率 16 MHz,支持 16 位乘法指令与硬件除法,指令执行效率高,可快速响应传感器数据采集、按键操作等实时任务,确保设备“开机即测、数据秒出”,无需老人与孕妇长时间等待。

  • 存储资源:内置 8 KB Flash 与 1 KB RAM,与 Chaos-nano 操作系统的轻量化设计完美匹配——内核仅占用 500 余字节 RAM,剩余内存可充分支撑传感器数据处理、报警逻辑等核心功能,无需额外扩展存储芯片,既降低设备体积与成本,又减少故障风险。

  • 运行模式(持续检测状态):16 MHz 主频下芯片自身功耗仅 240 μA/MHz(约 3.8 mA);

  • STM8L151F3 集成多种实用外设,无需额外扩展芯片,既简化设备结构、缩小体积,又降低功耗:

  • 芯片封装小巧(UFQFPN20 封装,尺寸 4 mm × 4 mm),可大幅缩小设备体积,为 150 mAh 电池的紧凑布局提供硬件基础。

系统整体框架

voc框图.PNG

系统采用“硬件驱动-操作系统-应用层”三层架构:

  1. 底层驱动层:由 STM8L15x_StdPeriph_Driver 驱动库与自定义设备驱动组成,实现 STM8L151F3 芯片外设(ADCI2CGPIO 等)及 VOC 传感器、显示模块、按键等硬件的底层控制,重点优化低功耗驱动逻辑与数据采集精度,对应代码中的 devices 目录及 stm8l15x_it.c/stm8l15x_it.h 中断处理文件。

  2. 操作系统层:即 Chaos-nano 内核(kernel 目录),负责任务调度(如“采集-处理-显示”任务优先级管理)、低功耗管理(核心功能),通过精简设计确保在 STM8L151F3 的 1 KB RAM 中高效运行,同时优化任务切换延迟与功耗控制策略,平衡续航与响应速度。

  3. 应用层:优化核心逻辑,包括:

    • 传感器快速采集(handle.c/handle.h);

    • 数据直观显示;

    • 操作逻辑简化(仅 2 个按键,开机自动检测,无操作自动休眠);

产品系统实现分析

工作流程

  • 按下开机键之后,系统进行初始化并启动开机键检测任务。当检测到开机键持续 3 s 按下后,设置电源开机并显示第一屏内容;

  • 按下切屏按键后:

    • 会触发相应的中断,在中断中启动切屏任务;

    • 当从中断返回后,调度器优先调度切屏任务;

    • 在切屏任务中会切换显示内容;

  • 上电后,系统会按照一定的延迟进行数据采集:

    • 每 1 s 启动温湿度任务采集一次温湿度,当采集到数据后刷新显示;

    • 每 1 s 启动 VOC 任务采集一次 VOC 数据,当采集到数据后刷新显示;

    • 每 2 s 启动电池任务采集一次电池的电量和充电状态,然后刷新显示;

  • 显示刷新:

    • 显示刷新没有设定单独的任务,因此显示刷新属于同步操作——这里没有采用单独的任务进行异步刷新显示;

    • 通过全局标志来判断当前处于哪个屏幕显示,当有当前屏幕的内容需要刷新时会对屏幕进行刷新,否则直接返回;

    • 电池标志在每个屏幕上都有,所以当有电池数据需要刷新时会及时刷新该部分显示;

软件实现

任务分类与优先级设定

该软件基于 IAR for STM8 开发环境,搭配 Chaos-nano 操作系统,采用“任务化”设计,将功能拆解为5个独立的任务:

  • 电源按键检测任务;

  • 切屏按键检测任务;

  • 温湿度(SHT21)检测任务;

  • VOC 检测任务;

  • 电池状态与电量检测任务;

通过基于优先级调度实现高效协同工作。

       任务 ID   任务名称                                 核心功能优先级触发方式
TASK_ID_POWER电源按键检测检测电源按键是否在规定的时间内保持按下状态0中断
TASK_ID_KEY切屏按键检测切换显示屏幕1中断
TASK_ID_SHT21温湿度检测获取温湿度检测数据2定时器
TASK_ID_TVOCVOC 检测获取 VOC 检测数据3定时器
TASK_ID_BAT电池检测检测电池的充电状态与电池电量4定时器

核心任务代码逻辑解析

  • 主调度逻辑

主函数通过 “获取下一个高优先级任务→执行任务→状态重置” 的循环,实现任务调度,核心逻辑如下:

void start_kernel(void)
{
 board_init();
 
 task_init();
 time_init();
 
 device_on();
 
 while (1)
 {
   switch (task_getNextPriority())
   {
   case TASK_ID_POWER:
     powerOnHandle();
     break;
     
   case TASK_ID_KEY:
     keyHandle();
     break;
     
   case TASK_ID_SHT21:
     Get_TempHum();
     break;
     
   case TASK_ID_TVOC:
     Get_Tvoc();
     break;
     
   case TASK_ID_BAT:
     Check_Charge_Bat();
     break;
     
   case TASK_ID_DISP:
     //bat_pic(3,50, pow_bat[1]);
     break;
     
   default:
     task_restoreAll();
     if (IDLE_PRI == task_getNextPriority())
     {
       sleep_cpu();
     }
     break;
   }
 }
}
  • 电源键检测

当按下电源按键后,会通过中断触发 TASK_ID_POWER 任务

  • 如果在电源关闭的状态下按下:该任务中会先延迟 3 s 后再次判断该按键是否保持按下状态,如果保持按钮下状态则设置相应的引脚和标志位;

  • 如果在电源开启的状态下按下:该任务中会先延迟 5 s 后再次判断该按键是否保持按下状态,如果保持按钮下状态则设置相应的引脚和标志位;

void powerOnHandle(void)
{
 static bool flag = false;
 
 if(!powerOn){
   if(!flag){
     if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3)!=RESET) {
       time_create(TASK_ID_POWER, 3000, &flag, true);
     } else {
       time_cancel(TASK_ID_POWER);
     }
   } else {
     if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3)!=RESET) {
       powerOn = true;
       GPIO_ResetBits(GPIOD, GPIO_Pin_0);
       GPIO_SetBits(GPIOA, GPIO_Pin_2);  
       curDispPageNumber = DISP_UPDATE_SHT21;
       update_disp(curDispPageNumber);
     }
   }
 } else {
   if(!flag){
     if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3)!=RESET) {
       time_create(TASK_ID_POWER, 5000, &flag, true);
     } else {
       time_cancel(TASK_ID_POWER);
     }
   } else {
     if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3)!=RESET) {
       powerOn = false;
       GPIO_SetBits(GPIOD, GPIO_Pin_0);          
       GPIO_ResetBits(GPIOA, GPIO_Pin_2);        
       curDispPageNumber = DISP_UPDATE_POWER_OFF;
       update_disp(curDispPageNumber);
     }
   }
 }
 
 task_setBlock(TASK_ID_POWER);
 flag = false;
 
 return;
}
  • 温度检测任务

当温湿度传感器初始化时,会启动一个定时器。当定时器计时结束时会触发 TASK_ID_SHT21 任务,并在该任务中获取通过 IICSHT21 中获取温湿度数据,更新屏幕显示;且启动下一延迟。

void Get_TempHum(void)
{
 if(flag){
   flag = false;
   Get_TempHum_1();
   update_disp(DISP_UPDATE_SHT21);
   time_create(TASK_ID_SHT21, DELAY_MS, &flag, true);
 }
 
 task_setBlock(TASK_ID_SHT21);
}


Chaos-nano 操作系统在开发中带来的优势

由于使用的是 8 位单片机所以产品最初是使用的是传统的软件开发方式;在 Chaos-nano 操作系统被开发后,使用 Chaos-nano 操作系统对该项目进行了重构。

新旧软件代码对比

  • 以下代码时传统模式开发中的按键处理部分:

void KeyHandle()
{
 OLED_CLS();
 while(1)
 {
   if(Sleeping==0){
     if(PowerStatus==ENABLE) //表示开机
     {
       Delay(3000);
       Check_Charge_Bat();
       Dis_Bat();
       if(page_nums==0)  {//显示温度
         my_page = 3;
         Delay(1000);
         
         if(FlagChange == ENABLE) //按下S2翻页
         {
           page_nums=1;
           OLED_CLS();
           Dis_Uin();
           FlagChange=DISABLE;
         }
         Get_TempHum();
         Check_Charge_Bat();
         Dis_Bat();
         //OLED 显示
         Dis_Data(page_nums);
         
       }else if(page_nums==1)  {//显示RH
         my_page = 0;
         Delay(1000);
         if(FlagChange == ENABLE)
         {
           page_nums=2;
           OLED_CLS();
           Check_Charge_Bat();
           FlagChange=DISABLE;
         }
         Get_TempHum();
         Check_Charge_Bat();
         //OLED 显示
         Dis_Data(page_nums);
         
       }else if(page_nums==3)  {//显示TVOC
         my_page = 2;
         Delay(1000);
         if(FlagChange == ENABLE)
         {
           page_nums=0;
           OLED_CLS();
           FlagChange=DISABLE;
         }
         Get_Tvoc();
         //OLED 显示
         Dis_Data(page_nums);
         
       }else if(page_nums==2) {//显示OC2
         my_page = 1;
         Delay(1000);
         if(FlagChange == ENABLE)
         {
           page_nums=3;
           OLED_CLS();
           Check_Charge_Bat();
           FlagChange=DISABLE;
         }
         Check_Charge_Bat();
         Get_Tvoc();
         //OLED 显示
         Dis_Data(page_nums);
       }
     } else if(PowerStatus==DISABLE)//充电状态关机
     {
       Delay(3000);
       if(FlagS==ENABLE){
         FlagChange=DISABLE;
         page_nums=0;
         FlagS=DISABLE;
         //关闭OLED屏幕
         OLED_CLS();
       }
     }
     
   }
   ScreenDispose();
   
 }
}
  • 使用 Chaos-nano 操作系统后的代码

void keyHandle(void)
{
 if(!powerOn)
   return;
 
 curDispPageNumber = (curDispPageNumber == DISP_UPDATE_SHT21) ? DISP_UPDATE_TVOC : DISP_UPDATE_SHT21;
 OLED_CLS();
 update_disp(DISP_UPDATE_BAT);
 update_disp(curDispPageNumber);
 
 task_setBlock(TASK_ID_KEY);
}

void update_disp(enum disp_update_t disp_update_number)
{
 switch(disp_update_number){
 case DISP_UPDATE_SHT21:
   {
     if(disp_update_number != curDispPageNumber)
       return;
     
     //显示温湿度
     ... ...
   }
   break;
   
 case DISP_UPDATE_TVOC:
   {
     uint16_t Tvocmg_L = 0;
     uint16_t eCO2PPM = 0;
     
     if(disp_update_number != curDispPageNumber)
       return;
     
     //显示甲醛和空气质量
     ... ...
   }
   break;
   
 case DISP_UPDATE_BAT:
   {
     if( (curDispPageNumber == DISP_UPDATE_SHT21) || (curDispPageNumber == DISP_UPDATE_TVOC) ){
       Dis_Bat(true);
     } else {
       Dis_Bat(false);
     }
   }
   break;
   
 case DISP_UPDATE_POWER_OFF:
   {
     OLED_CLS();
     Dis_Bat(true);
   }
   break;
 }
}


传统开发模式带来的问题:

  • 逻辑冗余且耦合度极高

  • 代码将按键检测、页面切换、数据采集(温湿度、TVOC)、OLED 显示、电池检测等功能 “堆叠” 在一个无限循环中,各模块职责边界模糊。例如,按键翻页逻辑与 page_nums 变量强绑定,数据采集函数(Get_TempHum()Get_Tvoc())直接嵌入页面判断分支,若需新增 “甲醛浓度单独显示” 页面,需修改整个循环结构与多个判断条件,牵一发而动全身。

  • 依赖 SleepingPowerStatusFlagChange 等全局变量进行状态控制,变量状态流转不透明,排查问题时需追溯整个代码流程,维护成本极高。

  • 阻塞式设计影响用户体验

  • 代码中大量使用 Delay(1000)Delay(3000) 等阻塞延时函数,期间 CPU 无法响应其他操作。对于用户而言,按下按键后可能需等待 1-3 秒才能完成页面切换,操作流畅度差;若在延时期间触发其他按键(如误触),设备无任何响应,易造成 “设备故障” 的误解。

  • 无限循环 while(1) 占用全部 CPU 资源,即使设备处于无操作状态,也无法进入低功耗模式,直接导致电池的续航能力大幅缩水,难以满足长时间工作的产品需求。

  • 扩展性差,适配需求变更成本高

  • 页面切换逻辑通过 page_nums 的多分支 if-else 实现,若需新增检测参数(如温湿度、TVOC 之外增加 PM2.5 显示),需新增 page_nums 枚举值、扩展判断分支、修改翻页逻辑,代码量呈线性增长,且容易引入逻辑错误。

  • 按键处理与显示、数据采集深度耦合,若需优化操作逻辑(如 “长按按键锁定数据”),需在冗长的循环中插入新的判断条件,破坏原有代码结构。

使用 Chaos-nano 操作系统后的代码优势

  • 模块化拆分,职责单一清晰

    • 将原代码拆分为 “按键处理(keyHandle())” 与 “显示更新(update_disp())” 两大独立模块,按键仅负责触发页面切换,显示仅负责根据页面类型更新内容,数据采集可独立封装为任务,各模块通过 curDispPageNumber 枚举变量通信,职责边界明确。

    • 采用枚举 enum disp_update_t 定义显示类型(DISP_UPDATE_SHT21DISP_UPDATE_TVOC 等),新增页面时仅需扩展枚举值与 update_disp() 中的 switch 分支,无需修改按键处理逻辑,扩展性极强。例如,新增 “甲醛显示” 页面,仅需添加 DISP_UPDATE_FORMALDEHYDE 枚举项与对应的显示分支,代码改动量不足 10 行。

  • 非阻塞式设计,适配特殊群体操作需求

    • 彻底摒弃阻塞延时,借助 Chaos-nano 的任务调度机制实现异步处理。按键按下后,keyHandle() 仅完成 “页面序号切换→触发显示更新→任务阻塞” 的核心逻辑,无需等待;数据采集、OLED 刷新等耗时操作可由独立任务异步执行,用户按下按键后瞬间完成页面切换,无延迟感,操作体验更流畅。

    • 通过 task_setBlock(TASK_ID_KEY) 函数将按键任务阻塞,避免短时间内重复触发,同时释放 CPU 资源供其他任务(如低功耗管理、数据校准)使用。配合 Chaos-nano 的低功耗调度,设备无操作时可快速进入休眠模式,最大化延长电池的续航时间。

  • 状态管理透明,维护效率大幅提升

    • 页面状态通过 curDispPageNumber 枚举变量统一管理,取值范围明确(仅对应已定义的显示类型),避免了裸机代码中全局变量状态混乱的问题。例如,update_disp() 函数通过判断枚举值直接定位显示逻辑,无需追溯全局变量的修改记录。

    • 逻辑分支从 4 个 if-else 简化为 1 个 switch 语句,可读性极强。开发人员无需理解复杂的循环嵌套与延时逻辑,即可快速定位问题或进行功能扩展,大幅缩短产品迭代周期。

  • 低耦合设计,适配产品功能迭代

    • 按键处理与数据采集、显示逻辑完全解耦。若需优化用户使用体验(如 “默认显示 TVOC 浓度,减少翻页操作”),仅需修改 curDispPageNumber 的初始值;若需调整电池显示逻辑,仅需修改 update_disp() 中的 DISP_UPDATE_BAT 分支,不影响其他功能模块。

    • 依托 Chaos-nano 的任务管理能力,可轻松新增独立任务(如 “低电量报警”“一键校准”),无需担心与原有按键、显示逻辑冲突。例如,新增 “校准任务” 时,仅需创建新任务并添加新功能的代码,原有代码无需改动。


Chaos-nano 带来的核心价值总结

对于本项目而言,Chaos-nano 不仅是 “让代码更简洁”,更是通过架构革新实现了三大核心价值:

1. 提升产品易用性

非阻塞式设计消除了按键操作的延迟感,模块化逻辑保障了设备运行的稳定性,让老人与孕妇 “一键操作、即刻响应” 的核心需求得到充分满足,降低了特殊群体的使用门槛。

2. 降低开发与维护成本,加速产品迭代

简洁的代码结构、清晰的模块划分,让开发人员无需花费大量时间梳理逻辑关系,新增功能、修改需求时的代码改动量减少 60% 以上,显著缩短产品开发周期与维护成本。

3. 释放硬件潜力,保障核心产品特性

Chaos-nano 的低功耗调度机制,配合非阻塞式代码设计,同时确保设备体积小巧、重量轻盈,完美实现 “极致便携 + 长续航” 的产品定位。

综上,Chaos-nano 操作系统通过对传统裸机代码的架构重构,解决了逻辑冗余、耦合度高、扩展性差等痛点,同时为开发团队提供了高效、灵活的开发框架,成为产品核心竞争力的重要支撑。


代码位置https://gitee.com/kongrong77/Chaos-nano/tree/main/examples/nose_chaos_nano

产品视频

voc.gif





关键词: Chaos-nano     操作系统     mcu     嵌入式操作    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]