STC32G 电磁循迹智能车:5ms 定时中断下 ADC 差比和与 PWM 控制实战
电磁循迹智能车的核心在于实时采集赛道磁场信号并快速响应。本文将深入探讨基于STC32G单片机的电磁循迹系统实现,重点解析5ms定时中断内完成多路ADC采集、差比和偏差计算以及PWM输出的完整闭环流程。通过优化代码时序和实时控制策略,我们能够构建一个高效、稳定的智能车控制系统。
1. 系统架构与硬件配置
电磁循迹智能车的硬件系统主要由以下几个关键部分组成:
- 主控芯片:STC32G系列单片机,具备高性能8051内核和丰富的外设资源
- 传感器模块:工字电感阵列(通常为3-5个),配合运放电路进行信号调理
- 执行机构:舵机(转向控制)和直流电机(速度控制)
- 电源管理:为系统提供稳定的5V、3.3V等不同电压等级
关键硬件参数对比:
| 组件 | 参数要求 | 典型配置 |
|---|---|---|
| 主控 | 主频≥24MHz,ADC≥10位,PWM通道≥4 | STC32G12K128 |
| 电感 | 工字型,电感量4.7-10mH | 10mH工字电感 |
| 运放 | 带宽≥1MHz,低噪声 | OPA2350 |
| 电机驱动 | 电流≥3A,PWM频率13-19kHz | DRV8701 |
提示:电机PWM频率建议设置在13-19kHz范围内,可有效减少对电磁信号的干扰。
2. 电磁信号采集与处理
电磁信号的采集和处理是循迹控制的基础。赛道中心线发出的20kHz交变磁场被电感捕获后,需经过以下处理流程:
- 信号调理:运放电路对微弱信号进行选频放大和检波
- ADC采集:单片机将模拟电压转换为数字量
- 信号归一化:消除环境干扰和硬件差异
// 三电感ADC采集示例代码 void ADC_Collect(void) { L = adc_once(ADC_P00, ADC_10BIT); // 左电感 M = adc_once(ADC_P01, ADC_10BIT); // 中电感 R = adc_once(ADC_P05, ADC_10BIT); // 右电感 }差比和算法是电磁循迹的核心算法,其计算公式为:
偏差 = (R - L) / (L + M + R) * 比例系数这种算法能有效消除信号强度变化带来的影响,使偏差值在-1到1之间归一化。
3. 5ms定时中断服务程序设计
定时中断是保证系统实时性的关键。我们将控制周期设置为5ms,在中断服务程序中完成所有实时控制任务。
// 定时器中断服务程序框架 void TM4_Isr() interrupt 20 { TIM4_CLEAR_FLAG; // 清除中断标志 // 1. 电感采集与偏差计算 ADC_Collect(); error = 50 * (R - L) / (L + M + R); // 2. 方向控制(舵机PWM更新) Steering_Control(error); // 3. 速度采集与电机控制 Speed_Measure(); Motor_Control(target_speed); }中断服务程序时序分析:
| 任务 | 典型耗时(μs) | 优化建议 |
|---|---|---|
| ADC采集 | 50-100 | 启用多通道连续采样 |
| 偏差计算 | 20-30 | 使用查表法替代浮点运算 |
| PWM更新 | 10-20 | 直接操作寄存器 |
注意:确保中断服务程序总执行时间不超过2ms,为其他任务留出处理时间。
4. 电机与舵机控制策略
4.1 舵机控制
舵机采用位置式PID控制,将偏差信号转换为PWM占空比:
void Steering_Control(float error) { static float last_error = 0, integral = 0; float output; // PID参数 float Kp = 0.8, Ki = 0.01, Kd = 0.2; integral += error; output = Kp*error + Ki*integral + Kd*(error-last_error); last_error = error; // 限幅处理 if(output > 100) output = 100; if(output < -100) output = -100; // 更新PWM占空比(50Hz频率) pwm_duty(PWM_STEER, 1500 + output*5); // 1500us为中值 }4.2 电机控制
电机控制采用速度闭环,通过编码器反馈实现精准调速:
void Motor_Control(int target) { static int last_speed = 0, integral = 0; int current = (speed1 + speed2)/2; // 平均速度 int error = target - current; // PI控制(电机响应快,通常不需要微分项) integral += error; if(integral > 500) integral = 500; // 抗积分饱和 if(integral < -500) integral = -500; int output = error*0.5 + integral*0.02; // 更新电机PWM pwm_duty(PWM_MOTOR_L, BASE_DUTY + output); pwm_duty(PWM_MOTOR_R, BASE_DUTY - output); }5. 系统优化与调试技巧
5.1 信号滤波处理
原始ADC数据需经过滤波处理以提高稳定性:
// 滑动平均滤波实现 #define FILTER_SIZE 5 int filter_buf[FILTER_SIZE] = {0}; int moving_average(int new_val) { static int index = 0; int sum = 0; filter_buf[index] = new_val; index = (index + 1) % FILTER_SIZE; for(int i=0; i<FILTER_SIZE; i++) { sum += filter_buf[i]; } return sum / FILTER_SIZE; }5.2 元素识别策略
通过电感值变化特征识别特殊赛道元素:
| 元素 | 左电感 | 中电感 | 右电感 | 识别方法 |
|---|---|---|---|---|
| 十字 | 高 | 高 | 高 | 三电感同时高于阈值 |
| 环岛 | 骤升 | 下降 | 骤升 | 侧电感突变,中电感下降 |
| 坡道 | 缓变 | 缓变 | 缓变 | 信号强度持续变化 |
5.3 动态参数调整
根据车速动态调整控制参数:
// 速度自适应PID参数 void update_pid_params(float speed) { if(speed < 1.0) { // 低速模式 Kp = 0.6; Ki = 0.05; Kd = 0.3; } else { // 高速模式 Kp = 0.4; Ki = 0.02; Kd = 0.5; } }6. 完整工程实现
将各模块整合为完整工程时,需注意以下关键点:
初始化顺序:
void main() { DisableGlobalIRQ(); board_init(); // 硬件初始化 pwm_init(10000); // 电机PWM 10kHz Steering_Init(50); // 舵机PWM 50Hz adc_init(); // ADC初始化 pit_timer_ms(TIM_4, 5); // 5ms定时器 EnableGlobalIRQ(); while(1) { // 非实时任务(显示、调试等) } }资源分配建议:
资源 用途 备注 TIM4 5ms系统定时器 中断优先级最高 ADC0 电感信号采集 多通道扫描模式 PWM1 舵机控制 50Hz频率 PWM2-3 电机控制 10kHz频率 调试接口设计:
// 通过串口输出调试信息 printf("L:%d M:%d R:%d E:%d\n", L, M, R, error);
在实际项目中,我们通过优化ADC采样时序,将5ms中断内的处理时间压缩到1.2ms以内,为后续功能扩展留出了充足余地。差比和算法配合适当的PID参数,能使智能车在2m/s速度下稳定循迹。