基于Arduino与LabVIEW的直流电机转速控制系统

2015-09-16 12:47:46   来源:eefocus   

关键字: Arduino  LabVIEW  直流电机  转速控制系统

多数的Arduino控制器都是基于Atmel公司的AVR系列单片机的,AVR单片机的片内资源非常的丰富,有ADC、定时器、外部中断、SPI、IIC、PWM等功能,且Arduino控制器的PWM采用的是定时器相位修正PWM(频率约为490Hz)和快速PWM(频率约为980Hz,Uno的5、6和Leonardo的3、11),这也就导致了全部的定时器都被被占用了,从而不能很方便的使用定时器设置一个中断来实现一个周期的任务,而一般需要通过读取系统已运行时间来判断定时时间是否已经达到。例如,通过增量式编码器来测量电机的转速,常规的单片机的程序架构是通过定时器来实现精确的时间定时,并利用外部中断来实现对脉冲数目的计数,然后计算出一定时间内脉冲的数目,从而得到转速数值并输出。

直流电机是Arduino机器人制作中的主要动力来源,但是由于电机的参数一致性有所差别,即使是相同型号的电机在相同电压下的转速都不完全相同,而且在带负载或负载不同的情况下,更加会导致电机转速发生变化,这就会导致制作的Arduino轮式机器人不能实现直线行走,因为这是一个开环控制,没有任何反馈信号返回。如果给直流电机加上编码器作为反馈器件,也就可以测量得到电机的当前转速,如果将其与设定值计算差值,并通过PID算法计算得到新的控制信号,从而可以动态的测量和控制电机的转速,形成一个闭环控制系统。

下面我们利用带有编码器的直流电机、Arduino控制器、直流电机驱动板和LabVIEW上位机软件以实验探索的形式来设计一个直流电机转速比例控制实验。

1.TimerOne定时器库

1.1下载及使用方法

TimerOne定时器库使用AVR单片机内部的定时器1实现定时中断的功能,其下载地址为:https://code.google.com/p/arduino-timerone/,只需要更改几个参数即可使用定时器中断来实现周期性执行的任务。需要注意的是,如果使用了TimerOne定时器库,也就不能在相应的引脚输出PWM电压,Uno上的定时器与PWM引脚的关系如表1所示。

表1 定时器与PWM引脚的关系

定时器

OC0A

OC0B

OC1A

OC1B

OC2A

OC2B

PWM引脚

6

5

9

10

11

3

TimerOne定时器库函数库中自带的ISRBlink程序如程序代码1所示,可以实现13号管脚上LED的5Hz频率的闪烁。

程序代码1:ISRBlink示例程序

#include

void setup() {

  pinMode(13, OUTPUT);

  Timer1.initialize(100000); //设置定时器中断时间,基本单位为微秒,如设置为100000,则定时时间为0.1秒,频率为10Hz。

  Timer1.attachInterrupt( timerIsr ); // 设置用户自定义的定时器中断服务函数,每发生一次定时器中断,均会执行一次定时器中断服务函数。

}

void loop(){

//主函数,用于执行非周期性任务

}

 

void timerIsr(){

    // 反转I/O口电平

    digitalWrite( 13, digitalRead( 13 ) ^ 1 );

}

1.2评估定时时间的准确性

仅仅凭靠眼睛不能判断定时时间是否准确,下面我们设计一个实验来评估定时时间的准确性。我们需要将上面示例代码中的Timer1.initialize(100000)更改为Timer1.initialize(1000),digitalWrite( 13, digitalRead( 13 ) ^ 1 )更改为digitalWrite(2, digitalRead( 2) ^ 1 ),通过反转I/O的电平实现数字端口2输出500Hz的近似方波。

同时,我们使用NI USB-6009便携式数据采集卡和LabVIEW 2012软件实现一个简易的模拟量采集器,将Arduino 控制器上的数字端口2和GND分别与NI USB-6009便携式数据采集卡上的AI0/AI0+和AI4/AI0-相连接,NI USB-6009便携式数据采集卡接口示意图如图1所示,Arduino Uno控制器与USB-6009便携式数据采集卡的连接图如图2所示。然后使用10kps的采样率,5秒的采样时间的参数采集Arduino 控制器上的数字端口2输出的方波信号,取其前20ms的波形如图3所示,通过波形频率分析工具测量得到其频率为499.901Hz。

