|
极简陋的模拟电路 (原文件名:磁悬浮(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个线圈中间的空隙,高度约在线圈中部,需注意霍尔作用面应位于线圈中轴线上,不应采用图中虚线标示的安装方式,否则会造成定位误差。
磁环置于电路板下面,需要注意的是磁环的放置会影响霍尔输出,因此运放输出中点调节最好配合磁环定位同时调节。
|
|
|