Sari la conținut
ELFORUM - Forumul electronistilor

quadrature encoder rotary


Postări Recomandate

Salutare . Folosesc un 16f628 ca sa decodifice directia de rotatie , daca e orar RB0=1 , iar daca e antiorar RB1=1. Folosesc RA0 intrare A encoder , RA1 intrare B encoder . Folosesc algoritmul de aici          http://www.romanblack.com/trackball.htm

Vreau sa folosesc TMR0 sa verific la intervale regulate de timp starea encoderului . Pseudocode ar fi cam asta 

 

1.  Pornesc intreruperi TMR0

2. Citesc encoder 

                           daca new!=old 

                                                vezi directia   daca Enc_A==0 & Enc_B==1 

                                                                                directia orar si RB0=1, RB1=0

                                                                       else

                                                                               directie antiorar si RB1=1, RB0=0

                           else 

                                 RB0=0

                                 RB0=0  ; nici o schimbare

 

Vreau sa stiu daca e bun pseudocodul

Multam

Link spre comentariu
  • Răspunsuri 17
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

Top autori în acest subiect

Codul in C de pe site este corect , doar inlocuiesti x_value++ cu RB0=1, RB1=0 si x_value-- cu RB0=0, RB1=1

 Ca sa vezi cand sta pui un timer sau la nu stiu cate citiri la care nu ai nici o schimbare faci RB0=0, RB1=0

 Pseudocodul nu e bun , evident ca o sa ai citiri succesive cu acceasi valoare si pe pinii de directie o sa apara un fel de tren de impulsuri ultrascurte.

Editat de mdorian
Link spre comentariu
	F4, F5, F6, F7 sunt pozitiile bitilor corespunzatori intrarilor de la optocuploare Daca tu folosesti sa spunem bitii 4,5,6,7 de la port pentru intrarile Vert A,Vert B , Horiz A, Horiz B adica la el F4, F5, F6, F7atunci newX.F4 inseamna bitul 4 de la newX si asa mai departe. Sincer , nu stiu de unde a scos denumirea de F4.. F7 pentru ca el foloseste portul B dar asta inseamna. Lipsesc declaratiile din codul lui dar newX, oldX, newY si oldY sunt octeti iar newX.F4 etc sunt biti. Cu ce compilator lucrezi?
Link spre comentariu

F poate veni de la "flag" sau "field", intr-adevar cred e numarul bitului din octet.

cred ca ar fi bine sa folosesti sugestia colegului cu interrupt on change, nu ai nevoie de TMR0, altfel valoare de old e practic aleatoare fata de new.

Link spre comentariu

In atasament e un proiect (mplabx) derivat dintr-un proiect mai mare in care foloseam si un encoder.

De compilat se compileaza (pentru PIC16F628A), dar n-am cum sa-l testez (am "aruncat" mare parte din codul original si pot aparea surprize).

Pentru encoder folosesc pinii RB4&RB5, ca sa pot folosi interrupt on change. In rest, e destul de "aerisit", sper sa intelegi ce am vrut sa fac.

encoder.zip

Editat de Liviu M
Link spre comentariu

Sincer , e cam avansat pentru mine , si prea putine comment uri...!Dar multumesc . Am insa un alt cod in assembler despre decodarea unui encoder si as vrea sa-l modific doar sa semnalizeze pe un pin in PORTA daca se roteste in sens orar , si pe un alt pin daca se roteste antiorar..!

 

Code:

LIST p=16F628A ;tell assembler what chip we are usinginclude "P16F628A.inc" ;include the defaults for the chip__config _INTOSC_OSC_NOCLKOUT & _LVP_OFF & _WDT_OFF & _PWRTE_OFF & _BOREN_OFF & _MCLRE_OFFcblock 0x20 ;start of general purpose registerstmp ;20tmp2 ;21Old ;22New ;23RCounter ;24FRotation;25dataL;26endccblock 0x70W_TEMP;70STATUS_TEMP;71ENDCorg 0x0000 ;org sets the origin, 0x0000 for the 16F628,this is where the program starts runninggoto mainorg 0x0004movwf W_TEMP ; push Wswapf STATUS,W ; push Status without affecting flags. The saved value is swappedmovwf STATUS_TEMPBTFSS INTCON,T0IFgoto exitintCall EncoderexitintBCF STATUS,RP0movlw 0xF0movwf TMR0swapf STATUS_TEMP,W ; swap back status to Wmovwf STATUS ; pop original value to status

