基于imx6ull裸机开发的循迹小车实验
一、实验目的
1.掌握嵌入式裸机开发:深入理解IMX6ULL芯片的GPIO、时钟、中断、定时器(PWM输出、输入捕获)等外设配置方法;掌握UART、I2C、SPI通信协议;实现ADC数据采集
2.实现循迹核心功能:完成电机驱动控制、灰度传感器数据处理和循迹算法设计
3.多模块协同开发:实现陀螺仪姿态检测、LCD触屏控制与小车运动的联动
4.提升调试能力:通过示波器、万用表等工具解决嵌入式系统开发中的实际问题
二、实验环境
1.硬件配置
(1)主控:IMX6ULL Cortex-A7开发板
(2)驱动模块:TB6612双路电机驱动
(3)传感器:8路灰度传感器、MPU6050陀螺仪
(4)显示:3.5寸LCD电阻触摸屏
(5)底盘:双电机四轮小车底盘
(6)电源:12V锂电池组
2.软件环境
(1)开发环境:Ubuntu 20.04 + VSCode
(2)工具链:arm-linux-gnueabihf交叉编译工具链
(3)调试工具:示波器、万用表、串口调试助手
3.测试环境
(1)标准黑白循迹赛道(含直线、90°弯道)
三、实验内容
1.IMX6ULL裸机环境搭建
(1)配置系统时钟和外设时钟
(2)初始化GPIO、定时器(PWM输出)、ADC、I2C等外设
2.电机驱动与控制
(1)TB6612 电机驱动电路设计采用TB6612双H桥芯片驱动左右电机,IMX6ULL的PWM引脚接芯片 PWMA/PWMB 端,GPIO 引脚接 AIN1/AIN2、BIN1/BIN2 方向控制端;电源端并联滤波电容,输出端串联续流二极管,增设过流保护,兼容 3.3V 电平无需转换。
(2)双路 PWM 速度控制初始化定时器为 20kHz PWM 模式,左右电机独立通道控制。按赛道状态分级调速:直道占空比 80%,转向前置降为 30%,转向中 10%;速度切换采用线性渐变,避免抖动,保障行驶稳定性。
(3)电机方向控制逻辑定义电平组合对应转向:前进(双电机正转)、后退(双电机反转)、差速转向(单侧降速)、停止(刹车)。方向切换前先关 PWM 延时 50ms,适配方形赛道直角转向需求,防止芯片损坏。
3.灰度循迹系统
本部分聚焦方形赛道直道行驶的核心感知环节,基于自带模数转换功能的8路灰度传感器,直接读取高低电平信号实现赛道轨迹识别,结合循迹算法完成直道稳定行驶,同时针对全白/全黑特殊状态设计专属处理逻辑,为后续直角转向提供可靠的状态触发依据。
(1)8 路 ADC 传感器数据采集
① 采集初始化:配置IMX6ULL的GPIO引脚为输入模式,将8路灰度传感器的数字量输出引脚分别接入对应 GPIO 口,关闭引脚上拉 / 下拉电阻,匹配传感器电平标准(3.3V);
② 数据读取:采用轮询方式依次读取8路GPIO引脚电平状态,每10ms采集一次,传感器输出低电平0代表检测到 “黑色轨迹”,高电平1代表检测到“白色背景”,直接将电平值存储至 8 位数字量数组;
③ 异常过滤:若某一路引脚电平连续 5 帧固定为 0 或 1(无变化),判定为传感器断路 / 短路,标记该通道异常并采用前一帧有效值替代,避免单通道故障影响整体循迹。
(2)二值化处理和循迹算法
① 二值化简化处理:因传感器已直接输出数字量电平(黑 = 0、白 = 1),无需额外 ADC 采样和阈值计算,直接沿用传感器输出的 0/1 值作为二值化结果,输出 8 位二值化数组;
② 循迹算法:采用 “加权平均法” 计算偏差值,公式为:偏差值 =Σ(通道编号 × 通道电平值)/Σ(通道电平值);以 4 号通道为中心,偏差值 > 4 则判定小车偏右,偏差值 < 4 则判定偏左;
③ 纠偏控制:根据偏差值输出 PWM 占空比调整转向电机,偏差值与转向修正量呈线性关系(偏差越大,转向修正幅度越大),保证小车始终沿黑色轨迹居中行驶。
(3)全白 / 全黑状态处理
① 全白状态判定:8 路电平值全部为 1 且持续 50ms,判定为 “全白”,立即触发电机停止指令,作为直角转向的前置触发条件;若持续时间 < 50ms(光线干扰),判定为误触发,保持当前循迹逻辑并增大纠偏幅度;
② 全黑状态判定:8 路电平值全部为 0 且持续 30ms,判定为 “全黑”(偏离赛道),立即降低电机速度 50%,同时输出最大幅度的反向转向修正,尝试回归赛道;若持续 2s 仍未恢复,触发紧急停止;
③ 状态恢复:全白/全黑状态解除后(电平数组恢复正常),先以低速(正常速度的 30%)行驶 500ms,待循迹偏差稳定后恢复正常速度和纠偏逻辑。
4.陀螺仪姿态检测
(1)JY62 通过串口通信配置 IMX6ULL 串口波特率为 115200bps,与 JY62 陀螺仪串口双向通信;校验通信数据帧格式,确保指令发送、数据接收时序匹配,通信异常时触发报警。
(2)原始数据读取与滤波处理串口实时读取 JY62 输出的角速度、加速度原始数据;采用滑动平均滤波处理 5 帧数据,滤除高频噪声,降低数据漂移误差。
(3)角度数据用于小车姿态矫正解算滤波后数据得到横滚角、偏航角,直道时矫正车身水平(倾角超 2° 调整转向);90° 转向时闭环控制偏航角,误差≤1°;倾角超阈值时触发电机停止保护。
5.LCD触屏交互
(1)LCD 控制器初始化与显示驱动初始化 LCD 控制器,配置显示分辨率、像素格式,编写字符 / 图形显示驱动函数,实现数据实时刷新显示。
(2)触摸屏坐标读取与校准读取触摸屏 AD 转换值,通过五点校准法修正坐标偏差,建立物理坐标与显示坐标的映射关系,确保触控定位精准。
(3)交互界面设计与功能实现设计简洁界面:显示循迹状态、陀螺仪角度、触摸坐标;设置触控按钮,实现启停、等功能。
6.针对赛道的逻辑状态编写
本部分针对方形赛道“直道+90°直角弯道”的核心特征,基于状态机实现“循迹 -停止-精准转向-再循迹”的闭环控制,整合灰度传感器、陀螺仪数据完成方形赛道的自主行驶,是整个小车系统从“传感器数据采集”到“赛道自主决策”的核心落地环节。
(1)方形赛道核心状态定义与切换规则
① 状态 1(循迹行驶):小车的默认初始状态,基于 8 路灰度传感器数据执行直道循迹逻辑,保持沿方形赛道直边行驶;
② 状态 2(全白停止):作为转向准备状态,仅在灰度传感器识别到 “全白”(直角弯道前的预设标记)且数据稳定 50ms 后触发,触发后立即停止电机输出,稳定车身;
③ 状态 3(90° 闭环转向):由状态 2 触发,停止状态保持 200ms 后自动进入,基于陀螺仪数据执行 90° 直角打角,完成后退出;
(2)90°直角转向的陀螺仪闭环控制逻辑
核心目标:利用陀螺仪的角度反馈实现 90°转向的精准闭环控制,保证直角转向的误差≤1°。
① 转向前校准:进入状态3前,先读取陀螺仪当前角度作为“转向基准值”,清零角度累计误差,避免初始偏移影响转向精度;
② 转向启动:输出固定占空比的 PWM 控制转向电机,驱动小车开始转向;
③ 实时反馈:每 10ms 读取一次陀螺仪角度,计算当前角度与“基准值 + 90°”的偏差;
四、实验过程介绍
本次三轮循迹小车实验基于IMX6ULL核心板搭建硬件与软件逻辑,采用前轮牛角万向轮+后轮双310电机的三轮结构,搭载TB6612电机驱动、8路灰度传感器、六轴陀螺仪及LCD触摸屏。

