接線
編碼器電機、電機驅動(這里用的L298n)、STM32、電源(可以是12V電池)的接線如下
3.3 代碼編寫
encoder.h中的內容
#ifndef _ENCODER_H_
#define _ENCODER_H_
#include "stm32f1xx.h"
//電機1的編碼器輸入引腳
#define MOTO1_ENCODER1_PORT GPIOA
#define MOTO1_ENCODER1_PIN GPIO_PIN_0
#define MOTO1_ENCODER2_PORT GPIOA
#define MOTO1_ENCODER2_PIN GPIO_PIN_1
//定時器號
#define ENCODER_TIM htim2
#define PWM_TIM htim3
#define GAP_TIM htim4
#define MOTOR_SPEED_RERATIO 45u //電機減速比
#define PULSE_PRE_ROUND 11 //一圈多少個脈沖
#define RADIUS_OF_TYRE 34 //輪胎半徑,單位毫米
#define LINE_SPEED_C RADIUS_OF_TYRE * 2 * 3.14
#define RELOADVALUE __HAL_TIM_GetAutoreload(&ENCODER_TIM) //獲取自動裝載值,本例中為20000
#define COUNTERNUM __HAL_TIM_GetCounter(&ENCODER_TIM) //獲取編碼器定時器中的計數值
typedef struct _Motor
{
int32_t lastCount; //上一次計數值
int32_t totalCount; //總計數值
int16_t overflowNum; //溢出次數
float speed; //電機轉速
uint8_t direct; //旋轉方向
}Motor;
#endif
encoder.c中的內容
#include "encoder.h"
Motor motor1;
void Motor_Init(void)
{
HAL_TIM_Encoder_Start(&ENCODER_TIM, TIM_CHANNEL_ALL); //開啟編碼器定時器
__HAL_TIM_ENABLE_IT(&ENCODER_TIM,TIM_IT_UPDATE); //開啟編碼器定時器更新中斷,防溢出處理
HAL_TIM_Base_Start_IT(&GAP_TIM); //開啟100ms定時器中斷
HAL_TIM_PWM_Start(&PWM_TIM, TIM_CHANNEL_2); //開啟PWM
HAL_TIM_PWM_Start(&PWM_TIM, TIM_CHANNEL_1); //開啟PWM
__HAL_TIM_SET_COUNTER(&ENCODER_TIM, 10000); //編碼器定時器初始值設定為10000
motor1.lastCount = 0; //結構體內容初始化
motor1.totalCount = 0;
motor1.overflowNum = 0;
motor1.speed = 0;
motor1.direct = 0;
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//定時器回調函數,用于計算速度
{
if(htim- >Instance==ENCODER_TIM.Instance)//編碼器輸入定時器溢出中斷,用于防溢出
{
if(COUNTERNUM < 10000) motor1.overflowNum++; //如果是向上溢出
else if(COUNTERNUM >= 10000) motor1.overflowNum--; //如果是向下溢出
__HAL_TIM_SetCounter(&ENCODER_TIM, 10000); //重新設定初始值
}
else if(htim- >Instance==GAP_TIM.Instance)//間隔定時器中斷,是時候計算速度了
{
motor1.direct = __HAL_TIM_IS_TIM_COUNTING_DOWN(&ENCODER_TIM);//如果向上計數(正轉),返回值為0,否則返回值為1
motor1.totalCount = COUNTERNUM + motor1.overflowNum * RELOADVALUE;//一個周期內的總計數值等于目前計數值加上溢出的計數值
motor1.speed = (float)(motor1.totalCount - motor1.totalCount) / (4 * MOTOR_SPEED_RERATIO * PULSE_PRE_ROUND) * 10;//算得每秒多少轉
//motor1.speed = (float)(motor1.totalCount - motor1.totalCount) / (4 * MOTOR_SPEED_RERATIO * PULSE_PRE_ROUND) * 10 * LINE_SPEED_C//算得車輪線速度每秒多少毫米
motor1.lastCount = motor1.totalCount; //記錄這一次的計數值
}
}
使用時需要在main.c的循環之前調用Motor_Init函數進行初始化。
如果發現無法進入編碼器中斷導致totalCount經常溢出歸零,可以嘗試換一種防溢出的方法,代碼如下
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//定時器回調函數,用于計算速度
{
if(htim- >Instance==GAP_TIM.Instance)//間隔定時器中斷,是時候計算速度了
{
motor1.direct = __HAL_TIM_IS_TIM_COUNTING_DOWN(&ENCODER_TIM);//如果向上計數(正轉),返回值為0,否則返回值為1
motor1.totalCount = COUNTERNUM_1 + motor1.overflowNum * RELOADVALUE_1;//一個周期內的總計數值等于目前計數值加上溢出的計數值
if(motor1.lastCount - motor1.totalCount > 19000) // 在計數值溢出時進行防溢出處理
{
motor1.overflowNum++;
motor1.totalCount = COUNTERNUM_1 + motor1.overflowNum * RELOADVALUE_1;//一個周期內的總計數值等于目前計數值加上溢出的計數值
}
else if(motor1.totalCount - motor1.lastCount > 19000) // 在計數值溢出時進行防溢出處理
{
motor1.overflowNum--;
motor1.totalCount = COUNTERNUM_1 + motor1.overflowNum * RELOADVALUE_1;//一個周期內的總計數值等于目前計數值加上溢出的計數值
}
motor1.speed = (float)(motor1.totalCount - motor1.lastCount) / (4 * MOTOR_SPEED_RERATIO * PULSE_PRE_ROUND) * 3000;//算得每秒多少轉,除以4是因為4倍頻
motor1.lastCount = motor1.totalCount; //記錄這一次的計數值
}
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
編碼器
+關注
關注
45文章
3646瀏覽量
134674 -
驅動
+關注
關注
12文章
1843瀏覽量
85334 -
電機
+關注
關注
142文章
9028瀏覽量
145664 -
STM32
+關注
關注
2270文章
10904瀏覽量
356397
發布評論請先 登錄
相關推薦
AB相編碼器-變M/T法測速,10ms定時,測6000轉伺服電機!
本帖最后由 SXST_T 于 2017-9-13 12:11 編輯
適用所有線數編碼器,此方法主要解決M法測低速分辨率不足,T法測高速分辨率高,
發表于 09-13 12:07
編碼器常用測速方法
2.1 倍頻技術 編碼器會輸出兩路方波信號,如果只在通道A的上升沿計數,那就是1倍頻;通道A的上升、下降沿計數,那就是2倍頻;如果在通道A、B的上升、下降沿計數,那就是4倍頻。 使用倍頻可以最大程度
評論