当前位置: 首页 > ops >正文

电子设计大赛【摄像头循迹】讲解

目录

系统概述与基础原理

1.循迹定义

2.核心原理

硬件系统的搭建

1.摄像头模块

(1)机器视觉能力

(2)开发支持

2.主控芯片

3.电机驱动模块

(1)芯片组合定位与分工

(2)关键芯片能力解析

1. STM32F103VCT6(ARM Cortex-M3 MCU)

2. Cyclone IV EP4CE6E22C8N(Intel FPGA)

(3)电机驱动架构 

软件代码讲解

一、直线循迹核心流程

二、关键代码解析

1. 图像预处理

 2. ROI区域定义

 3. 直线检测核心函数

4. 偏转角计算

 5. 数据封装与发送

 6. 主循环中的循迹处理

三、关键技术点

四、数据处理流程

效果展示


系统概述与基础原理

1.循迹定义

智能小车沿指定(黑线)路径循迹。

2.核心原理

摄像头采集路面图像 → 图像处理识别路径 → 生成控制信号 → 驱动执行机构(电机/舵机)


硬件系统的搭建

1.摄像头模块

搭载 Kendryte K210 芯片的 AI 摄像头模组。

(1)机器视觉能力

  • 实时目标检测:识别物体/人脸的位置、大小及类型,输出坐标信息。
  • 颜色/形状追踪:通过 HSV 空间过滤与连通域分析,定位最大色块并反馈中心坐标。
  • 神经网络模型支持:可部署 YOLOv2 Tiny 等轻量模型,适用于边缘端 AI 推理。

(2)开发支持

  • 编程环境:支持 MicroPython(MaixPy 框架),代码简洁易上手,提供图像处理库(如 find_blobs 色块检测)。

  • 通信接口:集成 UART/I2C/SPI,可连接 STM32 等主控,通过串口传输坐标数据。

  • 扩展性:支持 TF 卡存储模型文件,GROVE 兼容接口便于连接传感器。

2.主控芯片

采用ATMEGA2560-16AU这款芯片是 Arduino Mega 2560 开发板的核心微控制器芯片。

特性参数
架构8 位 AVR RISC 处理器
主频16MHz(-16AU 后缀表示 16MHz 版本)
Flash 程序存储器256KB
SRAM8KB
EEPROM4KB
PWM 通道15 路(12 位精度,支持相位校正/快速 PWM)
数字 I/O 引脚54 个(含 PWM 引脚)
串口4 个 UART
外部中断所有 I/O 引脚均支持

3.电机驱动模块

(1)芯片组合定位与分工

芯片核心角色电机驱动中的核心任务
STM32F103VCT6主控决策层 (MCU)系统调度、通信协议、高级算法(PID/FOC)
Cyclone IV EP4CE6E22C8N实时执行层 (FPGA)超高速PWM生成、编码器捕获、硬件保护逻辑

💡 协作逻辑
STM32 计算电机控制量 → FPGA 执行精确的功率器件驱动 → 实时反馈信号由 FPGA 捕获后送回 STM32


(2)关键芯片能力解析

1. STM32F103VCT6(ARM Cortex-M3 MCU)
  • 核心参数

    • 72MHz 主频,256KB Flash,48KB RAM

    • 高级定时器 × 3(支持6路互补PWM,死区时间可编程)

    • 12位ADC × 3(21通道,1μs转换速度)

  • 电机控制专长

    • 原生支持无感FOC算法(配合ST MotorControl SDK)

    • 3路霍尔/编码器接口(用于电机位置检测)

    • 硬件过流保护触发(BKIN引脚直连FPGA)

2. Cyclone IV EP4CE6E22C8N(Intel FPGA)
  • 核心参数

    • 6272 逻辑单元(LEs),270Kb 嵌入式存储器

    • 15个18×18乘法器(DSP模块)

    • 最大182个用户I/O

  • 电机控制专长

    • 纳秒级PWM响应:可生成分辨率<10ns的PWM(远优于MCU的百纳秒级)

    • 硬实时保护:过流/过压保护延迟<500ns(比软件中断快100倍)

    • 多路编码器并行处理(支持1024线增量式编码器@10万RPM)

(3)电机驱动架构 


软件代码讲解

一、直线循迹核心流程

二、关键代码解析

1. 图像预处理

