Hur läsa av encoder rätt

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
hol.nick
Inlägg: 50
Blev medlem: 31 mars 2014, 20:47:31
Ort: OH6_ÖsterBottnen

Hur läsa av encoder rätt

Inlägg av hol.nick »

Jag undrar hur brukar man göra när man har en incremental encoder
eller quadrature encoder, vad den nu riktigt kallas, ansluten till en uC för att inte få falska avläsningar.

Om man ansluter signal A att trigga en interrupt, och i interrupt rutinen
läser av signal B så vet man ju riktningen och kan ha en variabel att
räkna ner eller upp, allt funkar fint så långt.

Om en motor driver encodern jämnt är det ju knappast nåt problem,
men om man även har möjlighet till manuell kontroll så är det ju ganska sannolikt
att man råkar vrida encodern till ett läge så att man är "på kanten av en puls" och
då behövs ju bara en obetydlig rörelse bakåt så faller A och obetydligt frammåt så triggar den på nytt
dock utan att axeln rört sej så någon äkta up/ner räkning skall ske.

Har nån upplevt dylikt?
/N
Användarvisningsbild
Icecap
Inlägg: 26106
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Hur läsa av encoder rätt

Inlägg av Icecap »

I det fall använder man en encoder med stopp/"klick", då minskar dessa problem.
H.O
Inlägg: 5685
Blev medlem: 19 mars 2007, 10:11:27
Ort: Ronneby

Re: Hur läsa av encoder rätt

Inlägg av H.O »

Eller så triggar du din interrupt på stigande och fallande flank på såväl A- som B-kanalen och "kodar av" de fyra "kvadratura" tillstånden - alternativt använder en uC med inbyggd hårdvara för enkoder.
Användarvisningsbild
hawkan
Inlägg: 2586
Blev medlem: 14 augusti 2011, 10:27:40

Re: Hur läsa av encoder rätt

Inlägg av hawkan »

En Schmitt trigger ger lite hysteres
Användarvisningsbild
arvidb
Inlägg: 4537
Blev medlem: 8 maj 2004, 12:56:24
Ort: Stockholm

Re: Hur läsa av encoder rätt

Inlägg av arvidb »

Hysteres behövs inte. Rotary encoders, done properly.
Användarvisningsbild
HUGGBÄVERN
Tidigare soundbrigade
Inlägg: 32629
Blev medlem: 23 augusti 2006, 22:44:11
Ort: Lilla Paris
Kontakt:

Re: Hur läsa av encoder rätt

Inlägg av HUGGBÄVERN »

Frågan behandlades mycket utförligt i denna tråd en gång i tiden: viewtopic.php?f=52&t=89223
hol.nick
Inlägg: 50
Blev medlem: 31 mars 2014, 20:47:31
Ort: OH6_ÖsterBottnen

Re: Hur läsa av encoder rätt

Inlägg av hol.nick »

[quote=Icecap post_id=1605788 time=1618510608 user_id=947]
I det fall använder man en encoder med stopp/"klick", då minskar dessa problem.
[/quote]

jo det är en bra poäng, borde ju inte hoppa fram och tillbaka så lätt då.

Men nu menar jag dom modellerna som man använder i maskiner för possitionering
Jag håller på att modifiera en mekaniskt bra men elektriskt kass skärmaskin för papper
och skall visa possitionen på mothållet för skärbredden
grovjusteras med motorkörning och fin justeras förhand med ratt.

Encodern ger 100PPR och skruvens stigning 5mm/varv, kravet på upplösning nån 10del mm.
Referensköres vid start till bakre gränsbrytare och sedan framm till Z-puls från encodern.
Användarvisningsbild
Erikk
Inlägg: 63
Blev medlem: 1 april 2011, 12:13:40

Re: Hur läsa av encoder rätt

Inlägg av Erikk »

Har du tänkt använda en mikrokontroller till projektet, så gör du bäst i att använda en uC som har timers med encoder-stöd, tex STM32.

Kolla tex referens manualen för STM32F4 (RM0090): https://www.st.com/content/ccc/resource ... 031020.pdf
På sidan 615-617 finns den funktionaliteten beskriven, för TIM2/TIM5, dessa är general purpose 32bit timers. Finns fler sådana timers, men de är endast 16bit.

När allt är konfigurerat och klart så behöver du endast läsa CNT registret ur Timern för att ta reda på positionen, busenkelt.
hol.nick
Inlägg: 50
Blev medlem: 31 mars 2014, 20:47:31
Ort: OH6_ÖsterBottnen

