Ich versuche, einen Drehgeber an meinem STM32 zum Laufen zu bringen.
Gibt es etwas, das ich falsch mache? Reichen die Interrupts nicht aus, um mit der Geschwindigkeit des Encoders Schritt zu halten? Ist die Entprellung nicht genug (Sieht auf einem Oszilloskop okay aus, aber vielleicht sind die Interrupts empfindlicher)? Gibt es einen besseren Weg, dies im Allgemeinen zu tun? Ich stecke hier schon eine Weile fest, also wäre jede Hilfe großartig. Lassen Sie mich wissen, wenn weitere Informationen erforderlich sind.
*Code bearbeitet, um Änderungen widerzuspiegeln (Arbeitsalgorithmus)
UNTERBRECHUNGS-HANDLER
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
}
HAUPT C
//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;
}
}
Das ist kein großartiger Algorithmus in Ihrem Handler. Sie sollten NULL ifs haben. Keine Entscheidungen.
Speichern Sie Ihren AB-Zustand, dh 00 oder 01, und hängen Sie dann Ihren nächsten Zustand an, dh 0001 bedeutet, dass AB von 00 auf 01 wechselte, also B von 0 auf 1 geändert wurde. Machen Sie dies zu +1. Wenn Sie bei 00 beginnen und zu 10 wechseln, nennen Sie dies eine -1. Erstellen Sie ein 16-Element-Array aller möglichen Übergänge, das die Zahl enthält, die zu Ihrer Zählung hinzugefügt werden muss, wenn es auftritt, und beachten Sie, dass einige illegal sind und behandelt werden müssen.
0000 0 0 no transition
0001 1 +1
0010 2 -1
0011 3 0 Illegal, two transitions, and so on.
Indexieren Sie bei jedem Übergang in dieses Array, achten Sie auf illegale Ereignisse und behandeln Sie sie so, wie Sie es für richtig halten. Addieren Sie das Ergebnis zur Zählung. Verschieben Sie die neuen Werte an die Stelle des alten Werts in der Indexnummer und wiederholen Sie dies für immer
Im Pseudocode
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];
}
Sie könnten err_idx pflegen, um Ihnen zu helfen, schlechte Übergänge zu kennzeichnen
Sieht das nicht um Haaresbreite einfacher aus??
Scott Seidman
spizzak
Jippie
Joe Hass
Scott Seidman
Chris Stratton
spizzak
spizzak
spizzak
Joe Hass
Scott Seidman
Kamil Kissel
EXTI_ClearITPendingBit
:EXTI_ClearITPendingBit(EXTI_Line10 | EXTI_Line11)