接線
編碼器電機(jī)、電機(jī)驅(qū)動(dòng)(這里用的L298n)、STM32、電源(可以是12V電池)的接線如下
3.3 代碼編寫(xiě)
encoder.h中的內(nèi)容
#ifndef _ENCODER_H_
#define _ENCODER_H_
#include "stm32f1xx.h"
//電機(jī)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
//定時(shí)器號(hào)
#define ENCODER_TIM htim2
#define PWM_TIM htim3
#define GAP_TIM htim4
#define MOTOR_SPEED_RERATIO 45u //電機(jī)減速比
#define PULSE_PRE_ROUND 11 //一圈多少個(gè)脈沖
#define RADIUS_OF_TYRE 34 //輪胎半徑,單位毫米
#define LINE_SPEED_C RADIUS_OF_TYRE * 2 * 3.14
#define RELOADVALUE __HAL_TIM_GetAutoreload(&ENCODER_TIM) //獲取自動(dòng)裝載值,本例中為20000
#define COUNTERNUM __HAL_TIM_GetCounter(&ENCODER_TIM) //獲取編碼器定時(shí)器中的計(jì)數(shù)值
typedef struct _Motor
{
int32_t lastCount; //上一次計(jì)數(shù)值
int32_t totalCount; //總計(jì)數(shù)值
int16_t overflowNum; //溢出次數(shù)
float speed; //電機(jī)轉(zhuǎn)速
uint8_t direct; //旋轉(zhuǎn)方向
}Motor;
#endif
encoder.c中的內(nèi)容
#include "encoder.h"
Motor motor1;
void Motor_Init(void)
{
HAL_TIM_Encoder_Start(&ENCODER_TIM, TIM_CHANNEL_ALL); //開(kāi)啟編碼器定時(shí)器
__HAL_TIM_ENABLE_IT(&ENCODER_TIM,TIM_IT_UPDATE); //開(kāi)啟編碼器定時(shí)器更新中斷,防溢出處理
HAL_TIM_Base_Start_IT(&GAP_TIM); //開(kāi)啟100ms定時(shí)器中斷
HAL_TIM_PWM_Start(&PWM_TIM, TIM_CHANNEL_2); //開(kāi)啟PWM
HAL_TIM_PWM_Start(&PWM_TIM, TIM_CHANNEL_1); //開(kāi)啟PWM
__HAL_TIM_SET_COUNTER(&ENCODER_TIM, 10000); //編碼器定時(shí)器初始值設(shè)定為10000
motor1.lastCount = 0; //結(jié)構(gòu)體內(nèi)容初始化
motor1.totalCount = 0;
motor1.overflowNum = 0;
motor1.speed = 0;
motor1.direct = 0;
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//定時(shí)器回調(diào)函數(shù),用于計(jì)算速度
{
if(htim- >Instance==ENCODER_TIM.Instance)//編碼器輸入定時(shí)器溢出中斷,用于防溢出
{
if(COUNTERNUM < 10000) motor1.overflowNum++; //如果是向上溢出
else if(COUNTERNUM >= 10000) motor1.overflowNum--; //如果是向下溢出
__HAL_TIM_SetCounter(&ENCODER_TIM, 10000); //重新設(shè)定初始值
}
else if(htim- >Instance==GAP_TIM.Instance)//間隔定時(shí)器中斷,是時(shí)候計(jì)算速度了
{
motor1.direct = __HAL_TIM_IS_TIM_COUNTING_DOWN(&ENCODER_TIM);//如果向上計(jì)數(shù)(正轉(zhuǎn)),返回值為0,否則返回值為1
motor1.totalCount = COUNTERNUM + motor1.overflowNum * RELOADVALUE;//一個(gè)周期內(nèi)的總計(jì)數(shù)值等于目前計(jì)數(shù)值加上溢出的計(jì)數(shù)值
motor1.speed = (float)(motor1.totalCount - motor1.totalCount) / (4 * MOTOR_SPEED_RERATIO * PULSE_PRE_ROUND) * 10;//算得每秒多少轉(zhuǎn)
//motor1.speed = (float)(motor1.totalCount - motor1.totalCount) / (4 * MOTOR_SPEED_RERATIO * PULSE_PRE_ROUND) * 10 * LINE_SPEED_C//算得車輪線速度每秒多少毫米
motor1.lastCount = motor1.totalCount; //記錄這一次的計(jì)數(shù)值
}
}
使用時(shí)需要在main.c的循環(huán)之前調(diào)用Motor_Init函數(shù)進(jìn)行初始化。
如果發(fā)現(xiàn)無(wú)法進(jìn)入編碼器中斷導(dǎo)致totalCount經(jīng)常溢出歸零,可以嘗試換一種防溢出的方法,代碼如下
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//定時(shí)器回調(diào)函數(shù),用于計(jì)算速度
{
if(htim- >Instance==GAP_TIM.Instance)//間隔定時(shí)器中斷,是時(shí)候計(jì)算速度了
{
motor1.direct = __HAL_TIM_IS_TIM_COUNTING_DOWN(&ENCODER_TIM);//如果向上計(jì)數(shù)(正轉(zhuǎn)),返回值為0,否則返回值為1
motor1.totalCount = COUNTERNUM_1 + motor1.overflowNum * RELOADVALUE_1;//一個(gè)周期內(nèi)的總計(jì)數(shù)值等于目前計(jì)數(shù)值加上溢出的計(jì)數(shù)值
if(motor1.lastCount - motor1.totalCount > 19000) // 在計(jì)數(shù)值溢出時(shí)進(jìn)行防溢出處理
{
motor1.overflowNum++;
motor1.totalCount = COUNTERNUM_1 + motor1.overflowNum * RELOADVALUE_1;//一個(gè)周期內(nèi)的總計(jì)數(shù)值等于目前計(jì)數(shù)值加上溢出的計(jì)數(shù)值
}
else if(motor1.totalCount - motor1.lastCount > 19000) // 在計(jì)數(shù)值溢出時(shí)進(jìn)行防溢出處理
{
motor1.overflowNum--;
motor1.totalCount = COUNTERNUM_1 + motor1.overflowNum * RELOADVALUE_1;//一個(gè)周期內(nèi)的總計(jì)數(shù)值等于目前計(jì)數(shù)值加上溢出的計(jì)數(shù)值
}
motor1.speed = (float)(motor1.totalCount - motor1.lastCount) / (4 * MOTOR_SPEED_RERATIO * PULSE_PRE_ROUND) * 3000;//算得每秒多少轉(zhuǎn),除以4是因?yàn)?倍頻
motor1.lastCount = motor1.totalCount; //記錄這一次的計(jì)數(shù)值
}
-
編碼器
+關(guān)注
關(guān)注
45文章
3645瀏覽量
134578 -
驅(qū)動(dòng)
+關(guān)注
關(guān)注
12文章
1840瀏覽量
85311 -
電機(jī)
+關(guān)注
關(guān)注
142文章
9023瀏覽量
145563 -
STM32
+關(guān)注
關(guān)注
2270文章
10901瀏覽量
356224
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論