前言

两年一届的工训赛结束了。最终因器材和识别方面的一些问题,遗憾止步省赛,获得省一等奖。虽然无缘国赛,但还是想和大家分享我的搭建过程、遇到的坑以及一些经验。
我个人水平有限,觉得传送带方案可能更稳妥,但选择了机械臂方案也并不后悔。这段经历让我收获很多,如果分享中有任何不妥或者不足,也欢迎大家批评指正。

封面


赛题分析

(一)垃圾方面

  • 厨余垃圾、有害垃圾、其他垃圾、可回收垃圾

(二)功能方面

  • 垃圾分类、垃圾压缩、满载警报、播放自主设计的垃圾宣传片

(三)结构方面

  • 高亮显示屏固定在表面
  • 待机时循环播放“垃圾宣传视频”
  • 控制系统安装在比赛装置内
  • 装置的上表面方便打开和拆卸
  • 美观完整的外观(四周及上表面)
  • 装置整体不得超过400mmX400mmX600mm
  • 小垃圾桶的体积不少于直径为100mm,高度为100mm
  • 小垃圾桶的外表面要透明且要贴上明显的垃圾分类标志
  • 垃圾桶的最高表面要一个固定投放口(投放口为110mm的正方形)
  • 显示垃圾分类的数据(投放顺序,垃圾数量,任务完成提示,满载情况)

一、机械结构

(一)设计思路

采用UM结构定位物体坐标,由机械臂夹取并移至投料口。投掷前旋转二维舵机云台留出空间。可回收垃圾会先进行压缩。通过倾斜安装的光电传感器检测满载状态。顶部设有串口屏显示信息,四周和垃圾桶上方采用合页结构方便调试。所有元器件集中于底部,摄像头置于桶内顶端。锂电池电源位于下方小桶的缝隙中,底部按标准预留空间。

机械爪垃圾桶运行视频
模型整体照片

(二)机构部分

1.滑台定位机构

  • 滑台机构参考了UM结构3D打印机,并做了调整:将固定光轴的四个滑块的安装孔移至整体滑块中间,以扩大十字滑块的移动范围。参考该结构时需计算适配光轴的长度。
  • 自行设计孔位时建议预留0.15–0.2mm的余量。安装后需参照调平视频进行调平,确保十字滑块能顺畅移动到可动范围内任意位置。

3D打印建议使用PETG材料,40%填充率,3层壁厚

滑台定位机构

2.柔性夹爪机构

  • 制作夹具时,夹爪采用TPU材质以提供柔性,其他结构件使用PETG材质以保证较高硬度。
  • 在整机装配过程中,安装舵机时需先上电使其归位至90°位置,再进行机械固定,其余旋转角度需根据实际结构另行调整。确保运动范围内无机械干涉,避免舵机过载或堵转导致烧毁。

MG996R舵机较易损坏,建议比赛时多备几个

机械爪整体模型

3.旋转云台机构

  • 在旋转舵机云台的设计中,整体结构及托盘建议采用3D打印制作,以更好地适配装配需求。装配时需注意将舵机初始位置调整至90°,并准确设定目标旋转角度,确保云台运动顺畅。四周合页部分推荐使用雪弗板
  • 若发现垃圾从上表面投入后易弹起,可在托盘底部增加减振材料来缓解冲击。该结构中的四个舵机较易烧毁,装配时请特别注意是否发生堵转,并优先选用金属配件或数字舵机以提高可靠性。

我设计了一款舵机承载外壳,也在此分享给大家,希望对各位有所帮助😊。

旋转云台

4.满载压缩机构

  • 四个满载检测光电开关采用倾斜安装方式,分别布置在小垃圾桶的四个内角,便于全面检测。光电开关后方设有灵敏度调节旋钮,可用于调整检测距离。
  • 结构板材方面,底盘选用5mm亚克力板以保证整体稳定性,外壳和小垃圾桶则采用3mm亚克力板以减轻重量。针对可回收垃圾的压缩需求,对应的小垃圾桶一侧设计为可活动结构,便于实现压缩功能。
  • 将底盘舵机预先调整至特定角度位置,可省去旋转对准时间,实现单个垃圾的快速倾倒。
    云台底部可以铺垫缓冲材质

若出现舵机抖动现象😢:检查供电电流是否充足; 确认舵机是否损坏; 检查连接线是否插接牢固。

底盘装置

二、电路电控

(一)设计思路

  • 视觉识别模块首先对垃圾的种类、数量及坐标进行识别和定位,并将数据传送至下位机。下位机将信息转换为脉冲信号与高低电平,经由驱动器控制步进电机转动,同时驱动舵机完成倾倒和旋转等动作。系统通过光电开关检测满载状态,并采用大功率直流电机驱动气缸执行压缩操作。最终状态信息通过串口屏实时显示。

流程图

(二)器件选型

  • 视觉模块MaixCAM