swapf W_TEMP,F ; swap back W valueswapf W_TEMP,W ; pop Wbcf INTCON,T0IF ;clear int flagretfiemainmovlw 0x07movwf CMCON ;turn comparators off and enable pins for I/O functionsbsf STATUS, RP0 ;select bank 1movlw 0xff ;set PortB all inputsmovwf TRISBmovlw 0x00movwf TRISA ;set PortA all outputsMOVLW B'10000000' ; Set TMR0 prescaler to 2MOVWF OPTION_REGbcf STATUS,RP0 ;select bank 0movlw 1movwf RCounterCLRF INTCONbsf INTCON,GIEBCF INTCON,T0IFbsf INTCON,T0IELoopmovf FRotation,Wmovwf PORTAgoto LoopEncodermovf PORTB,W ; read port B to Wandlw 0x30 ; Keep only the first bits 5,4movwf tmp ; keep it to tmprrf tmp,Frrf tmp,Frrf tmp,Frrf tmp,Fmovf New,W ; mov the previous "New" valuemovwf Old ; to OLD file registermovf tmp,W ; then move the new valuemovwf New ; to "New" file registerClrf STATUSxorwf Old,W ; xor old and newbtfss STATUS,2 ;if it is zero then bit 2 of status reg is set. if so callreturnCall EncoderStatus ; else call encoderstatusReturnEncoderStatusmovf Old,W ; move the rightandlw 0x01 ; bit of the OLD value to tmp2movwf tmp2movf tmp,Wandlw 0x02 ; move the left bit of themovwf tmp ; new value to tmprrf tmp,0; rotate one bit tmpClrf STATUSxorwf tmp2,W ; xor them. if it is zero decrease else increasebtfss STATUS,2Goto INCRCGoto DECRCINCRCINCF RCounterClrf STATUSmovf RCounter,Wxorlw d'201'btfsc STATUS,2Goto IFROTReturnIFROTINCF FRotationmovlw 0x01movwf RCounterreturnDECRCDecf RCounterClrf STATUSmovf RCounter,Wxorlw d'0'btfsc STATUS,2Goto DFROTreturnDFROTDECF FRotationmovlw d'200'movwf RCounterreturnend 

programul original e aici :http://forum.allaboutcircuits.com/threads/rotary-encoder-16f628.53656/page-2

Link spre comentariu

In aplicatia din site , vor sa determine o distanta pe care o gasesc in binar pe portul A . Eu vreau doar sa semnalizez directia orar prin RA0=1 si antiorar prin RA1=1 .Uite ce am modificat eu 

 

 

