1 SPWM波调制技术
逆变电路的控制方式主要是采用SPWM(正弦脉宽调制技术),IR2104控制开关管的通断来实现正弦调制,SPWM的基本思路是将一个正弦波按等宽间距分成N等份,对于每一个波形以一个等面积的脉冲来对应,使脉冲的中点与相应正弦波部分的中点重合,如下图所示,由于此脉冲序列的面积分布满足正弦规率,根据面积等效原理,将这个脉冲序列输出至负载时,将使负载得到相当接近正弦的输出电压和电流。
由于采用该方式输出的电压波形很接近正弦波,所以电压中的谐波成分较少,同时也可以提高功率因数。通过改变SPWM脉冲的宽度可以改变输出电压的幅值,调节电路的调制周期则可以改变输出电压的频率,方便对负载进行控制。
单极性正弦脉宽调制是以一个宽度正弦规律变化的正弦脉冲序列对应交流输出波形的正半周,再以一个宽度按正弦规率变换的负脉冲序列对应交流输出波形的负半周,这两个脉冲序列交替作用,控制开关器件产生近似于正弦波的输出电压波形。
正弦脉宽调制的基本方法是将正弦波性的调制波与三角波形的载波进行比较,通过比较正弦波形各点的瞬时值确定该点对应的脉冲宽度。单极性正弦脉宽调制使用的三角波是单极性的,在正弦调制波为正半周时三角载波是正极性的;在正弦波为负半周时三角波载波为负极性。如下图所示。
双极性正弦脉宽调制是以一个宽度按正弦规率变化的正负双向脉冲序列对应交流输出波形的整个周期,通过正向脉冲与负向脉冲宽度的差产生出按正弦规率变换的正半周波和负半周波。
双极性正弦脉宽调制使用的三角波是双极性的,其波形的形式如下图,通过正弦调制波与三角波比较,当正弦调制波值大于三角波时,输出正脉冲;而当正弦调制波的值小于三角载波时,输出负脉冲。如此得到的脉冲序列是正负交替的双向脉冲序列。
三相正弦脉宽调制可以使用三个相角彼此相差120°的单相调制电路来合成,但是这样会使调制电路结构比较复杂。较简单的方法是采用一个双极性的三角载波对三相正弦调制波进行调制,其调制的波形如下图。
调制过程中,双极性三角载波为三个正弦调制波共用,分别进行比较后获取脉宽调制信号,方式与双极性正弦脉宽调制方法相同。从而得到三个双向的脉冲序列,分别对应A、B、C三相,使用此三个脉冲序列控制逆变电路的A、B、C三相开关元件,可以将直流电压逆变为正弦波的三相交流输出电压。
早期的SPWM采用模拟控制方式来实现,通过信号发生器产生所需的信号,由比较器进行信号之间的比较,随着数字技术和微处理器在SPWM逆变技术中的应用,采用一定算法产生SPWM的数字控制方式越来越广泛。
波形比较法,其基本的方法是由正弦信号发生器件产生正弦调制波,由三角波信号发发生器产生的三角载波,将正弦调制波与三角载波比较,通过比较器的判断而产生出对应的脉冲信号序列,对逆变电路进行控制从而得到所需的交流电压。
(1)等效面积法
其原理就是按面积等效原理构成与正弦波等效的一系列等幅但宽度按正弦规律变化的矩形脉冲。等效面积法适用于单极性控制,算法中计算的是正弦波形到横轴间的面积,这与模拟控制方式中的单极性正弦脉冲调制的方式一致。
(2)自然采样法与规则采样法
自然采样法在算法上仿真模拟控制方式的双极性正弦脉冲调制,通过计算正弦调制波与三角载波的交点位置,确定调制的脉冲宽度。而规则采样法是对自然采样法的简化,其几何关系如下图。
利用单片机输出PWM波,然后让占空比正弦规律变化。
实现步骤可以简单分为三步,以stm32为例:
(1)生成载波。比如要生成一个10KHZ的三角波,将计数器设置加减计数、周期设为1/10K就ok啦。这样生成的三角波的幅值是多少呀,3.3V?其实在单片机里面都是数字信号,三角波最高点的时候可以用一个计数值来表示,比如8400,最低点是0。不用管他的电压是多少。
(2)生成正弦波。这一步用软件生成一个正弦表即可。比如将正弦波取200个点,即将一个正弦分割成200份,每个点代表一个幅值。用离散的数字量表达正弦模拟量。
(3)将正弦波和三角波进行比较。
a.什么时候进行比较。设置计数值达到比较值产生动作。
b.比较完之后,需要改变比较值,用于下一个周期进行比较(比较值可以理解为占空比),比较值查正弦表获得,这样就生成了占空比正弦规律变化的SPWM。
C.调制度m。m=正弦表最大值/三角波最大计数值。如正弦表最大值4200,三角波最大计数值8400,m=4200/8400=0.5,此时spwm最大占空比为50%,设置m=1,spwm最大占空比为100%。
例如我们要生成一个开环的三相spwm。单相逆变需生成两组相差180度的spwm,三相即生成三组两两相差120度的spwm,且每组的spwm都是互补的。将生成的三组spwm分别加到1、2、3组桥臂,每组spwm互补防止了同一桥臂上下管同时导通会引起短路。
int const talab[250]=
{
100 , 102 , 108 , 116 , 126 , 140 , 154 , 172 , 194 , 216 ,
242 , 270 , 300 , 334 , 370 , 408 , 448 , 490 , 536 , 582 ,
632 , 684 , 738 , 794 , 854 , 914 , 976 ,1040 ,1108 ,1176 ,
1246 ,1320 ,1394 ,1470 ,1548 ,1626 ,1708 ,1790 ,1874 ,1960 ,
2046 ,2136 ,2224 ,2316 ,2408 ,2502 ,2596 ,2690 ,2786 ,2884 ,
2982 ,3080 ,3180 ,3280 ,3382 ,3482 ,3584 ,3686 ,3788 ,3892 ,
3994 ,4096 ,4200 ,4304 ,4406 ,4508 ,4612 ,4714 ,4816 ,4918 ,
5018 ,5120 ,5220 ,5320 ,5418 ,5516 ,5614 ,5710 ,5804 ,5898 ,
5992 ,6084 ,6176 ,6264 ,6354 ,6440 ,6526 ,6610 ,6692 ,6774 ,
6852 ,6930 ,7006 ,7080 ,7154 ,7224 ,7292 ,7360 ,7424 ,7486 ,
7546 ,7606 ,7662 ,7716 ,7768 ,7818 ,7864 ,7910 ,7952 ,7992 ,
8030 ,8066 ,8100 ,8130 ,8158 ,8184 ,8206 ,8228 ,8246 ,8260 ,
8274 ,8284 ,8292 ,8298 ,8300 ,8300 ,8298 ,8292 ,8284 ,8274 ,
8260 ,8246 ,8228 ,8206 ,8184 ,8158 ,8130 ,8100 ,8066 ,8030 ,
7992 ,7952 ,7910 ,7864 ,7818 ,7768 ,7716 ,7662 ,7606 ,7546 ,
7486 ,7424 ,7360 ,7292 ,7224 ,7154 ,7080 ,7006 ,6930 ,6852 ,
6774 ,6692 ,6610 ,6526 ,6440 ,6354 ,6264 ,6176 ,6084 ,5992 ,
5898 ,5804 ,5710 ,5614 ,5516 ,5418 ,5320 ,5220 ,5120 ,5018 ,
4918 ,4816 ,4714 ,4612 ,4508 ,4406 ,4304 ,4200 ,4096 ,3994 ,
3892 ,3788 ,3686 ,3584 ,3482 ,3382 ,3280 ,3180 ,3080 ,2982 ,
2884 ,2786 ,2690 ,2596 ,2502 ,2408 ,2316 ,2224 ,2136 ,2046 ,
1960 ,1874 ,1790 ,1708 ,1626 ,1548 ,1470 ,1394 ,1320 ,1246 ,
1176 ,1108 ,1040 , 976 , 914 , 854 , 794 , 738 , 684 , 632 ,
582 , 536 , 490 , 448 , 408 , 370 , 334 , 300 , 270 , 242 ,
216 , 194 , 172 , 154 , 140 , 126 , 116 , 108 , 102 , 100
};
uint16_t Counter_sine1 = 0; //A相
uint16_t Counter_sine2 = 83; //滞后A相120度
uint16_t Counter_sine3 = 166;//超前A相120度
/*TIM1GPIO初始化 CH1--A8 CH2--A9 CH3--A10
CH1N-B13 CH2N-B14 CH3N-B15
*/
void TIM1_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9| GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13| GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
#define CKTIM ((u32)72000000uL) //主频
#define PWM_PRSC ((u8)0) //TIM1分频系数
#define PWM_FREQ ((u16) 10000) //PWM频率(Hz)
#define PWM_PERIOD ((u16) (CKTIM / (u32)(2 * PWM_FREQ *(PWM_PRSC+1))))
#define MODULAT (float)0.7 //调制度
void TIM1_Mode_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_BDTRInitTypeDef TIM1_BDTRInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseStructure.TIM_Period = PWM_PERIOD; //计数周期
TIM_TimeBaseStructure.TIM_Prescaler = PWM_PRSC;//分频系数
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV2;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned1;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //配置为PWM模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能CHx的PWM输出
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;//互补输出使能,使能CHxN的PWM输出
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);//配置CH1
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC2Init(TIM1, &TIM_OCInitStructure); //配置CH2
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC3Init(TIM1, &TIM_OCInitStructure);//配置CH3
//死区时间
TIM1_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM1_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM1_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
TIM1_BDTRInitStructure.TIM_DeadTime = 360; //设置死区时间
TIM1_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
TIM1_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
TIM1_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable;
TIM_BDTRConfig(TIM1, &TIM1_BDTRInitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //4个抢先级、4个子优先级
NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_ITConfig(TIM1,TIM_IT_CC1|TIM_IT_CC2|TIM_IT_CC3,ENABLE); //使能中断
TIM_CtrlPWMOutputs(TIM1, ENABLE); //PWM输出使能
TIM_Cmd(TIM1, ENABLE); //使能TIM1
}
void TIM1_PWM_Init(void)
{
TIM1_GPIO_Config();
TIM1_Mode_Config();
}
//定时器1中断服务函数
void TIM1_CC_IRQHandler(void)
{
if(Counter_sine1>=250) { Counter_sine1 = 0; }
if(Counter_sine2>=250) { Counter_sine2 = 0; }
if(Counter_sine3>=250) { Counter_sine3 = 0; }
if (TIM_GetITStatus(TIM1, TIM_IT_CC1)!=RESET)
{
TIM_SetCompare1(TIM1,(uint32_t)(talab[Counter_sine1])*MODULAT); //A相
Counter_sine1++;
TIM_ClearITPendingBit(TIM1 , TIM_IT_CC1);
}
if (TIM_GetITStatus(TIM1, TIM_IT_CC2) !=RESET)
{
TIM_SetCompare2(TIM1,((uint32_t)talab[Counter_sine2])*MODULAT); //B相
Counter_sine2++;
TIM_ClearITPendingBit(TIM1 , TIM_IT_CC2);
}
if (TIM_GetITStatus(TIM1, TIM_IT_CC3) !=RESET)
{
TIM_SetCompare3(TIM1,(uint32_t)(talab[Counter_sine3])*MODULAT); //C相
Counter_sine3++;
TIM_ClearITPendingBit(TIM1 , TIM_IT_CC3);
}
}
TIM1设置为中央计数模式,开启互补通道,设置死区时间,死区时间是多少个时钟计数周期,比如TIM1计数周期是72M,设置为72就是1000ns。spwm频率设置为10k,然后TIM1每个通道的比较值达到时更新比较值。调制度m范围为0~1,设为0.7。正弦调制波的频率是自己设置的,方法是f=载波频率/表中点数,这里设置的是载波频率10K,取250个点得到的正弦频率就是40HZ,改变载波频率为50*250就得到了50hz的正弦波输出。正弦表可以用取点工具。
在连续时间控制系统中,PID控制器应用非常广泛,其设计技术成熟,长期以来形成了典型的结构,参数整定方便,结构更改灵活。由于计算机程序的灵活性,数字PID控制比连续PID控制更为优越。
连续时间PID控制系统如下图所示,D(s)完成PID控制规律,称为PID控制器。PID控制器是一种线性控制器,用输出量y(t)和给定量r(t)之间的误差的时间函数e(t)=r(t)-y(t)的比例、积分和微分的线性组合构成控制量u(t),称为比例、积分、微分控制,简称PID控制。
PID控制的三基本参数为KP、KI、KD,分别对应比例,积分,微分三个模,经实验测试,可总结出这三项参数的实际控制作用为:
比例调节参数(KP):按比例反映系统的偏差,系统一旦出现偏差,比例调节立即进行。比例调节是主要的控制部分,但过大的比例会使系统的稳定性下降。增大KP,系统的反应变灵敏、速度加快、稳态误差减小,但振荡次数也会加多、调节时间加长。
积分调节参数(KI):消除系统静态(稳态)误差 ,提高系统的控制精度。积分调节会使系统的稳定性下降,动态响应变慢,超调加大。积分控制一般不单独作用,而是与P或者PD结合作用。
微分调节参数(KD):反映系统偏差信号的变化率,可以预见偏差的变化趋势,产生超前控制作用,使偏差在未形成前已被消除。因此,微分控制可以提高系统的动态跟踪性能,减小超调量,但对噪声干扰有放大作用,过强的微分调节会使系统剧烈震荡,对抗干扰不利。
常规的PID控制系统中,减少超调和提高控制精度难以两全其美。主要是积分作用有缺陷造成的。如果减少积分作用,静差不易消除,有扰动时,消除误差速度变慢;而加强积分作用时又难以避免超调,这也是常规PID控制中经常遇到的难题。
P就是比例的意思。它的作用最明显,原理也最简单。
需要控制的量,比如水温,有它现在的『当前值』,也有我们期望的『目标值』。当两者差距不大时,就让加热器“轻轻地”加热一下。要是因为某些原因,温度降低了很多,就让加热器“稍稍用力”加热一下。要是当前温度比目标温度低得多,就让加热器“开足马力”加热,尽快让水温到达目标附近。
这就是P的作用,跟开关控制方法相比,是不是“温文尔雅”了很多.实际写程序时,就让偏差(目标减去当前)与调节装置的“调节力度”,建立一个一次函数的关系,就可以实现最基本的“比例”控制了~
KP越大,调节作用越激进,KP调小会让调节作用更保守。
要是你正在制作一个平衡车,有了KP的作用,你会发现,平衡车在平衡角度附近来回“狂抖”,比较难稳住。如果已经到了这一步——恭喜你!离成功只差一小步了~
D的作用更好理解一些,所以先说说D,最后说i。
刚才我们有了P的作用。你不难发现,只有P好像不能让平衡车站起来,水温也控制得晃晃悠悠,好像整个系统不是特别稳定,总是在“抖动”。
因为我们忽视了一种重要的情况:
还是以热水为例。假如有个人把我们的加热装置带到了非常冷的地方,开始烧水了。需要烧到50℃。
在P的作用下,水温慢慢升高。直到升高到45℃时,他发现了一个不好的事情:天气太冷,水散热的速度,和P控制的加热的速度相等了。这可怎么办?
P兄这样想:我和目标已经很近了,只需要轻轻加热就可以了。
D兄这样想:加热和散热相等,温度没有波动,我好像不用调整什么。
于是,水温永远地停留在45℃,永远到不了50℃。
作为一个人,根据常识,我们知道,应该进一步增加加热的功率。可是增加多少该如何计算呢?
前辈科学家们想到的方法是真的巧妙。设置一个积分量。只要偏差存在,就不断地对偏差进行积分(累加),并反应在调节力度上。这样一来,即使45℃和50℃相差不太大,但是随着时间的推移,只要没达到目标温度,这个积分量就不断增加。
系统就会慢慢意识到:还没有到达目标温度,该增加功率啦!到了目标温度后,假设温度没有波动,积分值就不会再变动。这时,加热功率仍然等于散热功率。但是,温度是稳稳的50℃。
Ki的值越大,积分时乘的系数就越大,积分效果越明显。所以,I的作用就是,减小静态情况下的误差,让受控物理量尽可能接近目标值。
I在使用时还有个问题:需要设定积分限制。防止在刚开始加热时,就把积分量积得太大,难以控制。
数字PID控制是通过算法程序实现PID控制的。数字控制系统大多数是采样数据控制系统,进入系统的连续时间信号必须经过采样和量化后转换为数字量,方能进行相应的计算和处理,不论是积分还是微分,只能用数值计算去逼近。当采样周期相当短时,用求和代替积分,用差商代替微商,将描述连续时间PID算法的微分方程变为描述离散时间PID算法的差分方程。数字PID控制通常有以下两种实现:
当执行机构需要的不是控制量的绝对值,而是控制量的增量(例如驱动步进电动机)时,需要用PID的“增量算法”,其简化示意图如下图所示。
-END-
关于比赛的帖子,之前写过很多篇:
「第一弹」电子设计大赛应该准备什么?
「第一篇」大学生电子设计竞赛,等你来提问。
「第二篇」全国一等奖,经验帖。
「第三篇」电赛,这些你必须知道的比赛细节,文末附上近十年电赛题目下载
「第四篇」电赛控制题可以准备一些什么?
「第五篇」全国电子设计竞赛-电源题设计方案总结
「第六篇」对于电赛,我们应该看重什么?
电子设计竞赛电源题(1)-电源题简介
电子设计竞赛电源题(2)-检波与采样
也有一些大神的经验贴,其实不乏国奖获得者:
全国一等奖,他的学习之路。
从0开始,三个月,获全国一等奖。
奖状是怎么炼成的—我的电赛狂魔之旅
全国一等奖的获得者,如今去当了人民教师。
也有一些关于比赛项目的文章:
参加智能车大赛还是电赛?在做电磁炮中我找到了答案
2019年电赛综合测评题详解
「权威发布」2019年电赛最全各类题目细节问题解答汇总
奖状是怎么炼成的—我的电赛狂魔之旅
【大学生电子设计竞赛分享经验贴】风力循迹小车
去年还做过几期猜题的文章,貌似有点接近了,今年还可以继续给大家猜猜。
「猜题第一篇」2019年大学生电子设计竞赛
「重磅猜题之第二篇」2019年大学生电子设计竞赛
最 后 若觉得文章不错,转发分享,也是我们继续更新的动力。5T资源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,PCB、FPGA、DSP、labview、单片机、等等!在公众号内回复「更多资源」,即可免费获取,期待你的关注~长按识别图中二维码关注