1、扫地机系统概述:从硬件到软件的完整拼图

做扫地机嵌入式开发这些年,我最大的感受就是——这玩意儿看着简单,实际上是个系统工程。你想想看,一个巴掌大的机器,要同时处理传感器数据、控制电机、管理电池、跑算法,还得保证实时性。嗯,今天我们就从硬件架构开始,一层层把这块拼图拼完整。

1.1 硬件架构:扫地机的"骨骼"与"感官"

先说说硬件。我习惯把扫地机的硬件分成四大块:大脑(MCU)、感官(传感器)、手脚(电机)、能量(电池)。这四块缺一不可,配合不好就容易出问题。

MCU选型:不是越强越好

MCU是核心,但选型有讲究。我个人习惯看三点:算力、外设资源、功耗。举个例子,我做过一个项目,一开始选了STM32F103,结果发现同时处理激光雷达数据和SLAM算法时,CPU占用率飙到90%以上。后来换了STM32F407,带FPU,浮点运算快了不少。

常见的MCU选型方案:

芯片型号 内核 主频 适用场景
STM32F103 Cortex-M3 72MHz 基础扫地机(无SLAM)
STM32F407 Cortex-M4 168MHz 中端扫地机(带简单SLAM)
STM32H743 Cortex-M7 480MHz 高端扫地机(激光+视觉融合)
国产GD32F450 Cortex-M4 200MHz 性价比方案
我的经验:别一味追求高主频。我见过有人用H743做基础扫地机,结果功耗高、发热大,电池续航反而短了。选型要匹配实际需求。

传感器:扫地机的"眼睛"和"耳朵"

传感器这块,种类多、接口杂。我整理了一下常见的:

  • 激光雷达(LDS):UART接口,数据量较大,需要DMA接收。我遇到过数据丢包的问题,后来加了环形缓冲区才解决。
  • 陀螺仪/加速度计(IMU):I2C或SPI接口,用于姿态估计。注意,IMU数据有温漂,需要做校准。
  • 碰撞传感器:GPIO中断,简单但重要。我曾经因为没做消抖处理,导致机器在门槛处反复碰撞。
  • 悬崖传感器:红外或超声波,ADC采样。这里有个坑——不同地面反射率不同,阈值要动态调整。
  • 里程计(轮速计):编码器输入,用于定位。精度取决于编码器线数和轮径校准。
避坑指南:我曾经在一个项目里,激光雷达和IMU共用同一个UART DMA通道,结果数据互相干扰,定位直接飘了。后来老老实实分开用独立DMA,问题解决。记住:传感器数据通道要隔离。

电机与驱动:动力系统的"肌肉"

电机一般用直流有刷电机或无刷电机。驱动方式有两种:

  • H桥驱动:用PWM控制方向和速度。注意死区时间设置,否则容易烧MOS管。
  • 专用驱动芯片:比如DRV8833,集成度高,但要注意散热。

我习惯在电机驱动上加电流采样,用来做堵转检测和负载判断。你想想看,如果机器卡在地毯边缘,电机电流会突然增大,这时候及时停止能避免烧电机。

电池管理:续航的"心脏"

电池这块,锂电池是主流。需要关注三点:

  1. 电量检测:用ADC采样电池电压,但要注意——电池放电曲线不是线性的。我做过一个简单的查表法,精度在5%以内,够用了。
  2. 充电管理:用专用芯片如TP4056,注意充电电流不要超过电池规格。
  3. 低电量保护:电压低于阈值时,强制回充。我曾经因为阈值设得太低,导致电池过放,直接报废了一块电池。

1.2 软件架构分层:把复杂问题拆解

硬件搭好了,软件怎么组织?我推荐分层架构。说白了,就是把代码按职责拆开,每层只管自己的事。这样好处很明显:好维护、好测试、好移植。

我常用的分层方式:

层级 职责 典型模块
应用层 业务逻辑、决策 路径规划、避障策略、回充逻辑
中间件层 算法封装、数据融合 SLAM、卡尔曼滤波、PID控制
驱动层 硬件抽象、寄存器操作 GPIO、UART、I2C、PWM驱动

举个例子,驱动层只负责"读传感器数据"和"写电机PWM"。中间件层拿到数据后做滤波和融合。应用层只管"前方有障碍物,左转"。这样每层改动不影响其他层。

核心原则:驱动层不要写业务逻辑,应用层不要直接操作寄存器。我见过有人把避障逻辑写在GPIO中断里,结果改个传感器型号,整个代码都要重写。

1.3 实时操作系统选型:FreeRTOS vs RT-Thread

要不要上RTOS?我的答案是:必须上。扫地机有多个并发任务——传感器采集、电机控制、算法运算、通信处理。用裸机轮询,你想想看,一个传感器采集卡住了,整个系统就瘫痪了。

选哪个?我两个都用过,说说感受。

FreeRTOS:轻量、稳定、生态好

  • 优点:代码量小,RAM占用低,适合资源受限的MCU。文档齐全,网上资料多。
  • 缺点:功能相对基础,没有设备框架,需要自己封装驱动。
  • 适用场景:RAM小于64KB、Flash小于256KB的MCU。

RT-Thread:功能丰富、组件化

  • 优点:有设备驱动框架、文件系统、网络协议栈,开箱即用。支持动态加载模块。
  • 缺点:代码量大,对RAM要求高。学习曲线稍陡。
  • 适用场景:RAM大于128KB、需要复杂功能的中高端MCU。

我个人习惯:小项目用FreeRTOS,大项目用RT-Thread。举个例子,一个只有激光雷达和基础避障的扫地机,FreeRTOS完全够用。但如果要加视觉识别、语音控制、OTA升级,RT-Thread的组件生态能省不少事。

我的建议:如果你刚接触RTOS,先从FreeRTOS入手。它简单、直观,能帮你快速理解任务调度、信号量、消息队列这些概念。等用熟了,再尝试RT-Thread。

任务划分示例(FreeRTOS)

我一般这样划分任务:

// 任务优先级定义
#define TASK_SENSOR_PRIO     3   // 传感器采集,最高优先级
#define TASK_MOTOR_PRIO      2   // 电机控制
#define TASK_ALGO_PRIO       1   // 算法运算
#define TASK_COMM_PRIO       0   // 通信处理,最低优先级

// 任务创建
xTaskCreate(sensor_task, "Sensor", 256, NULL, TASK_SENSOR_PRIO, NULL);
xTaskCreate(motor_task,   "Motor",  128, NULL, TASK_MOTOR_PRIO,  NULL);
xTaskCreate(algo_task,    "Algo",   512, NULL, TASK_ALGO_PRIO,   NULL);
xTaskCreate(comm_task,    "Comm",   256, NULL, TASK_COMM_PRIO,   NULL);

注意看,传感器任务优先级最高,因为数据要实时采集。算法任务栈空间最大,因为SLAM运算需要大量局部变量。通信任务优先级最低,丢几条日志无所谓。

避坑指南:我曾经把电机控制任务的优先级设得比传感器还高,结果传感器数据采集不及时,定位误差越来越大。记住:数据采集 > 控制执行 > 算法运算 > 通信,这个优先级顺序一般不会错。

小结

好了,这一章我们聊了扫地机的硬件架构、软件分层和RTOS选型。说白了,就是搞清楚"用什么芯片、怎么组织代码、用什么系统"。下一章我们会深入驱动层,讲讲具体怎么写传感器驱动和电机控制。嗯,到时候我会分享一些实际项目中的踩坑经验,敬请期待。