Timer1.initialize(10000); //设置定时器中断时间,单位微秒
Timer1.attachInterrupt( timerIsr ); //打开定时器中断
interrupts();//打开外部中断
}
void loop()
{
long lTemp = 0; //定义临时存储数据变量
if(j==1)//判断是否发生定时器中断,即定时时间是否到达
{
j=0;//清除定时器中断标志位
if((CurCnt&0x01) == 0) //当前使用的是偶数计数器,则上次频率值存放在第二个元素中
{
lTemp = counter_val[1];//读取数组第二个元素中的数值
counter_val[1]=0;//读完清除原来的数值,以便下次使用
}
else//当前使用的是奇数计数器,则上次频率值存放在第一个元素中
{
lTemp = counter_val[0];//读取数组第二个元素中的数值
counter_val[0]=0;//读完清除原来的数值,以便下次使用
}
Serial.print("A");//发送转速帧头大写A
Serial.print( lTemp);//发送转速数据
output_value =( set_point -lTemp)*Kp+ output_value;//比例计算得到控制量
if(output_value >255) //限制PWM在0-255范围内
output_value =255;
if(output_value <0) //限制PWM在0-255范围内
output_value =0;
analogWrite(3, output_value);//将计算得到的控制量输出
Serial.print("B");//发送PWM帧头大写B
Serial.println(output_value);//发送PWM数据
}
}
//外部中断处理函数
void counter()
{
counter_val[CurCnt& 0x01] += 1;//每一个中断加一
}
//定时器中断处理函数
void timerIsr()
{
j=1;//定时时间达到标志
CurCnt++; //切换计数数组
}
通过串口输出的电机实际转速与PWM值的数据如图11和图12所示。其中图11为系统刚启动的时候,此时可以看出电机逐渐上升,达到128之后逐渐降至100以下,这属于系统初期的振荡;图12是系统运行一段时间之后的转速和PWM数据,转速稳定在100±2,PWM稳定在145左右。
图11 PWM为80时转速数据
图12 PWM为255时转速数据
图11和图12中的串口输出数据看起来没有图形那么直观,为此我们使用LabVIEW2012和VISA 5.3编写一个转速显示程序。前面板如图13所示,程序框图如图14所示,其中的数据解析子VI的程序框图如图15所示,其功能是解析出串口数据中的转速值和PWM值。
除了上位机显示程序之外,我们还需要对转速的比例控制程序进行部分修改,具体如下:
将
Serial.print( lTemp);//发送转速数据
修改为
if((lTemp/100) ==0)
{
Serial.print( 0);
if((lTemp0/10) == 0)
Serial.print( 0);
}
Serial.print( lTemp);
将
Serial.println(output_value);//发送PWM数据
修改为
if((output_value /100) ==0)
{
Serial.print( 0);
if((output_value 0/10) == 0)
Serial.print( 0);
}
Serial.print(output_value);
图13 LabVIEW上位机前面板
图14 LabVIEW上位机程序框图
图15数据解析程序框图
在LabVIEW上位机软件上选择Arduino Uno控制器对应的串口号,即可将电机的转速和PWM值实时的显示在LabVIEW前面板上,如图16所示。
图16转速和PWM显示在LabVIEW上位机上
|