bldc/encoder/enc_abi.c

120 lines
3.4 KiB
C
Raw Normal View History

/*
Copyright 2016 - 2022 Benjamin Vedder benjamin@vedder.se
Copyright 2022 Jakub Tomczak
This file is part of the VESC firmware.
The VESC firmware is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
The VESC firmware is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
2022-02-19 12:00:52 -08:00
#include "encoder/enc_abi.h"
2021-12-15 04:40:16 -08:00
#include "ch.h"
#include "hal.h"
#include "stm32f4xx_conf.h"
#include "hw.h"
#include "mc_interface.h"
#include "utils.h"
#include <string.h>
#include <math.h>
2021-12-15 04:40:16 -08:00
bool enc_abi_init(ABI_config_t *cfg) {
2021-12-15 05:17:43 -08:00
EXTI_InitTypeDef EXTI_InitStructure;
2021-12-15 04:40:16 -08:00
memset(&cfg->state, 0, sizeof(ABI_state));
palSetPadMode(cfg->A_gpio, cfg->A_pin, PAL_MODE_ALTERNATE(cfg->tim_af));
palSetPadMode(cfg->B_gpio, cfg->B_pin, PAL_MODE_ALTERNATE(cfg->tim_af));
palSetPadMode(cfg->I_gpio, cfg->I_pin, PAL_MODE_INPUT_PULLUP);
2021-12-15 04:40:16 -08:00
// Enable timer clock
2021-12-15 04:40:16 -08:00
HW_ENC_TIM_CLK_EN();
// Enable SYSCFG clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
TIM_EncoderInterfaceConfig(cfg->timer,
TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
TIM_SetAutoreload(cfg->timer, cfg->counts - 1);
2021-12-15 04:40:16 -08:00
// Filter
cfg->timer->CCMR1 |= 6 << 12 | 6 << 4;
cfg->timer->CCMR2 |= 6 << 4;
2021-12-15 04:40:16 -08:00
TIM_Cmd(cfg->timer, ENABLE);
2021-12-15 04:40:16 -08:00
// Interrupt on index pulse
// Connect EXTI Line to pin
SYSCFG_EXTILineConfig(cfg->exti_portsrc, cfg->exti_pinsrc);
2021-12-15 04:40:16 -08:00
// Configure EXTI Line
EXTI_InitStructure.EXTI_Line = cfg->exti_line;
2021-12-15 04:40:16 -08:00
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
// Enable and set EXTI Line Interrupt to the highest priority
nvicEnableVector(cfg->exti_ch, 0);
2021-12-15 04:40:16 -08:00
return true;
2021-12-15 04:40:16 -08:00
}
void enc_abi_deinit(ABI_config_t *cfg) {
nvicDisableVector(cfg->exti_ch);
TIM_DeInit(cfg->timer);
palSetPadMode(cfg->A_gpio, cfg->A_pin, PAL_MODE_INPUT_PULLUP);
palSetPadMode(cfg->B_gpio, cfg->B_pin, PAL_MODE_INPUT_PULLUP);
palSetPadMode(cfg->I_gpio, cfg->I_pin, PAL_MODE_INPUT_PULLUP);
cfg->state.last_enc_angle = 0.0;
2021-12-15 04:40:16 -08:00
}
float enc_abi_read_deg(ABI_config_t *cfg) {
cfg->state.last_enc_angle = ((float) cfg->timer->CNT * 360.0) / (float) cfg->counts;
return cfg->state.last_enc_angle;
}
void enc_abi_pin_isr(ABI_config_t *cfg) {
// Only reset if the pin is still high to avoid too short pulses, which
// most likely are noise.
__NOP();
__NOP();
__NOP();
__NOP();
if (palReadPad(cfg->I_gpio, cfg->I_pin)) {
const unsigned int cnt = cfg->timer->CNT;
const unsigned int lim = cfg->counts / 20;
if (cfg->state.index_found) {
// Some plausibility filtering.
if (cnt > (cfg->counts - lim) || cnt < lim) {
cfg->timer->CNT = 0;
cfg->state.bad_pulses = 0;
} else {
cfg->state.bad_pulses++;
if (cfg->state.bad_pulses > 5) {
cfg->state.index_found = 0;
}
}
} else {
cfg->timer->CNT = 0;
cfg->state.index_found = true;
cfg->state.bad_pulses = 0;
}
}
}