电机编码器测速
下面这篇文章将会告诉你怎么使用Arduino读取外界的数字信号,编码器的一些介绍,还有听起来比较唬人的4倍频的揭秘。
1编码器的介绍
1.1编码器概述
编码器(encoder)是将信号(如比特流)或数据进行编制、转换为可用以通讯、传输和存储的信号形式的设备。
编码器把角位移或直线位移转换成电信号,前者称为码盘,后者称为码尺。
(对于电机测速来说应该需要将角位移转变为电信号,所以应该是码盘。
)按照工作原理编码器可分为增量式和绝对式两类。
增量式编码器是将位移转换成周期性的电信号,再把这个电信号转变成计数脉冲,用脉冲的个数表示位移的大小。
(淘宝上搜“带编码器的电机”大多是这种类型的编码器)绝对式编码器的每一个位置对应一个确定的数字码,因此它的示值只与测量的起始和终止位置有关,而与测量的中间过程无关。
(From 百度百科)
1.2旋转编码器
旋转编码器是一种光电式旋转测量装置,它将被测的角位移直接转换成数字信号(高速脉冲信号)。
编码器如以信号原理来分,有增量型编码器,绝对型编码器。
我们通常用的是增量型编码器,不同型号的旋转编码器,其输出脉冲的相数也不同,有的旋转编码器输出A、B、Z三相脉冲,有的只有A、B相两相,最简单的只有A相。
单相联接,用于单方向计数,单方向测速。
A.B两相联接,用于正反向计数、判断正反向和测速。
A、B、Z三相联接,用于带参考位修正的位置测量。
1.3测速原理
当电机转一圈之后就会输出相应的脉冲设为a,所以我们如果能计算单位时间里的总脉冲数设为x,那么x/a就是单位时间内转的圈数,即转速。
所以我们如果我们想测电机的速度,只需要计算单位时间内的脉冲数,就可以计算转速了。
例如带霍尔编码器的直流电机25GA370的部分参数如下:
编码器如果转一圈呢是11个脉冲。
但是电机外有个减速器,而且减速比是34:1,那么就是电机输出轴转1圈,输入轴就要转34圈。
即电机输出轴转1圈,编码器就要输出11x34=374个脉冲。
至于下面的四倍频我等会介绍。
那么就是如果我们在单位时间t内测出一相有n个脉冲,那么转速=n/(374xt)。
其实上面的计算只用了一相,如果我们要利用上两相的话那该怎么办呢?
这是AB两相的时序图,我们可以看到AB两相相位上相差了90度,本来一个脉冲是4个phase,而且用arduino计算是读取的某一个状态的变化。
所以4个phase用一相的话我们只能读取1个脉冲。
但是如果我们把两相结合起来的话在4个phase中就有4个状态的变化,也就是说如果结合两相我们读取的数值就是一相得4倍。
转速=脉冲数/(4x374xt)。
这就是所谓的软件4倍频功能。
通过读取更多的数值来减少误差。
2相关代码
/** * 日期: 2017/02/28 * 作者: 呆萌阿宝* 描述: 电机测速*/
const int d_time=100;//设定单位时间
int flagA=0;
int flagB=0;//标志位设定
int AM1=2;
int BM1=3;//A相B相输入引脚的定义
int AIN1=7;
int AIN2=8;
int PWMA=9;//AIN1、2和PWMA是电机输出引脚的定义
int valA=0;
int valB=0;//用来储存A相B相记录的脉冲数
double n;//存储转速的变量
unsigned long times;
unsigned long newtime;//时间变量
void go(int g);
void back(int b);
void stay();//电机子函数申明
void setup()
{
Serial.begin(9600);//串口初始化
pinMode(AIN1,OUTPUT);
pinMode(AIN2,OUTPUT);
pinMode(PWMA,OUTPUT);//AIN1、2和PWMA引脚的输出方式 pinMode(AM1,INPUT);
pinMode(BM1,INPUT);//AM1、BM2引脚的输入方式
}
void loop()
{
go(255);//调用go()子函数
newtime=times=millis();
while((newtime-times)<d_time)
{
if(digitalRead(AM1)==HIGH && flagA==0)
{
valA++;
flagA=1;
}
if(digitalRead(AM1)==LOW && flagA==1)
{
valA++;
flagA=0;
}
if(digitalRead(BM1)==HIGH && flagB==0)
{
valB++;
flagB=1;
}
if(digitalRead(BM1)==LOW && flagB==1)
{
valB++;
flagB=0;
}
newtime=millis();
}//计算AB两相的脉冲数
n=(valA+valB)/(1.496*d_time);//计算转速
Serial.print(n);
Serial.println("rad/s");//输出转速数值
valA=valB=0;//清零储存脉冲数的变量
}
/***********************************子函数程序**********************************/ void go(int a)
{
digitalWrite(AIN1,HIGH);
digitalWrite(AIN2,LOW);
analogWrite(PWMA,a);
}
void back(int b)
{
digitalWrite(AIN1,LOW);
digitalWrite(AIN2,HIGH);
analogWrite(PWMA,b);
}
void stay()
{
digitalWrite(AIN1,HIGH);
digitalWrite(AIN2,HIGH);
} [/kenrobot_code]
[kenrobot_code]/**
* 日期: 2017/02/28
* 作者: 呆萌阿宝
* 描述: 我觉得loop那应该可以改一下但是我没办法实验希望大家帮我看看行不行
*/
void loop()
{
go(255);//调用go()子函数
newtime=times=millis();
while((newtime-times)<d_time)
{
if(digitalRead(AM1)==HIGH)
{
valA++;
}
if(digitalRead(BM1)==HIGH )
{
valB++;
}
newtime=millis();
}//计算AB两相的脉冲数
n=(valA+valB)/(1.496*d_time);//计算转速
Serial.print(n);
Serial.println("rad/s");//输出转速数值
valA=valB=0;//清零储存脉冲数的变量
}[/kenrobot_code]
出处:https:///thread-42559-1-1.html。