另外,我们又将定时时间设置为100微秒、50微秒和25微秒,并使用NI USB-6009便携式数据采集卡和LabVIEW 2012软件以45kps的采样率和2秒的采样时间分别采集了数字端口2输出的波形数据并进行频率分析,得到其频率分别为4999.01Hz,9998.03Hz,19996Hz。从以上数据对比分析可知,定时器的定时时间非常准确,频率测量误差主要来自于I/O反转操作延时导致的。

最后,我们还测试了OCROBOT MEGA 2560控制器、Arduino Uno控制器山寨版输出的500Hz的方波信号频率,分别为500.435Hz和499.764Hz。

 

[转载]基于Arduino与LabVIEW的直流电机转速控制系统(1)

图1 NI USB-6009接口示意图

[转载]基于Arduino与LabVIEW的直流电机转速控制系统(1)

 图2 NI USB-6009与Arduino连接示意图

[转载]基于Arduino与LabVIEW的直流电机转速控制系统(1)

 

图3定时器中断产生的500Hz方波信号

2.转速测量

2.1测量转速方法

测量转速方法有3种,分别为测频法(M法)、 测周法(T法)及混合法(M/T法)。

测频法是在一定时间内,通过测量旋转引起的单位时间内的脉冲数,实现对旋转轴转速测量的一种方法,适用于高、中转速的测量。该法本质上属于定时测角法,为提高测量的准确度,有时采用多标记或开齿的方法,其不确定度主要取决于时间测量和计数量化。

测周法是在转速脉冲的间隔内,用时钟脉冲来测量转速的一种方法,适合于低转速测量。该法实际上就是定角测量法,即用时标填充的方法来测量相当于某一旋转角度的时间间隔。在高、中转速时,可采用多周期平均来提高测量准确度,其不确定度主要取决于时间测量、计数量化及触发的不确定度。

混合法是在测频法的基础上,吸取测周法的优点汇集而成的一种转速测量方法。它是在转速传感器输出脉冲启动定时脉冲的同时,计取传感器输出脉冲个数和时钟脉冲个数,而当到达测量时间时,先停止对传感器输出脉冲的计数,在下一个定时脉冲启动之前再停止时钟脉冲的计数。因此,该种方法可在较宽的范围内使用。

此处,我们选择测频法来测量转速,其工作原理为:当被测信号在特定时间段T内的周期个数为N时,则被测信号的频率f=N/T。

2.2转速测量程序设计

利用TimerOne定时器库来实现定时,通过外部中断对电机编码器输出的脉冲进行计数,计数值除以定时时间即为一定时间内的转速。实现1秒内转速测量的程序如程序代码2所示。

程序代码2:转速测量程序

#include

long counter_val[2] = {0,0};  //定义数组,用于存放外部中断计数值

byte CurCnt = 0;         //定义当前计数器标志,用于判断当前正在计数的数组

int j=0;                          //定义定时器中断标志,用于判断是否发生中断

void setup() {

  delay(2000);

  Serial.begin(115200);//初始化波特率为115200

  attachInterrupt(0, counter, RISING);//设置中断方式为上升沿

  Timer1.initialize(1000000); // 设置定时器中断时间,单位微秒,此处为1秒

  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("S");    //发送帧头大写S

        Serial.print( lTemp);  //发送频率数据,并回车换行

     }

}

 

//外部中断处理函数

void counter()

{

                  //通过当前计数器来实现对外部中断计数值存储的切换

     counter_val[CurCnt& 0x01] += 1;    //发生一次中断则加1

}

 

//定时器中断处理函数

void timerIsr()

{

  j=1;     //置位定时器中断标志位

  CurCnt++; //当前计数器的值加1,实现另一个计数值切换

}

2.3验证频率测量的准确性

前面提到了Arduino的模拟输出(PWM)的频率约为490Hz,且转速测量采用的是测频法,此时用来正好来验证一下程序设计的正确性。在上面的转速测量程序中的void setup()里面delay(2000)之前增加如下代码,以产生方波。串口输出的频率测量结果如图4所示。

[1] [2] [3]
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。
编辑:什么鱼
本文引用地址: http://www.eeworld.com.cn/Test_and_measurement/2015/0916/article_13144.html
[发表评论]
[加入收藏]
[打印本页]
[关闭窗口]
[返回顶部]
[RSS订阅]
小广播
每日新闻
最热点击
本周热门资源推荐
EEWORLD独家
论坛精华
精选博文