视觉模块

  • 舵机MG996R
    舵机需要单独供电

MG996R舵机

  • 步进电机驱动TB6600

步进电机驱动TB6600

  • BTS7960大功率直流电机驱动

BTS7960

  • Arduino Mega 2560

Arduino mega 2560

  • TJC串口屏

TJC串口屏

  • 锂电池

锂电池

  • 降压模块

降压模块

  • 光电开关
    在这里插入图片描述
    满载放置

把光电传感器的检测头都朝上安装在置物架上,这样电控的同学调试起来会更方便

  • 稳定性很重要,建议大家尽量选择打板。我当初比较菜因为不会画PCB,只能在洞洞板上靠飞线和拖锡连接,还是挺麻烦的

电路模块
电路模块2
这是当时还没做完的时候朋友帮忙拍的,样子还有点简陋😂

电控底板

可以3D打印一个洞洞板的隔离底板,避免电路板直接接触桌面或其它导电表面,防止发生短路烧毁

(三)控制逻辑

1.控制方法

  • 做这些东西之前,最好先了解一下各种控制元件的基本用法,我之前攒的资料分享给大家

TJC串口屏资料BTS7960驱动教程TB6600驱动教程MG996R驱动步进电机驱动

在这里插入图片描述

2.通讯部分

  • 系统首先按照逐字节的方式接收串口数据。接收过程中将数据分为数字字符非数字字符两类:
  • 数字数据处理
    • 当接收到数字字符时,将其逐位拼接成整数。 每个完整的整数依次存入数字数组,并设置标志位。 若遇到非数字字符且标志位为真,则完成一个数字的存储,并重置标志位,准备接收下一组数据。
  • 非数字数据处理
    • 将非数字字符按顺序存入另一数组,用于标识数据类别或作为结束标志。
  • 结束标识
    • 规定一个特殊字符作为一帧数据的结束标志(如 m)。当检测到该标志时,判定一波数据接收完成
  • 示例数据格式 r1123235156230372m 对应含义如下:
    • r 1 123 235 156 230 372 m
    • r:垃圾种类信息
    • 1 / 2:垃圾数量信息
    • (123,235):点位一坐标
    • (156,230):点位二坐标
    • 372:两点坐标的平均数,作为校验信息
    • m:一波数据结束标识

3.坐标计算

int X_distance_value = 0.5 * ((newintData[0] + newintData[2]) / 2);
int Y_distance_value = 0.5 * ((newintData[1] + newintData[3]) / 2);
X_move_steps = X_distance_value * 100;
Y_move_steps = Y_distance_value * 100;

(newintData[0] + newintData[2]) / 2 // 计算两个检测点的X坐标平均值,得到物体在图像中的中心X位置

0.5 // 乘以像素-物理单位转换系数(根据实际垃圾桶尺寸调整此参数)

100 // 将物理单位转换为步进电机所需步数(根据实际传动系统调整此参数)

4.物体标定

  • 缩放系数计算方法
    • 为了实现坐标像素与实际物理尺寸的对应关系,将外接摄像头固定在垃圾桶内部,并在检测平面上放置一张100 mm × 100 mm的标准正方形标定板。通过电脑调用外接摄像头拍摄标定图像,确保正方形完全出现在画面中。随后,利用图像处理方法提取正方形的顶点坐标,获取左上角点(xA, yA) 与右上角点 (xB, yB)。像素宽度可由 (xB - xA) 得到,结合实际长度 100mm,即可计算出像素与物理长度之间的缩放系数。
    • 缩放系数=100 / ( xB - xA )

图像处理方法我是用AI生成一段标定屏幕像素位置的python代码来解决的😁

  • 步进电机物理单位与步数转化

    • 步进电机输入固定数量的脉冲信号,测量其对应的实际移动距离,从而得出步数与位移之间的比例关系。

    在实际应用中,需要根据所选电机的步距角、驱动器细分设置以及传动机构参数(如丝杆导程或皮带齿距)重新标定该系数。

例如,在细分设置确定的条件下,步进电机在输入 200 步脉冲 后,带动机构移动了 10 mm
- 换算系数=200/10=20 steps/mm

  • 机械爪转动判断
    • 用坐标值判断目标是否长条(横向长于纵向),需要把爪子旋转 90° 来对齐

5.基本控制代码

  • 推荐TJC串口屏简单好上手,黑色区域用于显示垃圾识别的分类记录和信息统计

传输串口屏的HMI工程文件时,请务必使用压缩包格式(如ZIP或RAR)

串口屏页面

  • 爪的控制示例
void lifting_claws_move(int target_angle) { 
  if (current_lifting_claws_angle < target_angle) {
    while (current_lifting_claws_angle < target_angle) {
      current_lifting_claws_angle += step;
      lifting_claws.write(current_lifting_claws_angle);
      delay(claws_delayTime);
    }
  } else if (current_lifting_claws_angle > target_angle) {
    while (current_lifting_claws_angle > target_angle) {
      current_lifting_claws_angle -= step;
      lifting_claws.write(current_lifting_claws_angle);
      delay(claws_delayTime);
    }
  }
}

  • 光电开关控制示例
