测速编码器

编码器(Encoder)是将一种信息转换为另外一种可以进行传输、通信或者可以采用计算机进行处理的设备。编码器分很多中,本文关注旋转编码器(Rotary Encoder)是用来测量马达旋转速度和角度的装置。

旋转编码器可以分为单相,两相和三相三种,其中AB两相编码器比较常见,它可以做到正反向检测,计数和测速。

其原理比较简单就是旋转的时候A,B产生两路脉冲,不过两路脉冲错开1/4周期,这样根据AB两相检测到的高低脉冲值就可以判断方向和旋转速度。

其基本的计算方法:首先知道编码器转一圈产生r个脉冲,然后得知电机的减速比是s(减速比顾名思义就是为了减速,为了加大电机的扭矩也就是能够输出更大的力量,需要在电机转轴上安装小齿轮带动外面的大齿轮,可以电机转轴旋转s圈外面才输出一圈),所以单位时间t内产生了n个脉冲的话转速等于。

贴一段别人的示例代码,代码的基本意思是AM1与BM1就是两相的输入引脚,通过最后两者的脉冲数之和除以脉冲数*减速比*时间毫秒数/1000获得每秒的转速单位应该是round per second,代码中的rad/s应该是写错了,如果是角速度应该需要再乘以2Pi。另外代码没有判断正转或者反转的逻辑,具体可以参考本文后arduino官网的说明页面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**
* 日期: 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);     
}

有了测速编码器就可以做到测量电机的转速,这样就可以使用PID控制器来将编码器的测量结果作为输入来控制电机的转速,下面的代码使用了官方的PID库:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/********************************************************
* PID Basic Example
* Reading analog input 0 to control analog PWM output 3
********************************************************/

#include <PID_v1.h>

//Define Variables we'll be connecting to
double Setpoint, Input, Output;

//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);

void setup()
{
//initialize the variables we're linked to
Input = analogRead(0);
Setpoint = 100;

//turn the PID on
myPID.SetMode(AUTOMATIC);
}

void loop()
{
Input = analogRead(0);
myPID.Compute();
analogWrite(3,Output);
}

其中Input是测量输入,Setpoint是设定的目标,Output是控制的输出。

参考