图4-1 实验实现过程流程图
1.IO引脚配置

图4-2 引脚复用图
PWM使用的GPIO8和GPIO4引脚的复用,亮绿色标注
电机转向控制引脚GPIO1、UART3_CTS、SNVS_TAMPER5、SNVS_TAMPER8四个引脚,亮黄色标注
灰度循迹8个引脚GPIO2、UART3_TXD、UART2_RTS、UART2_TXD、SNVS_TAMPER0、SNVS_TAMPER2、SNVS_TAMPER4、SNVS_TAMPER7,蓝色标注
Led和蜂鸣器GPIO3、SNVS_TAMPER1,红色标记
串口UART4_TXD、UART4_RXD,暗绿色标记
不能使用的引脚GPIO0、JTAG_MOD、GPIO9,黑色标记
2.先让小车动起来
我们完成的是循迹三轮小车,前面使用了一个牛角轮(万向轮)的一个三轮结构。硬件我们使用的是轮趣科技家的车底板,310电机和荣洋电子家的TB6612电机驱动。

图4-3 底板图

图4-4 电机图

图4-5 电机驱动图
(1)步骤 1:查看IMX6ULL的PWM外设手册,配置定时器生成 PWM 波;
(2)步骤 2:通过 GPIO 控制电机驱动芯片(TB6612)的方向引脚;
(3)步骤 3:编写电机速度调节函数,通过修改 PWM 占空比控制转速。
3.灰度正确读取数值
灰度传感器使用的是感为的8路灰度传感器,带红色转接板,可以将adc模拟量转化为8路gpio引脚电平,减少cpu计算。