void check_sensor(int sensor_Pin, unsigned long &sensor_startTime, char sensorChar) {  
  if (digitalRead(sensor_Pin) == LOW) {
    if (sensor_startTime == 0) {
      sensor_startTime = millis();
    }
    if (millis() - sensor_startTime >= sensor_timeout) {
      Serial.print(sensorChar);
      switch (sensorChar) {
        case 'K':
          if (currentPage != 1) {  
            sendPageChange();
          }
          handleButtonPress(0);
          zip_rubbish();
          break;
        case 'Y':
          if (currentPage != 1) {  
            sendPageChange();
          }
          handleButtonPress(1);

          break;
        case 'C':
          if (currentPage != 1) {  
            sendPageChange();
          }
          handleButtonPress(2);

          break;
        case 'Q':
          if (currentPage != 1) {  
            sendPageChange();
          }
          handleButtonPress(3);

          break;
      }
      sensor_startTime = 0;
    }
  } else {
    sensor_startTime = 0;
  }
}

三、视觉识别

(一)硬件准备

视觉照片

  • 选购该设备时,可自行选择并烧录系统镜像,例如 MaixCam Pro 也是适用的配置方案。

单片机接口图

  • 与单片机连接时,需连接四根线:将左下角的供电线接至 5V 电源,右上角依次连接 RX、TX 和 GND 即可。
    如果外壳是封闭结构,或者桶内光线较暗影响检测,可以考虑在内部安装暖光灯带

(二)模型训练

  • 进入MaixHub官网,完成登录或注册后,点击“模型训练”并创建新训练任务,接下来只需拍摄所需图像数据即可。不过记得找位帮手来标注数据集——这部分可能比较痛苦😭,需要一些耐心。

模型训练

  • 训练模型的参数自己调整

模型训练2

  • 然后训练完成后部署模型就行

模型训练3

(三)逻辑思路

流程逻辑

  • 程序并不是每一帧都检测,而是每隔20帧调用一次模型,减少计算压力。然后比较前后几帧目标的位置,如果目标几乎不动,才认为是稳定的。
if frame_count % 20 == 0:
    objs = detector.detect(img, conf_th=0.55, iou_th=0.45)
  • 当检测到多个目标时,会根据事先定义的优先级顺序排序,选择最重要的那个。
sorted_objs = sorted(stable_objs, key=lambda obj: get_priority_index(detector.labels[obj.class_id]))
  • 调试的时候,程序会在屏幕上用红框把认出来的东西框出来,中间画个绿点标记位置,框上面还会显示这是啥东西以及识别得有多准。
img.draw_rect(obj.x, obj.y, obj.w, obj.h, color=image.COLOR_RED)
img.draw_circle(cx, cy, 4, color=image.COLOR_GREEN)

(四)Yolov5

Anaconda虚拟环境
手把手教你使用YOLOV5训练
处女座up主
十二up主
香橙派yolov5
使用YOLOV9进行PCB板缺陷检测

四、注意事项

  1. 如果经费允许,线材一定要选择质量更高的,使用前最好剥开线缆观察铜丝粗细
    我就是因为开关焊接用的铜线太细,导致设备最后无法开机😭

  2. 在设计时应预留出足够的测量空间,方便组委会进行电压检测
    比赛时千万别用劣质的转接端口!我那次就是为了测电压转接口直接就坏了,不得不现场拆锂电池。
    转换头

  3. 仔细看比赛规则,搞明白要不要写“无检测保护”
    看总裁判长要求无间隔依次投入10个垃圾,还是每隔5分钟投入一个垃圾

  4. 结构外壳最好做成完整的长方形

  5. 队伍分工一定要明确!赛场上一共就三四人,谁负责社区赛加工,谁负责调试决赛代码
    时间紧任务重!还要应对随机万变的规则!

  6. 别等垃圾堆满了再压缩——识别投完一次,就压缩一次

  7. 光电头大概率检测不到黑色物体;超声波对网球这类吸音材料可能失效

  8. 备赛要多试各种“垃圾图片”,尤其关注特殊省份可能出现的特殊类型。
    在这里插入图片描述
    在这里插入图片描述

  9. 测量满载的时候组委会可能没有足够多的垃圾,我们是黑色泡沫填充物

  10. 设备要支持“一键启动”,个别现场不允许提前开机


总结

以上就是我在做垃圾桶赛道时的一些经验和感受啦,里面难免会有理解不够到位或者说错的地方,如果有问题也欢迎大佬指出来~如果你正准备参加工训赛,希望这些内容能给你一点点帮助或者思路,少踩一些坑。最后奉上赛场垃圾和我的桶的实物图😁

赛场垃圾
实物图桶

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