系统架构设计:硬件架构与软件分层
好,咱们进入第二章。系统架构设计,说白了就是给分拣机画一张「施工蓝图」。我做了这么多年嵌入式,见过太多项目一上来就写代码,写到一半发现引脚不够用、电源带不动、状态机乱成一锅粥。嗯,咱们今天就把这事聊透。
一、硬件架构:五大模块怎么搭
分拣机的硬件,我习惯拆成五个部分:电源、主控、驱动、传感、通信。你想想看,这就像人的身体——电源是心脏,主控是大脑,驱动是肌肉,传感是感官,通信是神经。
1. 电源模块
电源设计,我吃过不少亏。有一次项目里用了便宜的DC-DC模块,结果电机一启动,主控直接复位。后来查了半天,是电源纹波太大。
- 主控:3.3V(数字核心)
- 电机驱动:12V-24V(动力部分)
- 传感器:5V(模拟部分)
- 通信模块:3.3V或1.8V
我个人习惯在电源入口加一个TVS管,再串一个自恢复保险丝。别省这个钱,我曾经因为没加TVS,雷雨天气烧了三块板子。
2. 主控模块
主控选型,我建议看三点:
- 外设数量:至少2路UART(一路给触摸屏,一路给上位机),3路定时器(PWM输出),1路SPI(给传感器)
- 处理能力:分拣机不需要跑Linux,STM32F4系列或者国产GD32F4系列足够了
- 引脚余量:留20%的GPIO做扩展,你永远不知道客户会加什么功能
我最近一个项目用的GD32F407,主频200MHz,跑FreeRTOS,带6个电机和8个传感器,绰绰有余。
3. 驱动模块
电机驱动是分拣机的核心。分拣机一般用步进电机或者直流有刷电机。
| 电机类型 | 驱动芯片 | 控制方式 | 适用场景 |
|---|---|---|---|
| 步进电机 | DRV8825 / A4988 | 脉冲+方向 | 精准定位(分拣臂) |
| 直流有刷 | L298N / TB6612 | PWM+方向 | 传送带 |
| 无刷电机 | ESC(电子调速器) | PWM信号 | 高速旋转(离心分拣) |
驱动电路要注意加续流二极管和光耦隔离。我之前偷懒没加光耦,电机启停时主控直接死机——教训啊。
4. 传感模块
分拣机常用的传感器:
- 光电传感器:检测物体有无,我用E3Z系列的,稳定
- 颜色传感器:TCS34725,I2C接口,分拣颜色用
- 称重传感器:HX711+应变片,分拣重量用
- 限位开关:机械式或者霍尔式,做原点定位
传感器布线要注意屏蔽。我遇到过传感器数据跳变,后来发现是电机线跟信号线走一起了。分开走线,加磁环,问题解决。
5. 通信模块
分拣机一般需要跟PLC或者MES系统通信。常用方案:
- RS485:工业现场最稳,Modbus协议,距离1000米没问题
- CAN总线:实时性高,适合多机协同
- 以太网:数据量大,但成本高
- WiFi/蓝牙:调试用可以,工业现场不推荐
二、软件架构:三层分离,各司其职
软件架构我坚持分层设计。为什么?因为不分层的代码,三个月后你自己都看不懂。我接手过一个项目,所有逻辑写在一个main.c里,5000行,改一个bug要花三天。
1. 驱动层
驱动层直接操作硬件寄存器。说白了,就是给上层提供API。
// 驱动层示例:步进电机驱动
void stepper_init(void);
void stepper_set_speed(uint16_t rpm);
void stepper_move_steps(int32_t steps);
uint8_t stepper_get_status(void);
驱动层要做的:
- 初始化外设时钟、GPIO、定时器
- 提供硬件抽象接口
- 处理中断服务函数
注意:驱动层不要加业务逻辑。我曾经看到有人在驱动层写分拣算法,那叫一个乱。
2. 中间件层
中间件层是承上启下的。它封装了常用的功能模块:
- FreeRTOS:任务调度、信号量、消息队列
- 协议栈:Modbus从站协议、自定义通信协议
- 算法库:PID控制、滤波算法、颜色识别
- 日志系统:环形缓冲区、串口打印
中间件层的好处是:换主控芯片时,只需要改驱动层,中间件和应用层基本不动。
3. 应用层
应用层就是业务逻辑。分拣机的应用层包括:
- 状态机管理(下面细说)
- 用户交互(按键、触摸屏)
- 分拣策略(按颜色、按重量、按形状)
- 异常处理(卡料、缺料、过载)
三、状态机设计:分拣机的灵魂
状态机,说白了就是分拣机的大脑。它决定了机器在什么条件下做什么事。我见过太多人用一堆if-else来写状态逻辑,结果状态一多,代码就成了一团乱麻。
状态机的基本要素
一个完整的状态机包含:
- 状态:机器当前处于什么阶段
- 事件:触发状态切换的条件
- 动作:进入/退出状态时执行的操作
- 转移:状态之间的跳转规则
分拣机的典型状态
我设计的分拣机状态机一般包含以下状态:
typedef enum {
STATE_IDLE, // 空闲等待
STATE_DETECT, // 检测物料
STATE_CLASSIFY, // 分类判断
STATE_SORT, // 执行分拣
STATE_ERROR, // 错误处理
STATE_CALIBRATE // 校准模式
} SorterState;
状态转移图
状态转移的逻辑:
- IDLE → DETECT:传感器检测到物料
- DETECT → CLASSIFY:物料信息采集完成
- CLASSIFY → SORT:分类结果确定
- SORT → IDLE:分拣动作完成
- 任何状态 → ERROR:出现异常(卡料、超时)
- ERROR → IDLE:手动复位或自动恢复
代码实现示例
void sorter_task(void *param) {
SorterEvent event;
while(1) {
event = get_next_event(); // 从队列获取事件
switch(current_state) {
case STATE_IDLE:
if(event == EVT_DETECT) {
motor_start(); // 动作
current_state = STATE_DETECT;
}
break;
case STATE_DETECT:
if(event == EVT_DATA_READY) {
classify_material(); // 动作
current_state = STATE_CLASSIFY;
} else if(event == EVT_TIMEOUT) {
current_state = STATE_ERROR;
}
break;
// ... 其他状态处理
}
}
}
状态机设计要点
- 状态要正交:每个状态只做一件事,不要一个状态既检测又分拣
- 事件要明确:事件来源要清晰(传感器、定时器、通信、用户)
- 要有默认处理:switch语句一定要加default,处理未定义事件
- 状态机可视化:我习惯先画状态转移图,再写代码。用draw.io或者手画都行
好了,系统架构设计就聊到这儿。硬件架构是骨架,软件分层是肌肉,状态机是灵魂。三者缺一不可。下一章咱们开始讲具体的硬件选型和电路设计,到时候我会把踩过的坑一个一个说给你听。