基于51单片机电机PWM直流可逆调速系统原理图

基于51单片机电机PWM直流可逆调速系统原理图,第1张

首先弄清楚pid是一种控制算法!!!

1,“如果用单片机恒温可以使温度到达预定值就停止加热,低了就加热,用一个温度传感器反馈,这样算是一个自动控制吗”你这是控制系统,但是效果会非常差,尤其是对于温度控制这种大惯性系统,达到预定值就停止加热,但是由于惯性,温度肯定会继续上升,电炉烧水的时候,水开了,断电之后水还要沸腾一定时间的(沸腾是很消耗能量的,由此可见如果是加热的话温度上升更严重,你也可以自己用温度计试试看);“低了就加热”是同样的道理。如果系统对控制精度有要求,你这样做肯定达不到要求。pid是一种控制算法,相对于其他控制算法来说算是最简单的了。pid能够做到在温度快要达到设定值的时候降低加热功率,让温度上升速度变慢,最终稳定在设定值。如果用你的直接控制,温度会在设定值上下振荡,永远不会停在设定值。

2,一般的控制系统都需要加反馈,以构成闭环控制系统,相对的还有开环控制系统。开环控制系统,举个例子,就是你加热的时候事先计算好大约需要多少热量,然后考虑一下环境影响,计算出加热时间,然后控制加热系统按照你这个时间加热。你觉得这样的系统能够稳定工作吗?环境稍稍有变动就挂了!开环控制系统的特点就是很容易受到环境的影响;闭环控制系统就稳定很多,你用1l水可用,2l水也行,500w电能用,1000w电炉也能用,这就是闭环的优点。

因此,大多数的控制系统都是闭环的,开环很少单独使用,即使用到了也是有闭环的。开环其实也是有优点的,开环在控制系统里面叫做前馈(跟反馈对应的),比如你的系统里面电源电压上升了,加热速度肯定会变快,如果你对电源电压采样,将采样的结果输入到闭环里面,对闭环做一个轻微的修正,控制的精度会更好,这就是开环的优势,它是超前的,能够预知结果(根据地源电压提高就能知道需要降低输出功率了)。

说完这些,你应该明白了,反馈是必需的(前馈也可以要,但是不是必需的),pid不能被取代(除非你用其它更复杂的控制算法)。

#include <avr/io.h>

void main(void)

{

PORTB=0x00

DDRB=0x0E

// T/C1 初始化

TCCR1A=0xA1

TCCR1B=0x09 //匹配时清零,TOP:255,频率:8M/256=31.25K

OCR1A=85 //占空比:1/3

OCR1B=128 //占空比:1/2

// T/C2 初始化

TCCR2=0x69 //匹配时清零,TOP:255,频率:31.25K

OCR2=170 //占空比:2/3

while (1)

}

使用M16产生三路PWM的程序,参考一下基本OK

还有个是可调节的PWM程序,我做过仿真了,需要全部留下邮箱传给你

/*****************************************************

#define KEY PINC.0

#define PWMA PORTB.3 //17号脚

#define PWMB PORTB.4 //18号脚

#include <mega8.h>

#include <delay.h>

#include <math.h>

unsigned int m=0

unsigned char xiangxian=0

bit INIT2=0//判断是否象限2已经初始化;

bit INIT3=0

bit INIT4=0

/*下面为四个象限中处理函数,参数为45度平分为255段角度*/

inline panduan()

{

if(m<=255)

{

xiangxian=1

}

else if((m>255)&&(m<511))

{

xiangxian=2

if(m==256)

{

INIT2=1

PWMA=0

OCR1A=0x00

OCR1B=0xff

PWMB=1

}

}

else if((m>=511)&&(m<767))

{

xiangxian=3

}

else if((m>=767)&&(m<1024))

{

xiangxian=4

}

else if(m>1024)

{

m=0

}

}

void xiangxian1(unsigned char degree)

{

PWMA=0

PWMB=0

OCR1BL=m

OCR1AL=255-m

}

void xiangxian2(unsigned char degree)

{ unsigned char temp

temp=m-255

OCR1AL=temp

OCR1BL=temp

}

void xiangxian3(unsigned char degree)

{

unsigned char temp

temp=m-511

PWMA=1

PWMB=1

OCR1BL=255-temp

OCR1AL=temp

}

void xiangxian4(unsigned char degree)

{unsigned char temp=0

temp=m-767

PWMA=1

PWMB=0

OCR1BL=255-temp

OCR1AL=255-temp

}

/*角度计算函数,负责计算在各个象限中角度对应的PWM输出*/

void SET_ANGLE( unsigned char degree)

{

switch (xiangxian)

{

case 1: xiangxian1(degree)break

case 2: xiangxian2(degree)break

case 3: xiangxian3(degree)break

case 4: xiangxian4(degree)break

default:break

}

}

void main(void)