# 拍摄原始图像
img = sensor.snapshot()# 转换为灰度图(巡线模式下)
if img_color_type == 0:img = img.to_grayscale(copy=False)# 动态调整灰度阈值
get_mean_gray(img,320,240)

 2. ROI区域定义

ROIS = {'left': (0, 0, 180, 50),            # 左侧纵向检测区'right': (0, 190, 180, 50),         # 右侧纵向检测区'up': (240, 0, 80, 240),            # 上方横向检测区'middle_up': (160, 0, 80, 240),     # 中上方横向检测区'middle_down': (80, 0, 80, 240),    # 中下方横向检测区'down': (0, 0, 80, 240),            # 下方横向检测区
}

 3. 直线检测核心函数

def find_blobs_in_rois(img):'''在预定义ROI区域中检测黑线'''roi_blobs_result = {}for roi_direct in ROIS.keys():# 初始化结果字典roi_blobs_result[roi_direct] = {'cx':0, 'cy':0, 'w':0, 'blob_flag': False}for roi_direct, roi in ROIS.items():# 在ROI区域内寻找符合阈值的色块blobs = img.find_blobs(LINE_COLOR_THRESHOLD, roi=roi, merge=True)if blobs:# 找到最大色块largest_blob = max(blobs, key=lambda b: b.pixels())if largest_blob.area() > 1000:  # 面积过滤小噪点# 记录色块中心坐标和宽度roi_blobs_result[roi_direct]['cx'] = largest_blob.cy()roi_blobs_result[roi_direct]['cy'] = largest_blob.cx()roi_blobs_result[roi_direct]['w'] = largest_blob.h()roi_blobs_result[roi_direct]['blob_flag'] = True# 调试模式下绘制检测框if is_debug:x,y,width,height = largest_blob[:4]img.draw_rectangle((x,y,width, height), color=(255))return roi_blobs_result

4. 偏转角计算

def state_deflection_angle(roi_blobs_result):'''计算车辆偏转角度和路口状态'''# ROI区域权重配置(重点关注上下区域)ROIS_WEIGHT = [1, 0, 0, 1]  # [上, 中上, 中下, 下]state_crossing = Falsedeflection_angle = 0down_center = 0center_num = 0# 1. 计算加权中心位置centroid_sum = (roi_blobs_result['up']['cx'] * ROIS_WEIGHT[0] + roi_blobs_result['middle_up']['cx'] * ROIS_WEIGHT[1] +roi_blobs_result['middle_down']['cx'] * ROIS_WEIGHT[2] + roi_blobs_result['down']['cx'] * ROIS_WEIGHT[3])# 2. 统计有效检测区域数量if roi_blobs_result['up']['blob_flag']:center_num += ROIS_WEIGHT[0]if roi_blobs_result['middle_up']['blob_flag']:center_num += ROIS_WEIGHT[1]# ... 其他区域类似# 3. 计算中心位置(避免除零错误)if center_num > 0:center_pos = centroid_sum / sum(ROIS_WEIGHT)else:center_pos = IMG_WIDTH / 2  # 默认中心位置# 4. 计算偏转角(图像中心 - 检测中心)deflection_angle = (IMG_WIDTH / 2) - center_pos# 5. 路口检测逻辑# 检测左右两侧是否有黑线(可能进入十字路口)if roi_blobs_result['left']['blob_flag'] or roi_blobs_result['right']['blob_flag']:# 检查是否在图像下方1/3区域内if (roi_blobs_result['left']['cy'] <= (IMG_HEIGHT/3) or roi_blobs_result['right']['cy'] <= (IMG_HEIGHT/3)):# 检查下方黑线宽度是否超过阈值(十字路口特征)if roi_blobs_result['down']['w'] > 140:state_crossing = True# 如果两侧同时检测到黑线,确定为十字路口if (roi_blobs_result['left']['blob_flag'] and roi_blobs_result['right']['blob_flag'] androi_blobs_result['left']['cy'] <= (IMG_HEIGHT/3) and roi_blobs_result['right']['cy'] <= (IMG_HEIGHT/3)):state_crossing = Truereturn down_center, state_crossing, deflection_angle

 5. 数据封装与发送

