中级会员
- 积分
- 214
- 金钱
- 214
- 注册时间
- 2014-4-30
- 在线时间
- 26 小时
|
编码器的配置如附图所示。
其中遇到的一些问题汇总如下:
1.正交编码器计数是4的倍数,比如:旋转1下,得到的数值是4;
解决办法:修改分频系数Prescaler = 4-1.
2.编码器不进中断,
解决办法:应该是要开启如下图所示的中断,而不是之前用的TIM1 capture compare interrupt。这个中断如果是用来判断圈数要注意使用此中断。
初始化:
HAL_TIM_Encoder_Start(&htim1, TIM_CHANNEL_ALL);
HAL_TIM_Encoder_Start_IT(&htim1, TIM_CHANNEL_ALL); //这里TIM_CHANNEL_1/TIM_CHANNEL_ALL均可
__HAL_TIM_ENABLE_IT(&htim1, TIM_IT_UPDATE);
3.如何判断圈数增加或减小?
在上述中断回调函数中做如下:
if (htim->Instance == TIM1) {
if ((htim->Instance->CR1 >> 4 & 0x01) == 0) //DIR==0
{
encoder.cycles++; // 圈数++
} else if ((htim->Instance->CR1 >> 4 & 0x01) == 1) //DIR==1
{
encoder.cycles--; // 圈数--
}
}
4.如何判断转动方向
网上找的都是五花八门,大多数是用上面的那个中断中去判断,如果驱动是旋转非常快或者脉冲数比较小的(如电机或者旋钮编码器)这些是可以的,根据溢出圈数的增减,可判断正反转;
但是响应不及时。
通过查找资料,使用了如下方法
encoder.dir = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim1);//可以获得当前电机的转向
5.获得绝对编码值
如下,=圈数*脉冲数+此时编码器的计数值。
encoder.tim_counter = (uint32_t) (__HAL_TIM_GET_COUNTER(&htim1)); //获取定时器的值
encoder.value = (int)encoder.cycles*encoder.max_counter + encoder.tim_counter;
6.待完善
①加flash和PVD掉电检测,保存掉电时编码器的值,上电加载。
②改变AB项的相序,把原来的减变加。
7.除了cubemx生成的代码,其他的做了封装,如下:
struct drv_encoder{
char dir;
int value;
int tim_counter;
int cycles;
float speed;
int max_counter;
};
struct drv_encoder encoder = {
.cycles = 0,
.tim_counter = 0,
.value = 0,
.max_counter = 0};
extern TIM_HandleTypeDef htim1;
void drv_encoder_init(struct drv_encoder *encoders) {
HAL_TIM_Encoder_Start(&htim1, TIM_CHANNEL_ALL);
HAL_TIM_Encoder_Start_IT(&htim1, TIM_CHANNEL_ALL); //这里TIM_CHANNEL_1/TIM_CHANNEL_ALL均可
__HAL_TIM_ENABLE_IT(&htim1, TIM_IT_UPDATE);
// TODO: implement
// Init encoder cfg parameters from flash.
encoder_set_counter(0);
encoder.max_counter = htim1.Init.Period +1;
encoders = &encoder;
}
struct drv_encoder* drv_encoder_get_value(void) {
update_encoder();
return &encoder;
}
struct drv_encoder* drv_encoder_set_value(int value) {
// TODO: implement
// Set value,and set cycles & set hal_TIM_SET_COUNTER;
encoder_set_counter(value);
return &encoder;
}
// 该函数请放到 HAL_TIM_PeriodElapsedCallback 里面。
void EncoderPeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if (htim->Instance == TIM1) {
if ((htim->Instance->CR1 >> 4 & 0x01) == 0) //DIR==0
{
encoder.cycles++;
} else if ((htim->Instance->CR1 >> 4 & 0x01) == 1) //DIR==1
{
encoder.cycles--;
}
}
}
int encoder_get_counter(void)
{
encoder.tim_counter = (uint32_t) (__HAL_TIM_GET_COUNTER(&htim1)); //获取定时器的值
encoder.value = (int)encoder.cycles*encoder.max_counter + encoder.tim_counter;
return encoder.value;
}
void encoder_set_counter(int t)
{
__HAL_TIM_SET_COUNTER(&htim1, t%htim1.Init.Period);
encoder.cycles = t/encoder.max_counter;//圈数
}
void update_encoder(void)
{
encoder.tim_counter = (uint32_t) (__HAL_TIM_GET_COUNTER(&htim1)); //获取定时器的值
encoder.dir = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim1);//可以获得当前电机的转向
encoder.value = (int)encoder.cycles*encoder.max_counter + encoder.tim_counter;
}
不吝赐教!
|
-
|