{

unsigned char temp

unsigned char xiangxian=0

// Declare your local variables here

PORTB=0x187

DDRB=0x1e

// Port C initialization

// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In

// State6=T State5=T State4=T State3=T State2=T State1=T State0=P

PORTC=0x01

DDRC=0x00

// Port D initialization

// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=Out Func1=In Func0=In

// State7=T State6=T State5=T State4=T State3=T State2=0 State1=T State0=T

PORTD=0x00

DDRD=0x04

// Timer/Counter 0 initialization

// Clock source: System Clock

// Clock value: Timer 0 Stopped

TCCR0=0x00

TCNT0=0x00

// Timer/Counter 1 initialization

// Clock source: System Clock

// Clock value: 1000.000 kHz

// Mode: Fast PWM top=01FFh

// OC1A output: Inverted

// OC1B output: Inverted

// Noise Canceler: Off

// Input Capture on Falling Edge

// Timer 1 Overflow Interrupt: Off

// Input Capture Interrupt: Off

// Compare A Match Interrupt: Off

// Compare B Match Interrupt: Off

TCCR1A=0xF1

TCCR1B=0x01

TCNT1H=0x00

TCNT1L=0x00

ICR1H=0x00

ICR1L=0x00

OCR1AH=0x00

OCR1AL=0x00

OCR1BH=0x00

OCR1BL=0x00

// Timer/Counter 2 initialization

// Clock source: System Clock

// Clock value: Timer 2 Stopped

// Mode: Normal top=FFh

// OC2 output: Disconnected

ASSR=0x00

TCCR2=0x00

TCNT2=0x00

OCR2=0x00

// External Interrupt(s) initialization

// INT0: Off

// INT1: Off

MCUCR=0x00

// Timer(s)/Counter(s) Interrupt(s) initialization

TIMSK=0x00

// Analog Comparator initialization

// Analog Comparator: Off

// Analog Comparator Input Capture by Timer/Counter 1: Off

ACSR=0x80

SFIOR=0x00

PWMA=0

PWMB=0

OCR1AL=0xff

OCR1BL=0x00

while (1)

{

if(KEY==0)

{

delay_ms(20)

if(KEY==0)

{

m=m+1

panduan()

SET_ANGLE(m)

PORTD.2=!PORTD.2

}

}

}

}

你那个地方不明白?能具体说说吗?我看程序已经有不少注释了啊?

下面的比较多,复杂些,先简单的说下吧:

一、加速减速,就是增加或减少脉冲宽度,改变电机速度!脉冲的宽度由

1、CLK=0的状态持续,由T1的定时决定;

2、CLK=1的状态持续,由(T0-T1)的时间决定;

二、定时器中断TH0=0x00    TL0=0x00 

1、T0定时器工作1方式,T0定时器启动后,从TH0、TL0赋值的计数值开始增加,增加到0XFFFF后,T0中断!

2、T0溢出后(中断),T0计数器不会自动停止,所以需要重新给T0定时器赋值!赋值后,进入下一个计数周期!

3、例子中,T0定时器从0x0000开始计数,也就是增加0xFFFF后进行中断!定时时间为 (0xFFFF / ( 晶振周期/12 ))) 秒,若晶振为12M,则定时为,65.536ms!

分析程序,从main开始分析,先将起始开始的时序图画出:

如下图!

从时序图可以看出,CLK为PWM输出,

1、CLK=0的状态持续,由T1的定时决定;

2、CLK=1的状态持续,由T0-T1的时间决定;

而   main   函数中的  while(1)   部分,进行的就是PWM调整程序。

1、  if (K3==0)   //高电平逆时钟转,低电平顺时钟转

{

ZF=0

}

else

{

ZF=1

}

根据程序推测,程序若为电机控制,K3开关为0时,ZF=0,顺时针转,K3开关为1时,ZF=1,逆时针转。

2、

if(K1==0)   //按下加速键

{

delay(1)

PWML++   //调宽值低四位加1

if(PWML==0x00)

{

PWMH++

}   //调宽值高四位加1

if (PWMH==0xFF) //最大值时

{

PWMH=0xFE

}

}

K1按键,加速按键,增加T1定时器计数起始时间,也就是减少T1计数时间,减少CLK=0的时间。

3、

if(K2==0) //按下减速键

{

delay(1)

PWML--    //调宽值低四位减1

if (PWML==0x00)

{

PWMH--

}    //调宽值高四位减1

if (PWMH==0x00)

{

PWMH=0x01

}   //最小值时

}

K2按键,减速按键,降低T1定时器计数起始时间,也就是增加T1计数时间,增加CLK=0的时间。

4、不论加速、减速,T0的时间都不变,CLK=0和CLK=1总持续时间不变{ (Tclk0+Tclk1)=T0 }。

程序不难,图不好画啊!


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12052922.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-20
下一篇 2023-05-20

发表评论

登录后才能评论

评论列表(0条)

保存