mega16 电机闭环控制程序
本人新手,用的AVR mega16 想写一个简单的函数。让电机能够在速度为0的时候抱死,即用手拧不动。就用了比例一项。我用的是输入捕获来计算脉冲的数目,同时在输入捕获的中断里面判断AB相的方向,如果正向就脉冲数加1 ,反之减1。现在有点不理解的就是,是否我可以用定时器每隔5个微秒读一下脉冲数和输入捕获里面的定时值。但是这样的话,定时值感觉就没有太大的意义了。不知道应该怎么处理呢?我程序里面写的是脉冲值一个变量,另外一个变量是无论脉冲正反,他都记一次数。记了10次,他就算一下脉冲值(有方向那个)和输入捕获的时间值。但是这样,如果速度为0的话,很有可能那个脉冲值达不到10.想问下有什么好办法吗?
下面是程序://定时器2PWM输出端口在OC2引脚,PC2为码盘B相输入
//电机减速后事150转码盘线数是400
#include<iom16v.h>
#include<macros.h>
#define uint unsigned int
#define uchar unsigned char
/**********************************************
电机速度和转向宏定义
***********************************************/
//定义PC0口为电机正反控制端1
#define CRT1_POWERON PORTC|=BIT(0)
#define CRT1_POWEROFF PORTC&=~BIT(0)
//定义PC1口为电机正反控制端2
#define CRT2_POWERONPORTC|=BIT(1)
#define CRT2_POWEROFF PORTC&=~BIT(1)
//限制最高转速若要求限定最高转速,改变这个值即可
#define speed_MAX 255
//限制最高转速若要求限定最高转速,改变这个值即可
#define speed_MIN 0
/**********************************************
码盘宏定义
码盘M/T法测速:
测速时间内码盘输出的脉冲数m1,又检测同一时间间隔内高频时钟脉冲数m2。
设高频时钟脉冲频率为f0 则测速时间 T=M2/f0;
习惯上转速常以每分钟转数来表示,则电机的转速可表示为:
n=60M1 *f0/(z*M2)r/min
式中,z为电机每转一圈所产生的脉冲数(z=倍频系数×码盘光栅数)
***********************************************/
#defineCRYSTAL80000000//晶振
#defineN 7000 //定义码盘线数
#defineBEI 1 //倍频数
#defineM1100 //定义每次需测量的码盘输出的脉冲个数
#definef0CRYSTAL/256//定义时钟
#definefeedback 60*time*f0/(N*clknum) //定义码盘反馈的转速
#definesetPWMOCR2 //PWM
//#definedirection PC2 //定义码盘B相,码盘A相接ICP1如果B相为1,则为正,为0 ,则为负
/**********************************************
PID参数宏定义
***********************************************/
#define P100
#define I10
#define D20
float setspeed; //设定转速
uchar direction; //定义方向,1为正,0为反
uint olddata =0;//输入捕获ICP1的旧读数
uint newdata=0;//输入捕获ICP1的读数
uint clknum=0;
int adjPWM; //PID调整后的PWM
int tt; //码盘上升沿次数
float time;//码盘上升沿次数 ,分了方向的
float adjspeed;
//1ms延时,准确性较高
void DelayMs(unsigned int i)
{
while(i--)
{
unsigned int j;
for(j=1;j<=613;j++) ;
}
}
/*-----------------------------------------------------------------
函数名称: void time2_int(void)
函数功能: 定时器2初始化函数
参 数: 无
返 回 值: 无
-----------------------------------------------------------------*/
void time2_int(void)
{
TCNT2=0X01;
OCR2=100;
TCCR2=(1<<WGM20)|(1<<WGM21)|(1<<COM21)|0x06;//快速PWM,256分频,升序清0,降序置1
TIMSK=0XC0; //定时器2溢出中断使能,比较匹配中断使能
}
void PORT_INIT()
{
DDRA|=0XFF;
PORTA|=0;
DDRB|=0XFF;
PORTB|=0;
DDRC|=0XFF&(~(1<<2));
// PORTC|=BIT(0)|BIT(1);
DDRD|=0XFF;
// PORTD|=BIT(7);
}
/*正方向*/
void zheng()
{
CRT1_POWERON;
CRT2_POWEROFF;
}
/*反方向*/
void fan()
{
CRT1_POWEROFF;
CRT2_POWERON;
}
/*停止*/
void stop()
{
CRT1_POWEROFF;
CRT2_POWEROFF;
}
/*正转*/
void forward (float setspeed)
{
if(speed!=0)
{
setPWM=(setspeed*255)/150;//setspeed是想要的转速,这里把它转化成PWM的数字(0~255)
}
zheng();
}
/*反转*/
void reverse (uchar setspeed)
{
if(speed!=0)
{
setPWM=(setspeed*255)/150; //setspeed是想要的转速,这里把它转化成PWM的数字(0~255)
}
fan();
}
/*PID反馈调速*/
void speedadjust()
{
adjspeed=P*(setspeed-feedback);
if(feedback>setspeed)
{
setspeed=adjPWM;
zheng();
// PORTC ^= (1 << PC0);
//PORTC ^= (1 << PC1);
}
else
{
setspeed=adjPWM;
fan();
//PORTC ^= (1 << PC0);
//PORTC ^= (1 << PC1);
}
forward(setspeed);
}
/*
输入捕获初始化
*/
void Timer1_Init(void)
{
TCCR1A = 0x00;
// Input Capture on Falling Edge
TCCR1B = (1<<ICNC1)|(0<<ICES1)|(0<<CS12)|(1<<CS11)|(1<<CS10); //噪声抑制 ,低电平进行捕捉 , 64预分频
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK = (1<<TICIE1); //定时器1 输入捕捉使能
}
//定时器1 输入捕获中断
#pragma interrupt_handler timer1_capt_isr:6
void timer1_capt_isr(void)
{
if( PINC & (1 << 3) ) //读取PC2位,即B相
{time++;}
else
{
time--;
}
tt++;
if(tt==M1)// 100次读一下
{
tt=0;
time=0;
newdata=ICR1;
clknum=newdata-olddata;
olddata=newdata;
}
}
/*读取内部时钟的计数值
void readclk()
{
tt=0;
time=0;
newdata=ICR1;
clknum=newdata-olddata;
olddata=newdata;
}*/
void main()
{
Timer1_Init();
_SEI();//全局中断使能
PORT_INIT();
time2_int();
while(1)
{
forward(0);
speedadjust();
DelayMs(50);
}
} http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=4419728&bbs_page_no=1&search_mode=4&search_text=eworker&bbs_id=9999 avr做电机控制不方便,没有QEP单元,也不好处理码盘jitter的干扰。另外单纯位置闭环是不能做到你的功能的,必须要电流环进行力矩调节才行的。 回复【1楼】eworker
-----------------------------------------------------------------------
哦,我只是想先试试看P的能不能成功,至少有一点效果的吧。然后再加I 进去。因为现在在参加学校比赛,而且马上要考试了。不然就考虑用STM32来做。
页:
[1]