Re: Hur läsa av encoder rätt

Inlägg av hol.nick »

Jo STM32 skall säkert vara en bra kandidat för olika project måste studera den närmare.
Man fastnar ju gärna i det man börjar använda och får svårt att se annat, AVR i detta fall :)

Med hjälp av forumet och några stärkare ur skåpet på en fredagskväll så kan allt lösas :mrgreen

Mitt problem med felaktig avläsning av en encoder är löst nu tror jag
för med en lös encoder som har 10ggr mera pulser än den som är i maskinen
lyckas jag inte få felavläsningar hur jag än vrider.

Så här är principen för min lösning, kan ju kanske hjälpa nån som skall använda encoders.
uC en AtMega 168A i detta fall.

ENC-A till PORTD.PD2 (Interrupt_0)
ENC-B till PORTD.PD1

[code]
DDR= 0x0; // sätter hela PORTD till ingångar, ändras enl. behov
EICRA|= (1<< ISC00); // INT0 på både stigande och fallande flank
volatile uint16_t encoder_cnt;
volatile uint8_t encoder_cntdiv;
..

ISR(INT0_vect) { // Interrupts from incremental encoder
uint8_t enc_state;

enc_state = PIND & 0b110; // encoder channel A & B state

if ( enc_state == 0b100 || enc_state == 0b010 ) encoder_cntdiv++;
else
if ( enc_state == 0b000 || enc_state == 0b110) encoder_cntdiv--;

if ( encoder_cntdiv == 8) { // uppdaterar var fjärde enc. räkning
encoder_cnt++;
encoder_cntdiv= 4;
}
else
if (encoder_cntdiv == 0 ) {
encoder_cnt--;
encoder_cntdiv = 4;
}

}

[/code]

kan ju nog putsas upp lite, men verkar fungera åtminstone som det ska nu.
encoder_cnt är räknarvariabeln som visas på displayen och uppdateras bara
var fjärde gång encodern räknar för att få rätt siffror på displayen
eftersom kulskruven som drar annhållet har 5mm stigning och enc.100ppr

/N
Användarvisningsbild
manicken
Inlägg: 91
Blev medlem: 10 februari 2006, 14:20:59
Ort: DEGEBERGA

Re: Hur läsa av encoder rätt

Inlägg av manicken »

On man har interrupt (fallande flank) på en av encoder utgångarna
samt att encodern ger följande signaler (vilket den borde göra)

a. 011100
b. 001110
eller
a. 001110
b. 011100

så räcker det att man läser av båda pinnar när man får interrupt

Om a = 0 och b = 1 så är riktningen a -> b
Om a = 1 och b = 0 så är riktningen b -> a

Sen måste man även ta hänsyn till eventuella kontaktstutsningar,
men om man har ett delay efter varje avläsning så borde det inte vara ett problem.
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4689
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Re: Hur läsa av encoder rätt

Inlägg av Swech »

Nej det räcker inte att göra så.... Det fungerar hjälpligt och oftast tillräckligt bra med rätt är det inte.
Om du har endast ett interupt på en kanal och encodern står och pendlar mellan 0 och 1 på den kanalen som
har interrupt kommer man att räkna flera steg felaktigt.

Korrekt sätt är att ha flank interrupt på båda kanaler, både positiv och negativ flank.
Då kan man räkna exakt rätt hela tiden

Sedan är delays av olika slag oftast till ondo eftersom
oerfarna programmerare helt sonika slänger in en delay på x ms där processorn då inte gör något vettigt.
Har man endast en uppgift så kan det gå men skall det ske andra saker parallellt så brukar man få
konstiga fel och problem på andra ställen just för att processorn sitter fast i någon delay

Swech
Användarvisningsbild
manicken
Inlägg: 91
Blev medlem: 10 februari 2006, 14:20:59
Ort: DEGEBERGA

Re: Hur läsa av encoder rätt

Inlägg av manicken »

Nu när jag läser trådskaparens inlägg en gång till så inser jag att denne redan gjort som jag skrev.

Delays kan se ut på många sätt,
ett långt delay ska ju vara "multitrådat"
alltså inte bryta main loopen eller på något annat sätt ta upp onödig processor tid.
Användarvisningsbild
Icecap
Inlägg: 26106
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Hur läsa av encoder rätt

Inlägg av Icecap »

Om vi antar att det kommer en interrupt på varje flank och på varje kanal då blir det rimligt enkelt.
OM förra avläsningen var en given värde kommer det att räknas en given riktning och "förra avläsningen" ställs till denna avläsning.

Därmed kan fler interrupt pga. studs inte ge fler pulser, det är bara den första som ger rätt signal. Alltså behövs ingen delay eller liknande.

Jag har tidigare löst detta vid att avläsa kanalerna med 1kHz och sedan utöva lite logik, det var i en enhet med 3 st encoders som i sin tur styrde 3 st frekvensutgångar som gick från 500mHz till 200kHz. Jag hade helt enkelt inte interrupt-ingångar nog.
Användarvisningsbild
manicken
Inlägg: 91
Blev medlem: 10 februari 2006, 14:20:59
Ort: DEGEBERGA

Re: Hur läsa av encoder rätt

Inlägg av manicken »

Då faller det tillbaka till tanken jag hade ifrån början.

(Notera att jag skrivit detta under tiden som icecap gjort sitt inlägg)

Man har interrupt på båda pinnar.

Kod: Markera allt

// global variables
uint_8 prev_int = 0; // 0 is the initial state
uint_8 dir = 0;
uint_8 dir_temp = 0;
uint_16 pulse_counter = 0;
uint_16 pulse_counter_temp = 0;

void int_pin_a() {
    if (prev_int == 0) {
        prev_int = 1;
        return;
    }
    else if (prev_int == 2) {
        prev_int = 0;
        dir = 1;
        pulse_counter++;
    }
}
void int_pin_b() {
    if (prev_int == 0) {
        prev_int = 2;
        return;
    }
    else if (prev_int == 1) {
        prev_int = 0;
        dir = 2;
        pulse_counter++;
    }
}

void main() {
    // setup
    while(1) {
        if (dir != 0) {
            pulse_counter_temp = pulse_counter; // ensure that it can be changed by int routine again.
            pulse_counter = 0;
            dir_temp = dir;
            dir = 0;
            
            if (dir_temp == 1) {
                
            }
            else if (dir_temp == 2) {
            
            }
        }
    }
}
Beskrivning av ovan kod:
I varje interrupt lagrar man vilken interrupt som hänt innan,
och endast fortsätter i interrupt rutinen om ovan interrupt skiljer sig ifrån
nuvarande
vilket både tar hand om kontaktstutsar och tillstånd där man står precis mellan två lägen.
När man får det andra interruptet så nollställer man ovan variabel så att man man decoda nya pulser,
samt sätter en flagga som kan läsas av i main loopen.
Det kan även behövas en räknare så att man inte man inte missar pulser.
I main loopen används temporära variabler för att minimera risken att missa pulser.

Har inte med hur int funktionerna anropas för att det skiljer mellan olika MCU,
men de ska anropas ifrån någon form a hårdvaru interrupt.
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4689
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Re: Hur läsa av encoder rätt

Inlägg av Swech »

Inte heller den metoden är korrekt.
Det som är lurigt är att flankerna ändrar riktning beroende på rikting på encodern.
Om vi har riktning vänster - höger
så får vi positiva flanker för kanal A i läge 1 2 och 3
Kanal B är i alla dessa lägen "0"
Vid negativ flank på A är Kanal B alla dessa lägen "1"

Vänder vi riktning (höger - vänster) så ser vi att när vi nu har positvia flanker på kanal A 4,5,6
så är kanal B i alla dessa lägen "1"
Vid negativ flank på A är Kanal B alla dessa lägen "0"

Vi behöver alltså minst två interruptrutiner
En för postiv flank kanal A
och en för negativ flank kanal A
I interruptrutin för positiv flank kontrolleras kanal B:
är den 0 så ökar vi räknaren
är den 1 så minskar vi räknaren.
I interruptrutin för negativ flank kontrolleras kanal B:
är den 0 så minskar vi räknaren.
är den 1 så ökar vi räknaren.

Om vi då hamnar i ett mellanläge så att B inte ändrar sig men A står och skickar positiva och negativa flanker
så blir det så att räknaren räknar upp 1 , och därefter ned 1 o.s.v.

Kör man med 4 interrupt, båda flanker båda kanaler så får man maximalt utnyttjande av encodern.
Varje flank räknas och åt rätt håll.
Står det och slår på en flank på en kanal hoppar räknaren upp och ned endast 1 steg

Swech


ENCODER.jpg
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Skriv svar