编码器相关知识及ESP32-Arduino程序

编码器主要分为光电编码器和磁编码器(霍尔编码器)。

 

一、主要原理:

对于编码器来讲,其本质在于测量距离,或者说路程。通过计算转一圈的脉冲个数,从而实现测速。

1.光电编码器:是一种通过光电转换将输出轴上的机械几何位移量转换成脉冲或数字量的传感器。这是目前应用最多的传感器,光电编码器是由光源、光码盘和光敏元件组成。光栅盘是在一定直径的圆板上等分地开通若干个长方形孔。由于光电码盘与电动机同轴,电动机旋转时,光栅盘与电动机同速旋转,经发光二极管等电子元件组成的检测装置检测输出若干脉冲信号,通过计算每秒光电编码器输出脉冲的个数就能反映当前电动机的转速。此外,为判断旋转方向,码盘可以包含AB相,相位差相差90度。

编码器相关知识及ESP32-Arduino程序   编码器相关知识及ESP32-Arduino程序    编码器相关知识及ESP32-Arduino程序

2. 霍尔编码器: 是一种通过磁电转换将输出轴上的机械几何位移量转换成脉冲或数字量的传感器。霍尔编码器是由霍尔码盘和霍尔元件组成。霍尔码盘是在一定直径的圆板上等分地布置有不同的磁极。霍尔码盘与电动机同轴,电动机旋转时,霍尔元件检测输出若干脉冲信号,为判断转向,一般输出两组存在一定相位差的方波信号。

     编码器相关知识及ESP32-Arduino程序

编码器相关知识及ESP32-Arduino程序

优缺点: 光电编码器相对于霍尔编码器来说,多数在恶劣环境下无法使用,而且体积也比较大。此外,光电编码器精度不高,主要是由于码盘(光栅)无法划分的太细。但是,在磁场环境下,光电编码器不受磁场的影响。如果磁场不是很强的话,霍尔编码器可以采用磁屏蔽的方法(顺磁性材料:铁、坡莫合金。抗磁材料:热解石墨)。

 

二、    编码器参数:(以霍尔编码器为例)

             编码器相关知识及ESP32-Arduino程序

基础脉冲数:指的是转一圈的脉冲个数。

磁环触发极数:14极指的是一共14个N/S极,总共7对。

其余参数很容易理解。

 

三、 测速方法:  位置差分法(即M法)/ 定角测时法(即T法)/    M/T法

根据脉冲计数来测量转速的方法有以下三种:
(1)在规定时间内测量所产生的脉冲个数来获得被测速度,称为M法测速;
(2)测量相邻两个脉冲的时间来测量速度,称为T法测速;
(3)同时测量检测时间和在此时间内脉冲发生器发出的脉冲个数来测量速度,称为M/T法测速。

1. M法

编码器相关知识及ESP32-Arduino程序

2. T法

编码器相关知识及ESP32-Arduino程序

3. M/T法

为了兼顾高速与低速,实际使用中常常是 M 法和 T 法结合使用,称为 M/T 法测速。

M法、T法结合的 M/T 测速法:低速时测周期、高速时测频率。

 

四、判断正反转

针对具有AB两相的编码器。  只需要看QEP_A和QEP_B。AB具有90度的相位差,通过判断两者上升沿或者下降沿的关系即可。

编码器相关知识及ESP32-Arduino程序

假设QEP_A触发为高电平,QEP_B为低电平时为正转,反之为反转。

 

五、实验程序 (M法测速)     ESP32-Arduino

通过定时中断,记录一段时间内的脉冲数从而计算出速度。

#include<Ticker.h>

#define PI 3.1415926

/***************** 定时中断参数 *****************/
Ticker timer1;  // 中断函数
int interrupt_time = 10; // 中断时间
int timer_flag=0;               //定时器标志;
 
/***************** 编码器引脚及参数 *****************/
uint8_t R1 = 18, R2=19;    // 右轮编码器引脚
uint8_t L1 = 26, L2=25;    // 左轮编码器引脚   左右轮区分是以锂电池为底部区分
volatile long Rcounter1=0, Rcounter2=0; // 右轮脉冲计数  该变量用于存储编码器的值,所以用类型修饰符volatile;
volatile long Lcounter1=0, Lcounter2=0; // 左轮脉冲计数  该变量用于存储编码器的值,所以用类型修饰符volatile;


// void right_counter_encoder1(); // 右轮1 计数脉冲数
// void right_counter_encoder2(); // 右轮2 计数脉冲数
// void left_counter_encoder1();  // 左轮1 计数脉冲数   
// void left_counter_encoder2();  // 左轮2 计数脉冲数   

void setup()

{

   Serial.begin(115200);

/***************** 编码器初始化 *****************/
  pinMode(L1, INPUT);    pinMode(L2, INPUT);   
  pinMode(R1, INPUT);    pinMode(R2, INPUT);  
  attachInterrupt(R1, right_counter_encoder1, RISING);//设置编码器R1相位上升沿中断
  attachInterrupt(R2, right_counter_encoder2, RISING);//设置编码器R2相位上升沿中断      
  attachInterrupt(L1, left_counter_encoder1, RISING);//设置编码器L1相位上升沿中断
  attachInterrupt(L2, left_counter_encoder2, RISING);//设置编码器L2相位上升沿中断
   
/***************** 定时中断 *****************/   
  timer1.attach_ms(interrupt_time, timerIsr);  // 打开定时器中断
  interrupts();                      //打开外部中断  

}

void loop()

{

if(timer_flag==1)

{        //判断是否发生定时器中断,这里是 interrupt_time ms发生一次
      timer_flag=0;       //清除标记
 }

}

//定时器中断处理函数,其功能主要为了输出编码器得到的数据
void timerIsr(){
   timer_flag=1;  //定时时间达到标志      
   readEncoder();   // 编码器
}

//编码器输出  mm
void readEncoder(){
  float L = Lcounter1/7/238*2*PI;  // 编码器旋转的角度(rad)编码器旋转一圈7个脉冲,减速比为238,
  float R = Rcounter1/7/238*2*PI; // 右轮
  Serial.print("左轮旋转的角度为:  ");  Serial.println(L);

//数值清零,重新计数
  Rcounter1 = 0; Rcounter2 = 0;   
  Lcounter1 = 0; Lcounter2 = 0;
}

 

// 编码器计数
void right_counter_encoder1(){  //右轮计数
    Rcounter1++;
  }
void right_counter_encoder2(){
    Rcounter2++;
  }
void left_counter_encoder1(){  // //左轮计数
    Lcounter1++;
  }
void left_counter_encoder2(){
    Lcounter2++;
  }