图4-6 灰度模块图
(1)步骤 1:连接灰度传感器到IMX6ULL的8个GPIO引脚,配置采集通道;
(2)步骤 2:编写传感器数据读取函数,区分 “黑线” 与 “白线” 的电压阈值;
4.灰度读值控制小车实现循迹
根据多组传感器的检测结果,编写转向控制逻辑(如 “左偏则右调”)。
(1)直行逻辑:当中间区域的灰度传感器检测到黑线、两侧传感器检测到白线时,判定小车沿轨迹直行,控制左右电机保持相同转速,维持当前行驶方向。
(2)左偏矫正逻辑:当左侧区域的灰度传感器检测到黑线、中间 / 右侧为白线时,判定小车轨迹左偏,采用差速调节:降低左电机转速、提高右电机转速,使小车向右微调方向,回归轨迹。
(3)右偏矫正逻辑:当右侧区域的灰度传感器检测到黑线、中间 / 左侧为白线时,判定小车轨迹右偏,同样采用差速调节:降低右电机转速、提高左电机转速,使小车向左微调方向,回归轨迹。
(4)异常消抖逻辑:当所有传感器连续检测到全白(无黑线)时,加入多次检测的消抖判定,避免因传感器误判导致小车失控。
5.小车状态机逻辑的编写
本环节采用 “分状态定义+条件触发切换”的思路,将小车运行划分为3个核心状态,通过状态标志位实现有序、可控的逻辑跳转,具体设计如下:
(1)状态 1:循迹状态:执行步骤 4 中的灰度循迹逻辑,控制小车沿轨迹行驶。
切换条件:当传感器连续检测到全白(消抖后),则切换至 “全白停止状态”。
(2)状态 2:全白停止状态:控制电机紧急停转(消除惯性冲出的风险),并短暂延时稳定小车状态。切换条件:停止动作完成后,自动切换至 “转弯模式状态”,同时清零全白检测的计数。
(3)状态 3:转弯模式状态:执行差速转向动作(如右轮正转、左轮反转),完成大角度转向;转向后加入延时,稳定小车姿态,避免直接循迹时灰度传感器无法识别黑线。切换条件:转弯动作完成后,自动切换回 “循迹状态”,重新开始轨迹跟踪。
6.陀螺仪串口读取数值
使用优信电子的带卡尔曼滤波的六轴姿态传感器。
图4-7 jy62位姿传感器图
(1)步骤 1:通过UART接口对接陀螺仪模块,配置模块的采样频率;
(2)步骤 2:编写数据解析函数,获取角度(或角速度)原始数据;
7.LCD触屏控制小车开始停止状态
(1)步骤 1:配置IMX6ULL的LCD控制器,初始化触摸屏的输入读取;
(2)步骤 2:编写UI界面(如 “循迹设置开始” 按钮),实现触屏点击事件的识别;
(3)步骤 3:关联触屏操作与小车参数,比如点击 “加速” 按钮修改 PWM 占空比。
8.数据处理浮点运算
针对陀螺仪采集到的数据进行处理的时候,还有显示LCD数据的时候,因为不支持浮点运算,所以分成了整数+小数部分分开计算。
9.LCD显示灰度、陀螺仪数值、触屏坐标
在 LCD 界面分区域规划显示内容,无间断采集8路灰度传感器实时数值、滤波后的陀螺仪角度/角速度数据、触屏点击的 X/Y 坐标值;按固定频率刷新 LCD 显示内容,将三类数据直观展示在对应区域,便于实时监测小车运行状态与调试优化。
五、基本原理介绍(主要代码的展示和解释等,20分);
1.代码概述
代码主要的逻辑部分就是在主循环和定时器1中断。
主循环的main函数里面是初始化以及绘制LCD按键区域,然后while循环里面就是执行读取陀螺仪的值在串口,LCD显示角度值,检测LCD是否按下开始按键,打印循迹的状态在LCD上面。
定时器1中断是设置的1ms执行一次,然后执行的是灰度的读取和小车运动状态的控制。
对于代码中所有的浮点运算,因为不支持浮点运算,所有都化成了整数部分和小数部分分开计算,再者是除法运算,采用 “乘法逆元” 或 “移位近似” 替代直接除法运算(避免除法指令的低效或兼容性问题)。将除法转换为整数乘法 + 移位操作,保证运算效率和精度。同时我们手动开启了IMX6ULL芯片的硬件浮点运算单元(FPU)和 NEON 协处理器。
/*
* @description : 使能I.MX6U的硬件NEON和FPU
* @param : 无
* @return : 无
*/
void imx6ul_hardfpu_enable(void)
{
uint32_t cpacr;
uint32_t fpexc;
/* 使能NEON和FPU */
cpacr = __get_CPACR();
cpacr = (cpacr & ~(CPACR_ASEDIS_Msk | CPACR_D32DIS_Msk))
| (3UL << CPACR_cp10_Pos) | (3UL << CPACR_cp11_Pos);
__set_CPACR(cpacr);
fpexc = __get_FPEXC();
fpexc |= 0x40000000UL;
__set_FPEXC(fpexc);
}
2.首先是主函数的逻辑代码:

