![]() 极简陋的模拟电路 (原文件名:磁悬浮(STM8 PWM).png) 源代码(STVD + Cosmic)ourdev_511866.zip(文件大小:53K) (原文件名:maglev_stm8.zip) 悬浮视频ourdev_511458.zip(文件大小:1.41M) (原文件名:maglev.zip) 电路基于ST三合一开发板的STM8S Mini Kit,ADC基准电压3.3V。 STM8使用内部16MHz RC振荡,分频比为1,核心频率16MHz。 ADC2时钟分频比为12,频率1.333MHz,工作在单次采样模式,采样时间为14 * 0.75?s + 7?s = 17.5?s,加上中断处理时间,采样率约为55KS/s。 TIM1时钟分频比为4,频率4MHz,计数器TOP值(ARR)为999,因此PWM频率为4KHz。 完成初始化后,主程序进入死循环,系统完全依赖中断服务例程运作。 设计要点详解: 1.ADC2采样完成(EOC)中断 <pre>/* * ADC2 End Of Conversion interrupt handler * Positions are filtered by a 7th-order moving average filter. */ @far @interrupt void ADC2_IRQHandler(void) { static u8 xFilterPos, yFilterPos; static s16 xFilterBuf[8] = {0, 0, 0, 0, 0, 0, 0, 0}; static s16 yFilterBuf[8] = {0, 0, 0, 0, 0, 0, 0, 0}; s16 adcValue, acc = 0; u8 i; adcValue = ADC2_GetConversionValue(); if (currentChannel == ADC2_CHANNEL_6) { xFilterBuf[xFilterPos & 7] = adcValue; xFilterPos++; for (i = 0; i < 8; i++) { acc += xFilterBuf; } xPos = acc >> 3; currentChannel = ADC2_CHANNEL_7; } else { yFilterBuf[yFilterPos & 7] = adcValue; yFilterPos++; for (i = 0; i < 8; i++) { acc += yFilterBuf; } yPos = acc >> 3; currentChannel = ADC2_CHANNEL_6; } // Switch the channel and start new conversion. ADC2_ClearFlag(); ADC2_ConversionConfig(ADC2_CONVERSIONMODE_SINGLE, currentChannel, ADC2_ALIGN_RIGHT); ADC2_StartConversion(); }</pre> EOC中断轮流采集CH6和CH7通道的数据,并对采样值进行7阶移动平均滤波,结果存放于xPos和yPos变量。 2.TIM1更新/溢出中断 <pre>/* * TIM1 update/overflow interrupt handler * This IRQ is executed every 250us. */ @far @interrupt void TIM1_UPD_OVF_TRG_BRK_IRQHandler(void) { static u8 direction; s16 xError, yError; s16 xPWM, yPWM; // Change X direction if (direction & X_DIRECTION_FLAG) { GPIO_WriteHigh(GPIOC, GPIO_PIN_3); } else { GPIO_WriteLow(GPIOC, GPIO_PIN_3); } // Change Y direction if (direction & Y_DIRECTION_FLAG) { GPIO_WriteHigh(GPIOC, GPIO_PIN_5); } else { GPIO_WriteLow(GPIOC, GPIO_PIN_5); } // PID calculation xError = xPID.targetValue - xPos; yError = yPID.targetValue - yPos; xPWM = calcPID(&xPID, xError); yPWM = calcPID(&yPID, yError); // Set the direction and OC polarity based on the PID output (takes effect on next PWM cycle) if (xPWM >= 0) { direction &= (u8) ~X_DIRECTION_FLAG; TIM1_OC1PolarityConfig(TIM1_OCPOLARITY_LOW); } else { direction |= X_DIRECTION_FLAG; xPWM = -xPWM; TIM1_OC1PolarityConfig(TIM1_OCPOLARITY_HIGH); } if (yPWM >= 0) { direction &= (u8) ~Y_DIRECTION_FLAG; TIM1_OC2PolarityConfig(TIM1_OCPOLARITY_LOW); } else { direction |= Y_DIRECTION_FLAG; yPWM = -yPWM; TIM1_OC2PolarityConfig(TIM1_OCPOLARITY_HIGH); } // Update the PWM (takes effect on next PWM cycle) TIM1_SetCompare1(xPWM); TIM1_SetCompare2(yPWM); TIM1_ClearITPendingBit(TIM1_IT_UPDATE); }</pre> TIM1更新/溢出中断每个PWM周期开始时(250?s)执行一次,每次执行会根据当前xPos和yPos进行PID运算和更新PWM占空比。10-bit ADC采样范围0~1023,因此PID的参考点设在中点511。 为了防止更新占空比造成当前PWM周期占空比不正常,输出比较器使用了预载功能,即更新会在下一个PWM周期才生效。 控制方向根据PID运算结果的符号来判断,保存在direction变量中,在下一个PWM周期才对应更新GPIO的输出状态,与PWM占空比更新同步。 PWM控制时序如下图(只画了X轴,Y轴同理): ![]() PWM时序 (原文件名:磁悬浮(PWM时序).png) 当PID输出为正数时,PC3输出低电平,PC1/TIM1_CC1输出高电平有效的PWM脉冲。 当PID输出为负数时,PC3输出高电平,PC1/TIM1_CC1输出低电平有效的PWM脉冲,图中T3为占空比20%的PWM,T4为占空比40%的反向输出PWM。 结合L293D,图中T1, T2周期输出占空比20%的正向PWM至线圈,而T3, T4周期分别输出20%和40%占空比的反向PWM至线圈,从而实现双向磁场控制。 3.PID参数 <pre> xPID.Kp = 4; xPID.Ki = 0; xPID.Kd = 30; xPID.integrationError = 0; xPID.prevError = 0; xPID.targetValue = 511;</pre> 由上面的代码可见,本系统只使用了PD控制,Ki为0,积分项不参与计算。Kp, Kd的值需要根据悬浮物的质量调整,整定方法可参考有关资料,这里就不详述了。 4.霍尔采样电路 霍尔采样电路采用了2片有源线性霍尔UGN3503,后接一级运放反相放大器,放大倍数为30倍,并且由一个10K多圈电位器调整输出中点电平。 运放和霍尔使用5V单电源供电,UGN3503的输出中点电压约2.5V,运放LM324输出电压范围约50mV~3.6V,因此STM8的ADC参考电压使用3.3V,分别调整10K电位器使LM324输出1.65V,此时STM8的ADC采样结果应该接近511,误差虽然越小越好,但不需要绝对准确(霍尔、运放都有温漂,不可能绝对准确),一般调整至480~550范围内即可。 5.硬件安装 ![]() 线圈及霍尔安装 (原文件名:磁悬浮(线圈及霍尔安装).png) 每组两个线圈同名端相连(即反向串接)。霍尔置于4个线圈中间的空隙,高度约在线圈中部,需注意霍尔作用面应位于线圈中轴线上,不应采用图中虚线标示的安装方式,否则会造成定位误差。 磁环置于电路板下面,需要注意的是磁环的放置会影响霍尔输出,因此运放输出中点调节最好配合磁环定位同时调节。 |
欢迎光临 中科因仑“3+1”工程特种兵精英论坛 (http://bbs.enlern.com/) | Powered by Discuz! X3.4 |