智能车实战——从ADC采集到PWM控制,让电磁车精准循迹
1. 电磁循迹智能车的核心原理电磁循迹智能车的核心在于通过电感感应赛道磁场变化将物理信号转化为电信号再通过控制算法实现精准循迹。整个过程可以分为三个关键环节信号采集、信号处理和运动控制。工字电感是电磁车的眼睛。当电感靠近通有20kHz交流电的赛道导线时由于电磁感应原理电感两端会产生感应电动势。这个电动势的大小与电感距离导线的距离成正比——距离越近感应电压越大距离越远则越小。实测中当电感距离导线10cm时感应电压可能只有几毫伏而距离2cm时电压可达几十毫伏。运放电路则相当于信号的放大器。原始感应信号有两个特点一是幅度太小毫伏级二是交流信号20kHz。常见的处理方案是使用OPA2350或LM358搭建两级运放电路第一级进行选频放大只放大20kHz附近的信号第二级进行峰值检波将交流信号转换为直流电压。经过处理后信号幅度可以达到0-3.3V范围正好匹配单片机的ADC输入要求。2. 信号采集与调理实战2.1 ADC采集配置要点单片机ADC的配置直接影响信号采集质量。以STM32为例推荐采用12位分辨率、软件触发模式并开启DMA传输。采样率不宜过高——20kHz的信号每个周期采样4-8个点足矣。关键配置代码如下// STM32 ADC初始化示例 void ADC_Init(void) { ADC_ChannelConfTypeDef sConfig {0}; hadc1.Instance ADC1; hadc1.Init.ClockPrescaler ADC_CLOCK_SYNC_PCLK_DIV4; hadc1.Init.Resolution ADC_RESOLUTION_12B; hadc1.Init.ScanConvMode ENABLE; hadc1.Init.ContinuousConvMode ENABLE; hadc1.Init.DiscontinuousConvMode DISABLE; hadc1.Init.ExternalTrigConv ADC_SOFTWARE_START; hadc1.Init.DataAlign ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion 2; // 两路电感信号 HAL_ADC_Init(hadc1); sConfig.Channel ADC_CHANNEL_0; // 左电感 sConfig.Rank 1; sConfig.SamplingTime ADC_SAMPLETIME_15CYCLES; HAL_ADC_ConfigChannel(hadc1, sConfig); sConfig.Channel ADC_CHANNEL_1; // 右电感 sConfig.Rank 2; HAL_ADC_ConfigChannel(hadc1, sConfig); }2.2 信号滤波处理原始ADC数据需要经过滤波才能使用。推荐采用移动平均滤波结合低通滤波的方案#define FILTER_LEN 5 int32_t filter_buf[FILTER_LEN]; // 移动平均滤波 uint16_t Moving_Average_Filter(uint16_t new_val) { static uint8_t index 0; static int32_t sum 0; sum - filter_buf[index]; filter_buf[index] new_val; sum new_val; index (index 1) % FILTER_LEN; return (uint16_t)(sum / FILTER_LEN); } // 一阶低通滤波 uint16_t Low_Pass_Filter(uint16_t new_val, uint16_t old_val, float alpha) { return alpha * new_val (1 - alpha) * old_val; }实测表明采用α0.3的低通滤波系数配合5点移动平均可以有效滤除高频干扰同时保持信号的实时性。3. 偏差计算与控制算法3.1 差比和算法详解差比和是电磁车最常用的偏差计算方法公式为偏差 (右电感值 - 左电感值) / (左电感值 右电感值)相比简单的差值法差比和有三大优势消除了电压波动的影响分子分母同比例变化输出范围固定在[-1,1]之间便于控制在赛道边缘也能保持较好的线性度实际编程实现时要注意处理除零问题float Calc_Error(uint16_t left, uint16_t right) { float error; if((left right) 0) error 0; else error (float)(right - left) / (float)(left right); return error; }3.2 PID控制参数整定将偏差输入PID控制器输出转向控制量。PID参数整定建议分三步走先调P比例参数从小值开始逐步增大直到小车出现轻微振荡再调D微分参数抑制振荡通常取P值的1/5到1/10最后调I积分参数消除静态误差但电磁车通常可以不用I项典型参数范围比例P1.0~3.0微分D0.1~0.5积分I0~0.1PID实现代码示例typedef struct { float Kp, Ki, Kd; float error, last_error, integral; } PID_TypeDef; float PID_Calculate(PID_TypeDef *pid, float error) { float output; pid-integral error; // 积分限幅 if(pid-integral 100) pid-integral 100; if(pid-integral -100) pid-integral -100; output pid-Kp * error pid-Ki * pid-integral pid-Kd * (error - pid-last_error); pid-last_error error; return output; }4. PWM输出与电机控制4.1 舵机控制要点电磁车的转向通常由舵机实现。舵机控制有三大关键点PWM频率必须为50Hz周期20ms脉宽范围一般在0.5ms-2.5ms对应0-180°中间位置1.5ms时舵机居中以STM32的PWM配置为例void PWM_Init(void) { TIM_OC_InitTypeDef sConfigOC {0}; htim2.Instance TIM2; htim2.Init.Prescaler 72-1; // 72MHz/721MHz htim2.Init.CounterMode TIM_COUNTERMODE_UP; htim2.Init.Period 20000-1; // 20ms周期 htim2.Init.ClockDivision TIM_CLOCKDIVISION_DIV1; HAL_TIM_PWM_Init(htim2); sConfigOC.OCMode TIM_OCMODE_PWM1; sConfigOC.Pulse 1500; // 初始1.5ms sConfigOC.OCPolarity TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(htim2, sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_Start(htim2, TIM_CHANNEL_1); }4.2 电机驱动技巧电机控制需要注意三个要点PWM频率建议在8-20kHz之间避免产生可闻噪声采用双极驱动正反转时注意设置死区时间电机电源与控制系统电源要隔离防止干扰TB6612驱动芯片的典型配置// 电机方向控制 void Motor_Direction(uint8_t dir) { if(dir FORWARD) { HAL_GPIO_WritePin(IN1_GPIO_Port, IN1_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(IN2_GPIO_Port, IN2_Pin, GPIO_PIN_RESET); } else { HAL_GPIO_WritePin(IN1_GPIO_Port, IN1_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(IN2_GPIO_Port, IN2_Pin, GPIO_PIN_SET); } } // 电机速度控制 void Motor_Speed(uint16_t speed) { __HAL_TIM_SET_COMPARE(htim3, TIM_CHANNEL_1, speed); }5. 系统集成与调试5.1 控制周期优化整个控制流程应该在固定周期内完成典型值为5-10ms。使用定时器中断实现void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim-Instance TIM4) { // 5ms定时器 static uint32_t cnt 0; // 每5ms采集一次电感 if(cnt % 1 0) { ADC_Value ADC_GetValue(); } // 每10ms计算一次控制量 if(cnt % 2 0) { float error Calc_Error(ADC_Value.left, ADC_Value.right); float steer PID_Calculate(steer_pid, error); PWM_SetSteer(steer); } cnt; } }5.2 常见问题排查在调试中经常遇到的问题及解决方案信号干扰表现为ADC值跳动大检查电机PWM频率是否在13-19kHz增加电源滤波电容缩短电感引线长度转向迟钝增大PID的P参数检查舵机机械结构是否顺畅确认PWM脉宽范围是否正确直道抖动适当减小P参数增加D参数检查电感安装是否对称增加软件滤波强度经过这些步骤你的电磁车应该能够稳定循迹了。在实际比赛中还需要针对不同赛道元素如十字、环岛等进行特殊处理这需要根据具体比赛规则进一步优化算法。