主函数就是一堆初始化函数,循环里面四个函数uart4_read_jy62_angle();read_finger_point();touch_button();print_data();
(1)陀螺仪串口读取的函数:uart4_read_jy62_angle()
陀螺仪我们使用的是jy62陀螺仪,这个陀螺仪的通信方式可以是串口也可以是I2C,我们选择了串口,通信解析数据过程如下:
数据是按照16进制方式发送的,每个数据分低字节和高字节依次传送,二者组合成一个有符号的short类型的数据。

图5-1 数据通信图
对于其中的数据,我们只需要角度数据,尤其注意传回数据的包头为0x55 0x53才是我们想要的数据,则通信协议如下:

图5-2 角度具体通信数据图
对于陀螺仪,如果不发初始指令,接收到的数据就会是乱码,当时也是被搞了一下,没看懂那个数据,后面发送初始指令过去后接收到的数据就正常了。还有就是波特率一定要设置和陀螺仪发送的波特率一样,不然收到的也会是乱码。

图5-3 串口模式命令图
调试时串口助手接收到的数据:

图5-4 串口收到数据解析图
陀螺仪数据读取加解析代码主要如下:


(2)读触摸屏代码read_finger_point()

(3)触摸判断代码touch_button()

(4)灰度数据打印代码print_data()

这里注释掉的延时函数很有意思啊,当时团队成员单写的触摸屏检测没问题,但是移植到工程里面就卡,就是这个延时函数造成的!!!吃一堑长一智
3.然后是定时器中断里面的逻辑代码:


(1)灰度读取函数代码sensor_r1=read_sensors();
① 灰度io口的复用和初始化

② 通过gpio_pinread函数读取引脚值,通过位操作,把八个引脚读到的电平放入一个data数据里面。