CODE 

 

 

   LIST p=16F628A 
          include "P16F628A.inc" 
          __config _INTOSC_OSC_NOCLKOUT & _LVP_OFF & _WDT_OFF & _PWRTE_OFF & _BOREN_OFF & _MCLRE_OFF
         cblock 0x20 
                     tmp                                        ;20
                     tmp2                                       ;21
                     Old                                        ;22
                     New                                        ;23
                     RCounter                                   ;24
                     FRotation                                  ;25
                     dataL                                      ;26
                     a1
                     a2 
                     a3
                     endc
         cblock 0x70 
                     W_TEMP                                     ;70
                     STATUS_TEMP                                ;71
                endc
 
            org 0x0000  
         
                goto main
 
                ;     salvez State inainte de intrerupere //
                    org 0x0004
                 
 
                    movwf W_TEMP 
                    swapf STATUS,W 
                    movwf STATUS_TEMP
                    btfss INTCON,T0IF 
                    goto exitint
                    call Encoder
 
       
           exitint
                    bcf   STATUS,RP0
                    movlw 0xF0
                    movwf TMR0
                    swapf STATUS_TEMP,W 
                    movwf STATUS 
                    swapf W_TEMP,F 
                    swapf W_TEMP,W 
                    bcf   INTCON,T0IF  
                    retfie
 
           main
                   movlw 0x07
                   movwf CMCON 
                   bsf   STATUS, RP0 
                   movlw 0xff 
                   movwf TRISB
                   movlw 0x00 
                   movwf TRISA 
                   movlw B'10000000'
                   movwf OPTION_REG 
                   bcf   STATUS,RP0 
                   movlw 1
                   movwf RCounter
 
                   clrf INTCON 
                   bsf  INTCON,GIE
                   bcf  INTCON,T0IF
                   bsf  INTCON,T0IE
 
          Loop
                   movf FRotation,W
                   movwf PORTA
               
                   goto Loop
 
         Encoder
                   movf PORTB,W 
                   andlw 0x30 
                   movwf tmp 
                   rrf tmp,F 
                   rrf tmp,F 
                   rrf tmp,F 
                   rrf tmp,F 
                   movf New,W 
                   movwf Old
                   movf tmp,W 
                   movwf New
                   clrf STATUS 
                   xorwf Old,W 
                   btfss STATUS,2 
                   return
                   call EncoderStatus 
                   return
 
      EncoderStatus
                   movf Old,W 
                   andlw 0x01 
                   movwf tmp2
                   movf tmp,W
                   andlw 0x02 
                   movwf tmp 
                   rrf tmp,0
                   Clrf STATUS
                   xorwf tmp2,W 
                   btfss STATUS,2
                   goto  INCRC
                   goto DECRC
 
         INCRC
                  INCF RCounter
                  Clrf STATUS
                  movf RCounter,W
                  xorlw d'201'
                  btfsc STATUS,2
                 Goto IFROT
                 Return
        IFROT
                 movlw b'00000001'
                 movwf FRotation
                 
                 movlw 0x01
                 movwf RCounter 
                 return
 
         DECRC
                  Decf RCounter
                  Clrf STATUS
                  movf RCounter,W
                  xorlw d'0'
                  btfsc STATUS,2
                  Goto DFROT
                  return
          DFROT
                 movlw  b'00000010'
                 movwf  FRotation
                 movlw d'200'
                 movwf RCounter 
                 return 
 
 
 
END

Am modificat IFROT si DFROT 

Link spre comentariu

Posted Image

 

 

Un nou algoritm simplist fara mari pretentii : Dectez prima data cand RA0 cade in zero si apoi cu ajutorul RA1 determin directia .

 

Resurse : PIC16F628 , RA0 , RA1 intrarile encoderului cu rezistente de 10k spre + 5v , RB0 , RB1 iesirile care decodifica directia ; RB0 indica o directie , RB1 cealalta 

                encoder rotativ 300 pulsuri /rotatie

 

Obiectiv : se decodifica directia daca encoderul se roteste si se activeaza in consecinta una dintre iesirile RB0, RB1 

                daca encoderul nu se roteste , atunci ambele iesiri raman in 0

 

 

CODE :

 

 

 

 list      p=16f628A          

#include <p16F628A.inc>  
 
errorlevel  -302          
 
__CONFIG   _CP_OFF & _LVP_OFF & _BOREN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTOSC_OSC_NOCLKOUT 
 
 
 
 
 
 
 
 
ORG     0x000            
goto    setup              
 
 
setup                                                                                    ; init PIC16F628A
 
                             banksel  CMCON
                             movlw 0x07                                           ; inchid comparatoare
                             movwf CMCON
                             bsf         STATUS,RP0
                             movlw    b'00000011'                                ; RA0, RA1 input
                             movwf    TRISA
                             clrf         TRISB
                             bcf         STATUS,RP0                               ;  bank 0
                             clrf         PORTA
                             clrf         PORTB
 
encoder
                            clrf           PORTB                                        ; bucla asta asigura STOP ( daca nu exista miscare trebuie ca iesirile sa fei in "0")
                            btfss        PORTA,RA0                                 ; verific daca exista miscare pe RA0
                            goto        $+2
                            goto        encoder
                            btfss        PORTA,RA1                                ; daca exista miscare pe RA1 atunci trebuie sa vad de care : orar sau antiorar
                            goto        orar
                            goto        antiorar
 
     
orar
                            movlw     b'00000001'                                  ; comand miscare orara 
                            movwf     PORTB
                            btfss       PORTA,RA0                                  ; vad daca inca mai exista miscare pe RA0 ( adica encoderul este inca in miscare de rotatie )
                            goto        $+2                                               ; daca DA verific si miscarea pe RA1
                            goto        encoder                                        ; daca NU ma intorc in STOP 
                            btfss       PORTA,RA1                                  ; am detectat miscare si vreau sa vad daca nu cumva so schimbat directia
                            goto        orar                                               ; e aceeasi miscare orara deci ma intorc in bucla asta
                            goto        encoder                                        ; so schimbat miscarea  deci merg intai in STOP si apoi schimb directia 
 
