1. 程式人生 > >玩平衡車系列——編碼器使用教程與測速原理

玩平衡車系列——編碼器使用教程與測速原理

(基於平衡小車之家標準版)

1.編碼器概述

編碼器是一種將角位移或者角速度轉換成一連串電數字脈衝的旋轉式感測 器,我們可以通過編碼器測量到底位移或者速度資訊。編碼器從輸出資料型別上 分,可以分為增量式編碼器和絕對式編碼器。

從編碼器檢測原理上來分,還可以分為光學式、磁式、感應式、電容式。常 見的是光電編碼器(光學式)和霍爾編碼器(磁式)。

2.編碼器原理

光電編碼器是一種通過光電轉換將輸出軸上的機械幾何位移量轉換成脈衝或數字量的感測器。光電編碼器是由光碼盤和光電檢測裝置組成。光碼盤是在一 定直徑的圓板上等分地開通若干個長方形孔。由於光電碼盤與電動機同軸,電動機旋轉時,檢測裝置檢測輸出若干脈衝訊號,為判斷轉向,一般輸出兩組存在一 定相位差的方波訊號。

霍爾編碼器是一種通過磁電轉換將輸出軸上的機械幾何位移量轉換成脈衝或數字量的感測器。霍爾編碼器是由霍爾碼盤和霍爾元件組成。霍爾碼盤是在一 定直徑的圓板上等分地佈置有不同的磁極。霍爾碼盤與電動機同軸,電動機旋轉時,霍爾元件檢測輸出若干脈衝訊號,為判斷轉向,一般輸出兩組存在一定相位差的方波訊號。

可以看到兩種原理的編碼器目的都是獲取 AB 相輸出的方波訊號,其使用方法也是一樣,下面是一個簡單的示意圖。

3.編碼器接線說明

具體到我們的編碼器電機,我們可以看看電機編碼器的實物。

這是一款增量式輸出的霍爾編碼器。編碼器有 AB 相輸出,所以不僅可以測 速,還可以辨別轉向。根據上圖的接線說明可以看到,我們只需給編碼器電源5V 供電,在電機轉動的時候即可通過 AB 相輸出方波訊號。編碼器自帶了上拉電阻,所以無需外部上拉,可以直接連線到微控制器 IO 讀取。

4.編碼器軟體四倍頻技術

下面我們說一下編碼器倍頻的原理。為了提高大家下面學習的興趣,我們先明確,這是一項實用的技術,可以真正地把編碼器的精度提升 4 倍。作用可類比 於單反相機的光學變焦,而並非犧牲清晰度來放大影象的數碼變焦。OK,先看看下面編碼器輸出的波形圖。

這裡,我們是通過軟體的方法實現四倍頻。首先可以看到上圖編碼器輸出的AB 相波形,正常情況下我們使用 M 法測速的時候,會通過測量單位時間內 A 相輸出的脈衝數來得到速度資訊。常規的方法,我們只測量 A 相(或 B 相)的上升 沿或者下降沿,也就是上圖中對應的數字 1234 中的某一個,這樣就只能計數 3次。而四倍頻的方法是測量 A 相和 B 相編碼器的上升沿和下降沿。這樣在同樣的 時間內,可以計數 12 次(3 個 1234 的迴圈)。這就是軟體四倍頻的原理。

我將一些初始化函式給粘貼出來

**************************************************************************/
/**************************************************************************
函式功能:把TIM2初始化為編碼器介面模式
入口引數:無
返回  值:無
**************************************************************************/
void Encoder_Init_TIM2(void)
{
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;  
  TIM_ICInitTypeDef TIM_ICInitStructure;  
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能定時器2的時鐘
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PB埠時鐘
	
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;	//埠配置
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空輸入
  GPIO_Init(GPIOA, &GPIO_InitStructure);					      //根據設定引數初始GPIOB
  
  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 預分頻器 
  TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //設定計數器自動重灌值
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//選擇時鐘分頻:不分頻
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;////TIM向上計數  
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
  TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, 
  TIM_ICPolarity_Rising);//使用編碼器模式3,模式3就我們在這裡所說的4倍頻,詳細資訊檢視stm32f1技術手冊

  TIM_ICStructInit(&TIM_ICInitStructure);
  TIM_ICInitStructure.TIM_ICFilter = 10;
  TIM_ICInit(TIM2, &TIM_ICInitStructure);

  TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除TIM的更新標誌位
  TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
  //Reset counter

  TIM_SetCounter(TIM2,0);
  TIM_Cmd(TIM2, ENABLE); 
}
/**************************************************************************
函式功能:把TIM4初始化為編碼器介面模式  和TIM2同理
入口引數:無
返回  值:無
**************************************************************************/
void Encoder_Init_TIM4(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;  
  TIM_ICInitTypeDef TIM_ICInitStructure;  
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//使能定時器4的時鐘
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能PB埠時鐘
	
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;	//埠配置
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空輸入
  GPIO_Init(GPIOB, &GPIO_InitStructure);					      //根據設定引數初始化GPIOB
  
  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 預分頻器 
  TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //設定計數器自動重灌值
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//選擇時鐘分頻:不分頻
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;////TIM向上計數  
  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
  TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用編碼器模式3
  
	TIM_ICStructInit(&TIM_ICInitStructure);
  
	TIM_ICInitStructure.TIM_ICFilter = 10;
  TIM_ICInit(TIM4, &TIM_ICInitStructure);
  TIM_ClearFlag(TIM4, TIM_FLAG_Update);//清除TIM的更新標誌位
  TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
  //Reset counter
  TIM_SetCounter(TIM4,0);
  TIM_Cmd(TIM4, ENABLE); 
}

5.微控制器如何採集編碼器資料

因為編碼器輸出的是標準的方波,所以我們可以使用微控制器(STM32 STM8 51等)直接讀取。在軟體中的處理方法是分兩種,自帶編碼器介面的微控制器如STM32,可以直接使用硬體計數。而沒有編碼器介面的微控制器如 51 微控制器,可以 通過外部中斷讀取,比如把編碼器 A 相輸出接到微控制器的外部中斷輸入口,這樣 就可通過跳變沿觸發中斷,然後在對應的外部中斷服務函式裡面,通過 B 相的電平來確定反轉。如今A相當於一個跳變沿的時候,如果B相就認為是正轉,低電平就認為是反轉。

函式功能:單位時間讀取編碼器計數
入口引數:定時器
返回  值:速度值
**************************************************************************/
int Read_Encoder(u8 TIMX)
{
    int Encoder_TIM;    
   switch(TIMX)
	 {
	   case 2:  Encoder_TIM= (short)TIM2 -> CNT;  TIM2 -> CNT=0;break;
		 case 3:  Encoder_TIM= (short)TIM3 -> CNT;  TIM3 -> CNT=0;break;	
		 case 4:  Encoder_TIM= (short)TIM4 -> CNT;  TIM4 -> CNT=0;break;	
		 default:  Encoder_TIM=0;
	 }
		return Encoder_TIM;
}