我发现这样直接充电会有些慢,所以可以再加上个充电电流取样电阻,用同样的方法控制充电电流的大小,另其恒流充电。或者直接设置个电压,在冲到那个电压前全速充电,到达那个电压后开启PID控制器控制电压。
一直以来看了论坛很多的电炮帖子,一直想要做个多级加速的,材料也买了不少,结果总使因为各种原因耽搁下来。在我爸的鼓励下终于准备设计制作一个多级加速的电磁炮,目前的准备是做一个磁阻炮。在今年五月份的时候其实已经做了一个电磁炮,不过是单极的。当时学校组织了个比赛要求做个两轮平衡车,我感觉光做平衡车没啥意思然后又开板整了个遥控器,缠了个单极的磁阻炮加上云台和上弹装置。我叫它“平衡炮台”。晒一下我的平衡炮台~
咳咳,有些跑题了,但其实在焊这个平衡炮台电路时就有用闭环控制ZVS的想法,就是将被充电电容两端的电压分压后经过运放构成的电压跟随器后由STM32adc采集然后用50HZ的PWM脉宽调制MOS管。这是之前看金坷居士在一篇帖子中提到的,金坷居士:“我目前认为唯一的可能就是低频PWM(50Hz左右,高了照样破坏ZVS,50Hz也会多少破坏)控制ZVS,像我已经实现了ZVS的准闭环,但我还是觉得闭环ZVS有难度,如果要搞调压的软开关电源,还是选择它激方案吧”。只是当时比赛时间有限,加上了电路却没这么用,只是大概延时充电了2秒然后发射。
因为ZVS简单好焊,所以一直以来都是用的普通的ZVS电路。电路在金坷居士的终于驾驭了ZVS这匹烈马!电磁枪升压电路发布!上改的。
在画红圈处加了个10k的电阻,在之前的“平衡炮台”上没加这个电阻,也没配置于与PWM_IN连接的stm32的引脚,然后两个MOS管莫名奇妙就炸了。。。然后只好加一个接地跳线帽,不用时给PWM_IN接地。但现在加上这个10k电阻就没再炸过。画蓝圈的地方最好加上个3.3v稳压管,不然如果电压过高直接进入STM32的ADC采集引脚会把STM32烧坏的(我就烧了一个)。实物图如下:
我没接运放直接分压接到STM32的ADC采集引脚了,因为第一次焊的lm324不管用,没有驱动能力,以为是电路的焊接问题,然后又重新焊了一个,结果还是没有驱动能力。。。然后量了下lLM324输入电阻甚至低到了几百欧姆,因为手里只有双电源运放op07了,所以就没有接运放。
因为STM32的ADC输入电阻最大只有350k,而且受采集速度的影响,速度越快,电阻越小,我把速度调到最慢,用万用表测了下大概是16M左右(知道是不是因为万用表坏了的原因,之前测电压超量程了,之后测什么的电压都会比实际高上一些)所以我感觉不太影响就直接接上了(当然接齐纳二极管了,可不想再烧个32)。
代码就是配置了一路ADC和通用定时器TIM3,ADC在触发转换完成中断时更新全局变量ADC_ConvertedValue的值。考虑到不能让ZVS开启时间太短,又测了该ZVS率是40kHz,所以设置TIM3的预分频(PSC)为7199,自动装载寄存器(ARR)为1999。这样产生的PWM频率为72MHz/(PSC*ARR) = 50HZ,占空比可以在0~2000间调节。
<code>int Voltage_Control(int v_now,int v_want) { static int e_v_integral; int Voltage_pwm = 0; int e_voltage = 0; //电压误差 static int e_voltage_old; //前次电压误差 static int voltage; voltage = voltage *0.7 + v_now*0.3; //滤波 e_voltage = v_want - voltage; //求出误差 e_v_integral += e_v_integral ; //对误差积分 e_v_integral = LIMIT(e_v_integral,10000,10000); //积分限幅 Voltage_pwm = kp * e_voltage + ki*e_v_integral + kd * (e_voltage - e_voltage_old); e_voltage_old = e_voltage; Voltage_pwm = LIMIT(Voltage_pwm,0,2000); //对输出的占空比限幅 return Voltage_pwm; }</code>
<code>int main(void) { /* led 端口配置 */ LED_GPIO_Config(); /* 定时器初始化 */ GENERAL_TIM_Init(); // 配置串口 USART_Config(); // ADC 初始化 ADCx_Init(); TIM3->CCR1 =0; while(1) { TIM3->CCR1 = Voltage_Control(ADC_ConvertedValue,2048); //调节占空比 printf("\r\n%d",ADC_ConvertedValue); Delay(0xffff); } }</code>
写了个简单的PID控制电压函数,在while(1)里循环调用,并把返回值赋值给TIM3通道1的CCR寄存器控制PWM输出的占空比。因为占空比最大是2000,而输入的电压值为0-4096对应0-3.3v(因为32里的ADC是12位的所以是4096)。最大占空比2000除最大误差4096大概是0.48,所以kp大概可以在0.4左右取,调试几个数后发现有过充和低频的电压上下浮动,于是加上kd,然后发现有一直有个静差,果断加上ki,经过几个数的调试后可以达到不错的控制效果,电压在正负2v内变化。
上图是stm32采集到的电压值,看起来还是大概在我设置的2048上的,再仔细调调PID的kp,ki,kd参数估计会有更好的效果。
<strike></strike>
我发现这样直接充电会有些慢,所以可以再加上个充电电流取样电阻,用同样的方法控制充电电流的大小,另其恒流充电。或者直接设置个电压,在冲到那个电压前全速充电,到达那个电压后开启PID控制器控制电压。
没有ir2110之类的半桥驱动,想用两片tc4424再加上隔离电源驱动全桥。算了算参数后做了个反激变压器,是用stm32产生pwm波经过tc4424驱动mos管,整完后测了测有电压输出,挺开心,然后我就想短路下测测电流有多大,结果一短路不知道哪里坏了,变压器巨烫。。。
然后我就感觉太麻烦了就没有继续整。
不过现在想想,也不知道为啥前两天那么执着想做全桥,做个简单的推挽也行,就是不知道给电容充电效果怎么样。
当时是一直有静差才加上积分的,结果还写错了。。。我加限制了,那个LIMIT()就是限幅。不过也写错了应该是
<code>e_v_integral = LIMIT(e_v_integral,-10000,10000);</code>
原来是把e_v_integral限制在10000~10000,刚才看了一遍,刚发现,所以其实积分项并没有起到作用。。。
是考虑过做成隔离的,PWM输出可以用6n137光耦,但是ADC采集端得用线性光耦,我这里只有几个pc817,之前也没有用过,不知道这个电路该怎么设计。
具体还没有用示波器测过,pwm频率不能太大,最小的占空比应比zvs的振荡周期大些,并且两次调节pwm占空比之间的时间也不能设置的太短。我这个在纯zvs不调压的情况下mos管不发热,但是如果开启调压后mos管就会有一定的发热(大概比体温高一些),我感觉我设置的这个还行,可以接受。而且单片机操作方便,可以设置成只在准备好使用时工作,不让其长时间对电容充电,减小发热的损耗。
PS:pwm设置成50hz后能听到哒哒哒的声音,确实也挺烦的。
时段 | 个数 |
---|---|
{{f.startingTime}}点 - {{f.endTime}}点 | {{f.fileCount}} |
200字以内,仅用于支线交流,主线讨论请采用回复功能。