(2)小车循迹逻辑函数代码track();
① 定义状态和变量

② 主要track循迹函数



(3)电机转向控制
① 引脚复用和初始化

② 电机使能、电机a、电机b的转向配置

(4)电机转速控制



pwm3与此相同配置




(5)LCD显示浮点数代码

(6)其他简单初始化的代码
串口初始化、中断初始化、lcd初始化、触摸屏初始化。




六、实验结果展示和分析(有图有真相,20分);
1.配置电机PWM波形图
正常PWM波形展示

图6-1 正常PWM输出波形图
不能使用的PWM引脚GPIO9复用配置出来的波形

图6-2 不正常引脚PWM输出波形图
2.上电屏幕初始化显示

图6-3 上电初始化显示LCD图
3.触摸开始按键后显示数据

图6-4 触摸按键变化LCD图
4.小车循迹图片

图6-5 小车循迹图
5.小车转角处理图片

图6-6 小车转角处理图
七、总结与心得体会(包含对本课程的意见或者建议等)(10分)
最初想完成这个小车是因为涉及了很多知识点,可以结合知识点都上手实操一下,比如说小车电机的pwm需要定时器的输出比较,灰度的采集需要定时器中断,普通GPIO引脚的复用功能,陀螺仪读取需要串口通信,同时结合触摸LCD屏做控制状态和数据显示。
从中遇到的一些有意思的困难:
① 定时器中断初始化:
在设置定时器中断的时候,最开始配好定时器中断但是并没有显示任何现象,所以放了个LED灯在中断里,发现LED不闪烁,以为是卡在中断里面了,然后在主循环里面放了个蜂鸣器却响,说明程序没有卡,是根本没执行中断,后面检查的时候,发现是因为中断的初始化和定时器的初始化顺序的问题,中断初始化要放在前面才能正常运行,而我不小心把定时器初始化放在了前面。
② 串口初始化配置:
UART4->UCR2 |= (1<<14) | (1<<5) | (1<<2) | (1<<1); (bit14: 1 忽略RTS引脚、bit8: 0 关闭奇偶校验、 bit6: 0 1位停止位、bit5: 1 8位数据位、 bit2: 1 打开发送、 bit1: 1 打开接收)
当时写漏了串口的UCR2寄存器配置,串口一直接收不到信息,补上后就能正常接收了。
③ 引脚复用问题:
配置电机的pwm的时候,pwm1可以配置成功,但是pwm2不行,输出的电压会比pwm1小0.5v的样子,而且示波器观察波形并不标准,后续对照代码,发现代码没有问题,想着换一个引脚试试,结果换个引脚过后发现pwm正常输出,波形也正常。
灰度的引脚也是,有三个引脚配置出来读取电平并不正常,会自己跳变,换三个引脚过后发现可以使用了。
④ 电机执行频率和灰度执行频率:
最开始电机执行放在主函数的while循环里面,灰度数据采样放在中断里500ms一次,但是发现效果并不好,最开始调整了灰度采样的频率,设置定时器1ms采集一次,发现效果有所改善,但是仍然不理想,把定时器频率配置更高过后发现仍然没有什么太大的变化,想着会不会是采样采到了数据但是无法及时控制电机。根据香农定理中“采样频率匹配控制响应频率”,把电机执行也放在中断里面紧跟灰度采样后面,灰度采集一次数据就执行一次电机后,发现效果非常好,控制非常迅速稳定。
⑤ 对于陀螺仪角度闭环:
最开始团队准备使用板载的icm20608六轴传感器采集数据,但是数据采集只有加速度和角速度,如果将角速度转化为角度需要进一步积分处理,但是团队积分后,因为六轴传感器上电会有零飘积分后误差越积越大,所以团队使用陀螺仪jy62,用串口读取角度值,在最初接收数据时,发现数据是一堆乱码看不懂,后面才想到是没有发初始指令,发指令配置好波特率后,数据接收就正常了。
⑥ 致命delay函数errow:
在中断里面请务必不要写delay函数,会卡住程序引发一些错误,最开始调试打印灰度值的时候写了一个delay忘记删掉,后面写LCD触摸屏读取的时候发现读取断续不灵敏,就是因为有个delay函数卡在那里了!!!
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)