FEATURED · 精选文章

蓝桥杯智能物料传送系统设计:从TCS3200颜色识别到电机控制全解析

发布时间 / 2026/8/28 3:49:10
来源 / 创域科博编辑部
栏目 / 资讯中心
蓝桥杯智能物料传送系统设计:从TCS3200颜色识别到电机控制全解析 1. 项目概述与赛题解析“智能物料传送”这个题目听起来就很有工业自动化的味道。没错这正是2015年第六届蓝桥杯全国大学生单片机设计与开发大赛的国赛题目。对于经历过那个时期的电子类学生来说这道题堪称经典它完美地将单片机基础、传感器应用、电机控制和系统集成思维融合在了一起。题目要求你设计一个模拟的智能物料传送系统核心任务是通过单片机控制传送带将不同颜色的“物料”通常用色块模拟识别、分拣并传送到指定的位置。这不仅仅是写几行代码让电机转起来那么简单它考察的是你对整个嵌入式系统从感知、决策到执行的全链路理解与实现能力。当时很多同学拿到题目第一反应是“用哪个传感器识别颜色”“电机怎么驱动”。但更深层次的挑战在于如何让这几个看似独立的模块颜色识别、电机驱动、位置检测协同工作稳定、准确、实时地完成整个分拣流程。系统需要在有限的内存和算力下当时主流是51内核或STM32F103处理传感器的模拟/数字信号做出快速判断并精确控制步进或直流电机的启停和转速。这中间任何一个环节的延时或误差都可能导致物料分拣失败。所以这道题既是基础技能的试金石也是工程化思维的练兵场。无论你是刚入门单片机的新手还是有一定项目经验的爱好者深入剖析这个赛题都能让你对嵌入式系统设计有更体系化的认识。2. 系统整体设计与核心思路拆解2.1 需求分析与功能定义首先我们必须把赛题描述转化为清晰的技术指标。一个典型的“智能物料传送系统”通常包含以下核心功能点物料检测与上料系统需要知道是否有物料被放置到传送带的起始端。这通常通过一个光电传感器或微动开关来实现作为整个流程的触发信号。颜色识别这是系统的“眼睛”。物料比如木块的某个表面贴有不同颜色的贴纸如红、绿、蓝。系统需要在物料经过识别区域时快速、准确地判断出其颜色。精确定位与传送控制传送带由电机驱动。系统需要知道物料当前走到了哪个位置以便在正确的分拣点将其推出。这就要求对传送带的位移进行测量或估算。物料分拣执行根据识别出的颜色在对应的分拣位置通过舵机、电磁铁或另一个小型电机将物料从传送带上推入指定的收集槽。人机交互与状态显示需要有一个界面如LCD屏幕来显示当前模式、识别出的颜色、分拣计数等信息。同时按键用于启动、停止、模式切换等控制。把这些功能点串联起来就形成了一个完整的控制闭环上料检测触发 - 启动传送带 - 到达颜色识别区进行识别 - 根据识别结果和位移计算控制传送带运行到指定分拣点 - 触发分拣机构动作 - 完成分拣循环或等待下一次上料。2.2 硬件平台选型与核心模块设计2015年的国赛官方指定的主控芯片通常是基于8051内核的IAP15F2K61S2蓝桥杯竞赛专用板或类似的STC15系列单片机。也有赛区可能使用STM32。这里我们以更经典的51内核平台为例进行拆解其思路对于STM32同样具有参考价值。主控芯片MCUIAP15F2K61S2。它的资源决定了我们的设计边界大约8K RAM61K Flash速度比传统89C51快很多。没有硬件浮点单元所以算法要尽量用整数运算。拥有多个定时器、串口、ADC和PWM资源这为我们驱动各类外设提供了基础。核心外设模块选型与设计思路颜色识别模块这是系统的核心传感器。常见方案有TCS3200颜色传感器这是当年的首选甚至可以说是“标配”。它内部集成了RGB滤光片阵列和频率输出电路可以直接输出与光强成比例的方波频率。单片机通过测量其OUT引脚在固定时间内的脉冲数即频率来反推RGB分量值。其优点是电路简单编程直观用定时器捕获或外部中断计数。缺点是受环境光影响较大需要校准且不同颜色的频率范围需要事先测定。三路光敏电阻/光电二极管滤光片这是一种分立元件方案。用红、绿、蓝三个LED作为光源分别点亮并用对应的光敏元件接收反射光。通过ADC读取三路电压值来判断颜色。这种方案成本低但电路调试复杂稳定性相对较差在竞赛的紧张环境下不是最优选。方案选择理由对于竞赛场景稳定、易用、资料丰富是关键。TCS3200有大量的成熟代码和调试经验可供参考能极大降低开发风险。因此绝大多数队伍都会选择TCS3200。我们需要做的就是设计一个遮光结构来减少环境光干扰并编写稳健的频率测量和颜色判据算法。电机驱动与位移检测模块传送带驱动通常使用直流减速电机。为了控制其启停和调速需要电机驱动芯片如L298N或TB6612FNG。L298N更经典但发热大TB6612FNG效率高体积小是更好的选择。单片机通过PWM波控制电机速度通过IO口控制方向。位移检测这是实现精确定位的关键。单纯靠时间估算位移会因电机转速波动、皮带打滑而累积误差。必须引入位置反馈。最常用的方案是槽型光电传感器光电对管。在传送带侧面安装一个镂空码盘电机转动时码盘穿过光电对管产生脉冲。单片机通过计数脉冲数就能知道皮带走了多少距离。例如码盘一圈20个孔皮带轮周长10厘米那么每计数一个脉冲皮带就前进0.5厘米。这个方案成本低可靠性高。分拣执行机构通常使用舵机Servo。舵机可以精确控制角度通过连杆机构将旋转运动转化为直线推动把物料推下传送带。单片机通过产生一个周期为20ms、高电平宽度在0.5ms-2.5ms之间的PWM信号来控制舵机角度。选择舵机是因为它接口简单一根信号线位置控制无需额外反馈且力矩足够。人机交互模块显示常用LCD1602字符液晶屏。用于显示“状态运行”、“颜色红色”、“红色计数5”等信息。其并行接口编程简单但占用IO口多11个。如果IO口紧张可以考虑使用I2C接口的LCD1602转接板只需2个IO口。输入独立按键或矩阵键盘。用于启动、停止、复位计数等。2.3 软件架构与流程设计软件上我们需要采用一个清晰的架构来管理这些并发的任务。对于51单片机虽然跑不了RTOS但可以通过“前后台系统超级循环中断”的模式来构建。后台主循环处理实时性要求不高的任务。比如扫描按键更新系统状态运行/停止。刷新LCD显示内容。根据颜色识别结果和脉冲计数判断是否到达分拣点并设置分拣标志。前台中断服务程序处理实时性要求高的关键事件。定时器中断系统的“心跳”。用于产生精确的延时、PWM信号控制舵机、定时扫描TCS3200等。外部中断/定时器捕获用于捕获槽型光电传感器的脉冲进行位移计数。这是定位精度的基础必须用中断来确保不丢失脉冲。外部中断/计数器用于测量TCS3200的输出频率。可以将TCS3200的OUT引脚接到单片机的外部中断引脚在固定闸门时间如100ms内计数脉冲个数。主程序流程图的核心逻辑如下系统初始化配置IO口、定时器、中断、ADC、LCD等。进入主循环。检测“上料传感器”是否有信号。一旦有信号启动传送带电机PWM输出。物料运动触发槽型光电传感器脉冲中断程序累加脉冲计数。当脉冲计数达到“颜色识别区”位置时启动颜色识别流程例如停止电机短暂时间或者直接在运动中连续采样TCS3200。颜色识别算法得出结果红/绿/蓝并记录该物料对应的目标分拣点位置脉冲数。传送带继续运行持续比较当前脉冲计数与目标分拣点脉冲数。当两者相等或进入一个误差范围时停止传送带电机控制对应颜色的舵机动作完成分拣。舵机归位传送带反转或等待下一次上料计数清零或显示累加。3. 核心模块的硬件连接与软件驱动实现3.1 TCS3200颜色传感器的驱动与校准TCS3200的引脚不多但连接和配置有讲究。硬件连接VCC、GND接5V和地。S0、S1用于选择输出频率分频比。通常设置为S01, S10对应2%分频这样输出频率在几KHz到几十KHz便于单片机测量。S2、S3用于选择滤光片类型。我们需要循环设置S20, S30选择红色滤光片。S20, S31选择蓝色滤光片。S21, S30选择无滤光片清除。S21, S31选择绿色滤光片。OUT频率输出引脚。连接到单片机的一个具有外部中断或定时器捕获功能的IO口如INT0。软件驱动与测量颜色识别的本质是依次让传感器通过红、绿、蓝滤光片读取数据得到三个分量值R, G, B。// 伪代码示例 unsigned long get_filter_frequency(unsigned char s2, unsigned char s3) { set_s2_s3(s2, s3); // 设置S2, S3选择滤光片 delay_ms(10); // 等待传感器稳定这个时间很关键太短读数不稳 clear_pulse_count(); // 清零脉冲计数器 enable_counter(); // 启动计数如开启外部中断 delay_ms(100); // 设置一个固定的“闸门时间”例如100ms disable_counter(); // 停止计数 return pulse_count; // 返回计数值即频率的相对大小 } void identify_color(void) { unsigned long R, G, B; R get_filter_frequency(0, 0); // 红色滤光片读数 delay_ms(5); G get_filter_frequency(1, 1); // 绿色滤光片读数 delay_ms(5); B get_filter_frequency(0, 1); // 蓝色滤光片读数 // 识别逻辑不是看绝对值而是看相对大小 if ( (R G) (R B) (R/G 1.5) (R/B 1.5) ) { // 红色分量显著大于绿和蓝 current_color COLOR_RED; } else if ( (G R) (G B) (G/R 1.5) (G/B 1.5) ) { current_color COLOR_GREEN; } else if ( (B R) (B G) (B/R 1.5) (B/G 1.5) ) { current_color COLOR_BLUE; } else { current_color COLOR_UNKNOWN; } }注意这里的1.5只是一个示例阈值实际值必须在你的具体环境下用标准色块进行校准获得。校准方法是分别测量红、绿、蓝色块的R,G,B值记录下它们之间的比例关系。环境光一变这个比例关系相对稳定而绝对值会变所以用比例判断比用绝对值判断更可靠。3.2 基于槽型光电传感器的位移测量位移测量的精度直接决定了分拣的准确率。硬件连接槽型光电传感器的输出端通常是集电极开路输出接一个上拉电阻如10K到VCC然后连接到单片机的外部中断引脚如INT1。当码盘遮挡时输出高电平透光时输出低电平或相反取决于具体传感器。我们配置中断在下降沿或上升沿触发。软件实现volatile unsigned long distance_pulse_count 0; // 必须在中断中修改的变量用volatile // 外部中断1服务程序假设传感器接INT1下降沿触发 void EXTI1_ISR(void) interrupt 2 { distance_pulse_count; // 每触发一次中断脉冲计数加1 } // 在主循环中根据脉冲数计算位移 unsigned long get_current_distance_mm(void) { // 假设码盘一圈20个孔皮带轮周长100mm // 则每脉冲对应距离 100mm / 20 5mm const unsigned long mm_per_pulse 5; return distance_pulse_count * mm_per_pulse; } // 判断是否到达目标位置 if (get_current_distance_mm() target_distance_mm) { stop_motor(); trigger_sorting(); }实操心得码盘的安装至关重要。必须确保码盘与轴同心且在传感器槽中转动平稳无晃动。否则会产生抖动引发多次误触发。可以在中断服务程序里加入简单的软件去抖例如中断触发后关闭该中断一段时间如2ms再重新开启可以有效滤除机械抖动产生的毛刺。3.3 直流电机PWM调速与舵机控制直流电机PWM调速以TB6612为例TB6612FNG有两个电机通道A和B我们用一个。需要连接VM电机电源7-12V。VCC逻辑电源5V。GND共地。AIN1,AIN2控制电机方向。例如AIN11, AIN20正转反之反转。PWMA接单片机的PWM输出引脚如P1.3利用定时器产生PWM。// 定时器初始化产生PWM假设使用定时器0模式116位自动重装 void PWM_Init(void) { TMOD 0xF0; // 清零T0位 TMOD | 0x01; // T0设为模式1 TH0 (65536 - 100) / 256; // 初始值决定PWM频率这里约10KHz TL0 (65536 - 100) % 256; ET0 1; // 开启T0中断 TR0 1; // 启动T0 PWM_PIN 1; // PWM输出引脚初始高电平 } void Timer0_ISR(void) interrupt 1 { static unsigned char pwm_counter 0; static unsigned char pwm_duty 70; // 占空比70% TH0 (65536 - 100) / 256; // 重装初值维持频率 TL0 (65536 - 100) % 256; pwm_counter; if (pwm_counter 100) { // PWM周期为100份 pwm_counter 0; PWM_PIN 1; // 周期开始输出高电平 } if (pwm_counter pwm_duty) { PWM_PIN 0; // 达到占空比输出拉低 } } // 设置电机速度和方向 void set_motor_speed(unsigned char duty, unsigned char dir) { pwm_duty duty; // 修改全局占空比变量 if(dir FORWARD) { AIN1 1; AIN2 0; } else { AIN1 0; AIN2 1; } }舵机控制舵机控制信号是周期20ms50Hz脉宽0.5ms-2.5ms的PWM。可以用一个定时器专门产生。// 定时器1初始化用于舵机PWM模式116位 void Servo_PWM_Init(void) { TMOD 0x0F; TMOD | 0x10; // T1模式1 // 定时器初值计算假设系统时钟12MHz12T模式机器周期1us。 // 要产生20ms周期需要20000us。我们让定时器每50us中断一次需要400次中断为一个周期。 TH1 (65536 - 50) / 256; // 50us中断一次 TL1 (65536 - 50) % 256; ET1 1; TR1 1; Servo_PIN 1; } volatile unsigned int servo_pulse_width 1500; // 初始脉宽1.5ms对应90度 volatile unsigned int servo_tick_count 0; void Timer1_ISR(void) interrupt 3 { TH1 (65536 - 50) / 256; // 重装50us初值 TL1 (65536 - 50) % 256; servo_tick_count; if (servo_tick_count 400) { // 400 * 50us 20ms周期结束 servo_tick_count 0; Servo_PIN 1; // 开始新的周期输出高电平 } // 将脉宽单位us转换为定时器滴答数 if (servo_tick_count (servo_pulse_width / 50)) { Servo_PIN 0; // 脉宽时间到输出拉低 } } // 设置舵机角度0-180度 void set_servo_angle(unsigned char angle) { // 将角度转换为脉宽us angle_map 500 angle * (2000/180) servo_pulse_width 500 angle * 2000 / 180; }4. 系统集成与调试中的关键问题4.1 多任务管理与时序冲突在超级循环架构下最怕的就是一个耗时任务阻塞整个系统。例如在颜色识别时如果使用delay_ms(100)来等待闸门时间这100ms内单片机什么都做不了电机可能失控按键无响应。解决方案使用状态机和非阻塞延时。将颜色识别过程分解成几个状态IDLE, SET_FILTER, WAITING, READING利用定时器中断维护一个全局时间戳在主循环中根据状态和时间戳来判断该做什么而不是死等。enum ColorState {CS_IDLE, CS_SET_RED, CS_WAIT_RED, CS_READ_RED, CS_SET_GREEN, CS_WAIT_GREEN, ...}; enum ColorState c_state CS_IDLE; unsigned long color_sample_start_time 0; unsigned long red_value 0; void color_state_machine(void) { switch(c_state) { case CS_IDLE: if (need_to_sample_color) { set_s2_s3(0,0); // 选红色滤光片 clear_pulse_count(); enable_counter(); color_sample_start_time sys_tick; // 获取当前系统时间戳 c_state CS_WAIT_RED; } break; case CS_WAIT_RED: if (sys_tick - color_sample_start_time 100) { // 非阻塞等待100ms disable_counter(); red_value get_pulse_count(); c_state CS_SET_GREEN; // 切换到下一个状态 } break; case CS_SET_GREEN: set_s2_s3(1,1); // 选绿色滤光片 delay_ms(10); // 这个短延时可以保留或也用状态机优化 clear_pulse_count(); enable_counter(); color_sample_start_time sys_tick; c_state CS_WAIT_GREEN; break; // ... 后续状态类似 } } // 在主循环中调用 color_state_machine();这样即使在等待采样的100ms里主循环依然可以快速扫描按键、更新显示等。4.2 定位误差的累积与补偿单纯依靠光电脉冲计数会有误差电机启动/停止时的滑差、皮带轻微打滑、脉冲计数丢失或误触发。解决方案引入“归零”参考点。在传送带的起点上料位置安装一个限位开关或另一个光电传感器作为“原点传感器”。每次系统上电或完成一个循环后让传送带反向慢速运行直到触发原点传感器然后将distance_pulse_count清零。这样每个物料的分拣位置都以这个物理原点为基准进行计算可以消除累积误差。void go_home_and_reset(void) { set_motor_speed(30, REVERSE); // 低速反转 while(origin_sensor NOT_TRIGGERED); // 等待触发原点传感器注意加超时判断 set_motor_speed(0, REVERSE); // 停止 distance_pulse_count 0; // 脉冲计数器清零 current_position_mm 0; // 逻辑位置清零 }4.3 抗干扰与信号稳定性TCS3200受环境光影响必须制作一个遮光罩将传感器和被测色块罩起来内部可用一个白色LED作为稳定的光源。这样就能基本排除环境光变化的影响。电机对电源的干扰电机启停时会产生很大的电流波动和电磁噪声可能造成单片机复位或传感器读数异常。务必在电机电源端并接一个大容量电解电容如470uF和一个小容量瓷片电容0.1uF进行滤波。电机驱动芯片的电源和单片机电源最好能分开磁珠或0欧电阻隔离并确保共地良好。传感器信号线干扰脉冲信号线如光电传感器、TCS3200 OUT尽量短如果无法缩短可以考虑接入一个施密特触发器如74HC14进行整形或者软件上在中断服务程序中做去抖处理。5. 功能扩展与优化思路完成基础功能后如果想在比赛中脱颖而出可以考虑以下优化点自适应颜色校准系统上电后自动依次识别红、绿、蓝标准色块将读取到的R、G、B基准值存入EEPROM。后续识别时使用相对基准值的比例来判断而非固定阈值极大提升对不同批次色块和环境微小变化的适应性。速度闭环控制通过测量光电脉冲的频率实时计算传送带速度。如果速度偏离设定值则动态调整PWM占空比使速度保持稳定。这需要用到简单的PID算法能显著提高高速运行下的分拣精度。多物料队列管理如果赛题支持连续上料系统需要能记住多个物料的位置和颜色。可以设计一个小的队列数组每识别一个物料就将其颜色和目标位置存入队列。主程序根据当前脉冲计数和队列头部的数据来决定何时分拣。这考验数据结构和逻辑控制能力。更友好的人机界面使用LCD12864图形点阵屏可以绘制简单的动画如显示物料移动的示意图、实时速度曲线等。或者加入蜂鸣器用不同的声音提示识别成功、分拣完成、出错等状态。通信与上位机通过串口将识别结果、计数、系统状态发送到电脑上位机上位机用串口助手或自己写的软件进行显示和记录。这体现了系统的可观测性和可扩展性。6. 常见问题与调试技巧实录在调试这样一个多模块系统时问题总是层出不穷。下面是一些典型的“坑”和解决方法问题1颜色识别不准时对时错。可能原因环境光干扰传感器距离色块高度不合适识别时物料在运动反射光不稳定阈值设置不合理。排查步骤确保物理环境加上遮光罩和专用光源。固定传感器高度使其聚焦在物料表面。静态测试将物料静止放在传感器下通过串口打印出R、G、B的原始计数值。观察不同颜色下三个值的比例关系是否稳定、差异是否明显。如果不明显可能需要调整光源强度或传感器增益TCS3200的S0,S1。动态优化如果必须在运动中识别尝试在识别区上方加装一个挡板让物料在通过时有一个短暂的“稳定期”或者提高采样频率进行多次采样取中值或平均值。算法优化不要只用“最大值”判断。尝试使用归一化处理r R/(RGB), g G/(RGB), b B/(RGB)然后判断r,g,b中哪个最大且超过一定阈值如0.5。这能消除整体亮度变化的影响。问题2物料分拣位置有偏差有时推空有时推不到。可能原因脉冲计数误差机械安装不精确电机启停有惯性。排查步骤校准脉冲当量让传送带运行一个较长的已知距离如1米记录脉冲总数。计算脉冲当量 距离 / 脉冲数。这个值比理论计算更准确。检查机械确保分拣推杆舵机臂的初始位置和推动位置与传送带边缘对齐。可以用手转动皮带目测物料到达推杆正下方时脉冲计数是多少。加入提前量与滞后量由于惯性电机从收到停止指令到完全停下物料还会前进一小段。因此目标位置要设得比实际分拣点提前一些。例如计算出的分拣点在脉冲数1000实际停止指令可以在脉冲数980时发出。这个“提前量”需要通过实验测定。使用闭环定位更高级的做法是到达目标位置附近后进入低速“爬行”模式当脉冲数等于目标值时立即刹车。这需要电机能快速响应。问题3系统运行一段时间后死机或复位。可能原因电源功率不足电机干扰导致电源电压跌落软件跑飞堆栈溢出。排查步骤监测电源用万用表测量单片机VCC引脚在电机启动瞬间的电压。如果跌落超过0.5V说明电源内阻太大或容量不足。更换功率更大的电源并在电机驱动电源入口加大电容。看门狗启用单片机内部的看门狗IAP15有。在程序主循环中定期喂狗。如果程序跑飞看门狗会复位系统。检查中断确保中断服务程序执行时间尽可能短不要在里面做复杂计算或调用可能阻塞的函数。避免中断嵌套。堆栈深度51单片机堆栈空间有限。减少函数嵌套层数避免在中断和主程序之间传递大的结构体。问题4按键响应不灵或LCD显示乱码。可能原因主循环被耗时任务阻塞按键扫描代码有bugLCD初始化或时序不对。排查步骤优化主循环如前所述将所有delay改为非阻塞方式。确保主循环一次执行时间在几毫秒内。按键消抖使用状态机进行按键扫描识别稳定的按下和释放状态而不是简单检测电平。LCD时序严格按照LCD1602 datasheet的时序要求写代码尤其是使能信号E的脉宽和建立保持时间。如果用的是IO口模拟在操作指令/数据后加足够的nop()或短延时。如果接线过长可以考虑降低通信速度。调试这样的系统分模块调试是黄金法则。先让电机单独转起来位置计数准确再单独调试颜色传感器能稳定识别静态色块然后单独调试舵机能精确推到指定位置。最后再把它们像拼积木一样组合起来用简单的逻辑串联测试。每增加一个功能就测试一遍这样一旦出问题很容易定位到是新加入的模块引起的。准备好你的万用表、逻辑分析仪或者用单片机另一个IO口模拟逻辑分析仪抓时序和串口调试助手它们是你最得力的助手。
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