antiorar
 
                            movlw    b'00000010'                                   ; comand miscarea antiorara
                            movwf    PORTB
                            btfss    PORTA,RA0                                     ; vad daca inca mai exista miscare pe RA0 ( adica encoderul este inca in miscare de rotatie )
                            goto     $+2                                                  ; daca DA determin directia
                            goto     encoder                                           ; daca NU ma intorc in STOP
                            btfss    PORTA,RA1                                     ; determin directia
                            goto     encoder                                           ; daca e orar atunci mai intai trebuie sa trec prin stop si abia apoi sa pornesc antiorar
                            goto     antiorar
 
 
        end
 
 
Nu stiu unde gresesc !!? La pornire ambele leduri care ma ajuta sa vad starile RB0 , RB1 raman aprinse . Daca misc intr-o directie incep sa se stinga ledurile cate unul sau ramane unul ramane aprins celalalt clipeste 
Link spre comentariu

Sa inteleg ca tu ai LEDuri sau masori RB0, RB1.

 

Daca vrei sa concepi tu programul il iei in pasi mai mici.

 

1.De exempu RA0. Poti numara de cate ori comutatorul ala o fost inchis ? Cate impulsuri s-au dat in RA0 fara sa conteze directia ?

 

Si rezultatul in afisezi pe RB0-LED. Adica Daca  'tacanit" de 7 ori encoderul, dupa apasarea unui push  LEDul va clipi tot de 7 ori.

 

Poti face asta ? Trebuie un debounce.

----------------------------------------

in figura din postul #13 a trebui sa pui timpul orientativ pe figura.

 

Imi imaginez numaratorul de genul:

-

Etich:

if (RA0==0) contor++

delay(timp minim apasare)

 goto Etich

 

Sau

 

Etich:

if (RA0==0) contor++

delay(timp minim apasare)

if (!(push==0)) goto Etich

 

La encoder algoritmul asa:

 

Etich:

if (RA0==0) contor++

delay(timp minim apasare)

Repeta de100 ori; if (RA1==0) insemna ca se roteste intr-un sens.

goto Etich

 

-------------------------------------------------------------------------------------------------

Fa o simulare in Proteus si ma uit si eu peste ea. Eu am MikroC, dar nu cred ca va fi o problema sa adaptezi programl.

Poatere chiar Encoder in Proteus. Daca nu pui ceva generator de semnal sa simuleze encoderul.:)

Link spre comentariu

Mult prea complicat codul tau a_sorien cand codul dat ca exemplu e foarte simplu : dupa fiecare schimbare pe RA0 sau RA1 , daca valoarea anterioara a RA1 e diferita de valoara actuala a RA0 e un sens , daca e egala atunci e alt sens. 

O traducere in asm a codului:

 

;declara trei octeti  old_porta si  new_porta si timer      clrf old_portamain_loop       movf PORTA, w       movwf new_porta  ; vezi daca s-a schimbat ceva       xorwf old_porta,w       andlw 0x03 ; pastreaza doar primii doi biti RA0 si RA1       btfsc STATUS, Z       goto unchanged; nu s-a schimbat nimic  ; s-a schimbat ceva         rlf old_porta, w; aduce vechiul RA1 pe prima pozitie in w       xorwf new_porta,w ; le compara       andlw 0x01; pastreaza doar bitul zero care ne intereseaza       btfss STATUS,Z       goto orar ; diferiteantiorar   movlw   b'00000010' ; comand miscarea antiorara   clrf timer; sterge timerul   goto endtestorar           movlw   b'00000001' ; comand miscarea orara   clrf timer;  sterge timerul   goto endtest  unchanged      incfsz timer ,f ;      goto main_loop   movlw   b'00000000'  ; daca timer-ul s-a dat peste cap sterge RB0 si RB1endtest ; actualizeaza corespunzator portul B   movwf   PORTB   movf new_porta, w ; actualizeaza old_porta   movwf old_porta       goto main_loop 

 

 Detectarea opririi se face simplist , la 256 de bucle fara nici o schimbare cand timer se da peste cap se sterge portul B , se mai pot aduce imbunatatiri, sa folosesti un timer pe intreruperi eventual.

Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări