[elektro] rotary encoder, mit csinálok rosszul?

nemeth.tibor798 at t-online.hu nemeth.tibor798 at t-online.hu
Mon Jan 2 15:34:20 CET 2017


  Hali!

Bár őskövületnek érzem magam, de mivel több mint 20 éve működik a  
módszer, leírom a lényeget. Én még mindig ASM-ban nyomulok, munkás  
nagyon, de legalább tudom mit csinálok.
A két encoder bit 1 portra megy, a portot csak egyszer olvasom és  
eltárolom majd feldolgozom. Bár nem teljesen értem a C-t, de ha jól  
látom a programodban többször van If (ENCx_PORT) és ez gondolom port  
olvasást jelent. Nos semmi garancia rá, hogy két olvasás között nem  
változik, már úgy értem egy interrupton belül.
A feldolgozásra nagyon gyalog, de szerintem nagyon hatékony,  
ugrótáblás módszert használok. Van két régi bitem és két aktuális. Ez  
a 4 bit egy ugrótáblába megy be ami 16 elemű. Az egyidőből származó  
bitek szomszédosak.
Gondolom ez C-ben sem gond, nekem ASM van:
Itt W alsó 4 bitje játszik.

    ANDLW    0FH
    ADDWF    PCL,1

    GOTO    NNOOPP
    GOTO    DECPOSITION
    GOTO    INCPOSITION
    GOTO    ERRORCOUNT
    
    GOTO    INCPOSITION
    GOTO    NNOOPP
    GOTO    ERRORCOUNT
    GOTO    DECPOSITION
    
    GOTO    DECPOSITION
    GOTO    ERRORCOUNT
    GOTO    NNOOPP
    GOTO    INCPOSITION
    
    GOTO    ERRORCOUNT
    GOTO    INCPOSITION
    GOTO    DECPOSITION
    GOTO    NNOOPP

A megfelelő címkéken van a növelő, csökkentő, semmittevő és  
hibaszámláló rutin.
Eredetileg PIC16C54-en volt egy 4 dimenziós problélmám, az a PIC csak  
ezt a feladatot látta el, mivel annak még nem volt megszakítása,  
egyszerűen polloztam, elég sűrűn. A pozíciókat nyomta ki soroson. A  
rutinokban elhelyezett NOP-okkal megoldottam, hogy minden ágon azonos  
legyen a végrehajtási idő. Ez azért kellett mert abban soros harder  
sem volt, igy a bit-idők voltak kitöltve az encoderek feldolgozásával.

Modernebb PIC-ben B port change mexakítást használom, Itt meg kellett  
tanulnom, hogy ha a port egyéb lábait is használni akarom, akkor arra  
erősen ügyelni kell, mert a port olvasása törli a hardverbiteket (a  
változást jelző flipflopot) és szerencsétlen egybeesés esetén elmarad  
az interrupt.

Persze nem árt ha a hardver tiszta jeleket produkál, de a fenti  
módszer jól tűri, ha az él körül pereg a bit, számlál szépen  
oda/vissza.  Ha a kettő bit egyszerre változik, azt ez sem tudja  
lekezelni, de az egyértelműen hiba. No és persze olyan is volt, hogy  
egy nem túl jól kivitelezett kapcsistáp teleszórta zavarral én meg az  
encoder szidtam. Szóval ez is egy lehetőség.

Üdv.
                               Németh Tibor

Idézet (Gabor Jordan <jordang.elektro at gmail.com>):

> ÜDV,
>
> Rotary encoder, PIC18F67K90 B3 és B4 lábain csücsül, felhúzva  
> 47k-val kívülről.
>
> A lenti megszakítás (XC8) kezelné le, de nem jó. Kb. 10ből 8szor jól  
> lép, de 2szer vagy rossz irányba, vagy többet. Az ENC1 lefutóél  
> csinál megszakítást és nézem az ENC2 láb hogyan áll. Mindig is így  
> csináltam és ment. Optikai enkóderrel most is megy. Így is  
> (lassabban) meg úgy is, ha kiveszem a késleltetéseket. Hiba nélkül.  
> Gondolom a mechanikusnál a prell-el vagy kontakt-al van gond.  
> Szkópon nem is túl szép a kapcsolás, látszik a prell, de lemegy még  
> a késleltetések előtt (legalábbis amit látok). Mégsem jó, hiába  
> játszom az időzítésekkel.
>
> Más tipusú enkoderrel jó volt (bourns), de amit most használni  
> akarok, nem jó. Van több darab, cseréltem is, de nem jó.
>
> Hogy illik megbízhatóan olvasni ezeket?
>
> 1 szintű megszakítást használok, a megszakítás kezelést elvileg nem  
> szakítja meg másik megszakítás (legalábbis az XC9 azt mondja ne  
> kapcsolgassam a kódban a GIE-t, ő megteszi).
>
> Köszönöm,
>
> ÜDV JG
>
> *****
>
>    if (INTCON3bits.INT3IF==1) // interrupt from rotary encored
>        {
>        INTCON3bits.INT3IF=0;
>        __delay_us(50);
>        if (ENC1_PORT==0)
>            {
>            __delay_us(50);
>            if (ENC1_PORT==0)
>                {
>                __delay_us(50);
>                if (ENC1_PORT==0)
>                    {
>                    if (ENC2_PORT)
>                        {
>                        //LCDPutCmd(01);
>                        //LCDPutStr("vissza");
>                        pwm = pwm - 16;
>                        }
>                    else
>                        {
>                        //LCDPutCmd(01);
>                        //LCDPutStr("oda");
>                        pwm = pwm + 16;
>                        }
>                        update = 0x01;
>                    }
>                }
>            }
>        }
>
> *******
>
> -----------------------------------------        elektro[-flame|-etc]


More information about the Elektro mailing list