def data_format_wrapper(down_center, state_crossing, deflection_angle):'''封装循迹数据为通信协议格式'''send_data = [0x55,  # 帧头0x02,  # 数据长度0x91,  # 指令类型(循迹)down_center,  # 底部中心标志(未使用)1 if state_crossing else 0,  # 路口标志get_symbol(deflection_angle),  # 偏转角符号(+/-)abs(int(deflection_angle)),  # 偏转角绝对值0xbb   # 帧尾]return bytes(send_data)def UsartSend(str_data):'''通过串口发送数据'''uart.write(str_data)

 6. 主循环中的循迹处理

while True:# ... 其他代码# 巡线模式激活if Flag_track:# 1. 在ROI区域检测黑线roi_blobs_result = find_blobs_in_rois(img)# 2. 计算偏转角和路口状态down_center, state_crossing, deflection_angle = state_deflection_angle(roi_blobs_result)# 3. 定时发送数据(50ms周期)if is_need_send_data:UsartSend(data_format_wrapper(down_center, state_crossing, deflection_angle))

三、关键技术点

  1. 动态阈值调整

    • 使用get_mean_gray()函数实时计算图像平均灰度

    • 基于平均灰度动态调整黑线检测阈值,适应不同光照条件

  2. 多区域检测策略

    • 将图像分为6个关键区域

    • 横向区域(上、中上、中下、下)用于计算偏转角

    • 纵向区域(左、右)用于十字路口检测

  3. 加权中心计算

    • 使用[1, 0, 0, 1]权重配置,重点考虑图像顶部和底部的检测结果

    • 有效减少中间区域的干扰

  4. 十字路口识别

    • 同时检测左右两侧出现黑线

    • 要求黑线位置在图像下方1/3区域内

    • 下方黑线宽度超过140像素作为辅助判断

四、数据处理流程

  1. 主控STM32通过串口发送0x55 0x02 0x91 0x01 ...启动循迹

  2. K210进入循迹模式,开始处理图像

  3. 每50ms计算一次偏转角并通过串口发送

  4. 发送数据格式:[帧头, 长度, 指令, 底部标志, 路口标志, 符号, 偏转值, 帧尾]

  5. STM32根据偏转值调整电机PWM输出,实现方向控制


效果展示

摄像头循迹1.0


http://www.xdnf.cn/news/16060.html

相关文章:

  • SpringMVC快速入门之请求与响应
  • 【大模型文生图、文生音频实战Demo】基于Spring AI Alibaba和阿里百炼大模型实现文生图、文生视频
  • WebGIS 中常用公共插件
  • 1688 Agent Russia 丨俄罗斯1688跨境代采系统搭建指南
  • 前端开发 React 状态优化
  • 基于深度学习的图像分类:使用预训练模型进行迁移学习
  • 原创-基于 PHP 和 MySQL 的证书管理系统 第三版
  • Neo4j 框架 初步简单使用(基础增删改查)
  • Neo4j如何修改用户密码?
  • 【Java】Reflection反射(代理模式)
  • Redis能完全保证数据不丢失吗?
  • Spring Cloud Alibaba Sentinel 基本工作原理源码阅读
  • BQ4050RSMR DIOTEC高精度锂电池保护与电量监测芯片 集成保护+计量+通信
  • AWS Lambda IoT数据处理异常深度分析:从告警到根因的完整排查之路
  • 快手DHPS:国内首个实现基于RDMA 通信的可负载均衡高性能服务架构!
  • 设计汽车集群电源
  • 前端资源缓存优化案例:深入探讨 Nginx 配置中的 Cache-Control 头部叠加问题
  • 一次Oracle集群脑裂问题分析处理
  • 耐达讯自动化EtherCAT转RS232:示波器连接的“开挂秘籍”
  • pig cloud框架中引入websocket
  • Android Camera openCamera
  • Node.js 倒计时图片服务部署与 Nginx 反向代理实战总结
  • OneTwoVLA——基于π0实现类π0.5:一个模型中完成原来双系统下的慢思考、快执行,且具备自适应推理能力和自我纠错能力
  • Java 大视界 -- Java 大数据机器学习模型在电商产品销量预测与库存优化管理中的应用(359)
  • OpenCV 零基础到项目实战 | DAY 2:图像预处理全解析
  • 基于JSP的高校寝室综合管理系统/宿舍管理系统
  • 【JavaSE】正则表达式学习笔记
  • 【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 主页-最近七天微博发布量实现
  • PetaLinux 使用技巧与缓存配置
  • Docker 容器中的 HEAD 请求缺失 header?从 Content-MD5 缺失聊起