Estoy tratando de hacer que un codificador rotatorio funcione en mi STM32.
¿Hay algo que estoy haciendo mal? ¿Las interrupciones no son suficientes para mantener la velocidad del codificador? ¿El rebote no es suficiente (se ve bien en un osciloscopio, pero tal vez las interrupciones sean más sensibles)? ¿Hay una mejor manera de hacer esto en general? He estado atascado en esto por un tiempo, así que cualquier ayuda sería genial. Avíseme si es necesaria más información.
*Código editado para reflejar cambios (algoritmo de trabajo)
MANEJO DE INTERRUPCIONES
static int8_t states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
uint8_t RotaryCurrentState = 0x00;
uint8_t RotaryTransition = 0;
int8_t RotaryPosition = 0;
/*Rotary Encoder Interrupt Handler
Channel A (IRQ11) & B (IRQ10)
CW --->
A (IRQ11) ¯|___|¯¯¯¯|___|¯¯¯¯
Interrupts ^ ^ ^ ^
B (IRQ 10) ¯¯¯|___|¯¯¯¯¯|___|¯
Interrupts ^ ^ ^ ^
CCW <---
void EXTI4_15_IRQHandler(void)
{
RotaryCurrentState = (Read_IO(ROTARY_A) << 1) | Read_IO(ROTARY_B);
RotaryTransition = (RotaryTransition <<2 ) | RotaryCurrentState;
RotaryPosition = RotaryPosition + states[RotaryTransition & 0x0F];
EXTI_ClearITPendingBit(EXTI_Line10); //Clear Channel B
EXTI_ClearITPendingBit(EXTI_Line11); //Clear Channel A
}
C PRINCIPAL
//Initialize
RotaryTransition = Read_IO(ROTARY_A) << 3 | Read_IO(ROTARY_B) << 2 | \
Read_IO(ROTARY_A) << 1 | Read_IO(ROTARY_B);
while(1)
{
//CW Transition
if (RotaryPosition == 4)
{
STM_EVAL_LEDToggle(LED4);
RotaryPosition = 0;
}
//CCW Transition
else if (RotaryPosition == -4)
{
STM_EVAL_LEDToggle(LED3);
RotaryPosition = 0;
}
}
Ese no es un gran algoritmo en su controlador. Deberías tener CERO si. Sin decisiones.
Guarde su estado AB, es decir, 00 o 01, luego agregue su siguiente estado, es decir, 0001 significa que AB pasó de 00 a 01, por lo que B cambió de 0 a 1. Haga de esto un +1. Si comienza desde 00 y cambia a 10, llámelo -1. Cree una matriz de 16 elementos de todas las transiciones posibles que contengan el número que debe agregarse a su conteo si ocurre, y tenga en cuenta que algunas son ilegales y deben manejarse.
0000 0 0 no transition
0001 1 +1
0010 2 -1
0011 3 0 Illegal, two transitions, and so on.
Indexe esta matriz en cada transición, esté atento a los eventos ilegales y trátelos como mejor le parezca. Agregue el resultado al conteo. Cambie los nuevos valores al punto de valor anterior en el número de índice y repita para siempre
en pseudocódigo
signed int8 add_subt[16] = { 0, 1 ,-1 , ....};
unsigned int8 idx;
signed int32 pos_count;
main() {
% initialize idx
idx = readA <<3 + readB<<2 + readA<<1 + readB;
while(1){}
}
interrupt_on_any_change(){
idx=idx<<2 & 0x0F + readA<<1 + readB;
pos_count=pos_count+add_subt[idx];
}
Podría mantener err_idx para ayudarlo a marcar malas transiciones
¿No se ve un cabello más simple?
scott seidman
picante
yippie
joe hass
scott seidman
chris stratton
picante
picante
picante
joe hass
scott seidman
kamil kisiel
EXTI_ClearITPendingBit
:EXTI_ClearITPendingBit(EXTI_Line10 | EXTI_Line11)