post the code you are trying , and a bit of info about your re setup .
does it have detents ?
how many edges per turn ?
pull ups ?
filter caps ?
pic type ?
pins used ?
is not much to work withstill not able to make my panel encoder working
post the code you are trying , and a bit of info about your re setup .
does it have detents ?
how many edges per turn ?
pull ups ?
filter caps ?
pic type ?
pins used ?
is not much to work withstill not able to make my panel encoder working
Thanks for the assistance.
My encoder has detents and has about 24 edges per turn.
I used a pull up of 2x 10 k on both encoder phases and a 2x 0.1uF to ground.
I am using pic18f452 , xtal=10 Mhz, ppl X 4 to get 40 Mhz clock speed.
I used RB0 for the "A" phase as shown on the code.
At the end of the world I am now able to make it working well using the following picbasic program by including Darrel Taylor interrupt routine.
The program prints counter results on a terminal @ 115200 baud rate 8,n,1.
Regards, Ambro
DEFINE OSC 40 ' XTAL= 10 MHZ CLOCK= 40 MHZ
INCLUDE "MODEDEFS.BAS"
INCLUDE "DT_INTS-18.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP-18.bas" ; Include if using PBP interrupts
INTCON2.BIT6=0 ' interrupt from 1 down to 0 on RB0
CNT VAR WORD ' COUNTER TO BE DISPLAYED ON TERMINAL
CNT= 32000
CNTOLD VAR WORD
CNTOLD=32000
B VAR PORTD.1 ' encoder B PHASE
A VAR PORTD.0 ' encoder A PHASE
' DEBUG INTERFACE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ \\\\\\\\\\\\\\
'' Set Debug pin port ________________________________________
DEFINE DEBUG_REG PORTD
'' Set Debug pin bit _________________________________________ PIC_PIN_30
DEFINE DEBUG_BIT 7
'' Set Debug baud rate _________________________________________
DEFINE DEBUG_BAUD 115200
'' Set Debug mode: 0 = true, 1 = inverted ______________________
DEFINE DEBUG_MODE 1
DEBUG 13,10,13,10, " START OF PROGRAM ", 13, 10, 13, 10
ADCON1=7 ' all digital !
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler INT_INT, _ToggleLED1, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
@ INT_ENABLE INT_INT ; enable external (INT) interrupts
Main:
PAUSE 1
IF CNT <> CNTOLD THEN
DEBUG DEC CNT,13,10
CNTOLD=CNT
ENDIF
sorry for not having paste the complete code...
DEFINE OSC 40 ' XTAL= 10 MHZ CLOCK= 40 MHZ
INCLUDE "MODEDEFS.BAS"
INCLUDE "DT_INTS-18.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP-18.bas" ; Include if using PBP interrupts
INTCON2.BIT6=0 ' interrupt from 1 down to 0
CNT VAR WORD ' COUNTER TO BE DISPLAYED ON TERMINAL
CNT= 32000
CNTOLD VAR WORD
CNTOLD=32000
B VAR PORTD.1 ' encoder B PHASE
A VAR PORTD.0 ' encoder A PHASE
' DEBUG INTERFACE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ \\\\\\\\\\\\\\
'' Set Debug pin port ________________________________________
DEFINE DEBUG_REG PORTD
'' Set Debug pin bit _________________________________________ PIC_PIN_30
DEFINE DEBUG_BIT 7
'' Set Debug baud rate _________________________________________
DEFINE DEBUG_BAUD 115200
'' Set Debug mode: 0 = true, 1 = inverted ______________________
DEFINE DEBUG_MODE 1
DEBUG 13,10,13,10, " START OF PROGRAM ", 13, 10, 13, 10
ADCON1=7 ' all digital !
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler INT_INT, _ToggleLED1, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
@ INT_ENABLE INT_INT ; enable external (INT) interrupts
Main:
PAUSE 1
IF CNT <> CNTOLD THEN
DEBUG DEC CNT,13,10
CNTOLD=CNT
ENDIF
GOTO Main
'---[INT - interrupt handler]---------------------------------------------------
ToggleLED1:
if b=0 then cnt=cnt-1
IF B=1 THEN CNT=CNT+1
@ INT_RETURN
I found that strategy gave quite disappointing results , was jerky missed counts and had sudden and unexpected direction reversals. there are better waysCode:ToggleLED1: if b=0 then cnt=cnt-1 IF B=1 THEN CNT=CNT+1 @ INT_RETURN
I am sorry Richar for having posted the file that is not the final one:
please change the following:
A VAR PORTD.0 ' encoder A PHASE
shAll be:
A VAR PORTB.0
This is the interrupt input !
I would be happy to know ...
Thanks and regards,
Ambrogio
I did capture the output of the terminal printout for a better check.
There are about 200 changes of the cnt obtained by "manually" turning the encoder knob on my control panel. Probably sometims cw and ccw.
I noted very few spikes : I am not shure if they are due to the time required for the serial port output or to the encoder software.
Any improvement to the program is very much appreciated.
I am really searching for a good solution.
Thanks
regards,
Ambrogio
I do it this way
enc pins must be sequential and on same port
both enc pins must be able to generate an interrupt (ioc on neg and pos edge is best , ioc, rac,rbc on neg or pos edge will work as will int0 int1)
enc pins must be pulled up (10k) and have 0.1uF filter caps
I have an asm version that's 100 bytes smaller and has about 1 tenth of the irq latency and is much faster too
Code:'**************************************************************** '* Name : rotary encoder.BAS * '* Author : richard * '* Notice : Copyright (c) 2013 * '* : All Rights Reserved * '* Date : 9/4/2013 * '* Version : 1.0 16f1825 * '* Notes : enca porta.2 encb porta.3 * '* : note mclr disabled ,full quad decode * '**************************************************************** #CONFIG __config _CONFIG1, _FOSC_INTOSC & _CP_OFF & _WDTE_ON & _PWRTE_ON & _MCLRE_OFF & _CLKOUTEN_OFF __config _CONFIG2, _PLLEN_ON & _LVP_OFF #ENDCONFIG include "dt_ints-14.bas" include "REENTERPBP.bas" asm INT_LIST macro INT_HANDLER IOC_INT, _enc_isr,pbp,NO endm INT_CREATE ENDASM DEFINE OSC 32 OSCCON=$70 ANSELA=0 OPTION_REG.6=0 ev VAR BYTE bank0 cnt VAR WORD bank0 TMP VAR BYTE bank0 enca VAR porta.2 encb VAR porta.3 TRISA = 111110 lata.0=1 IOCAP=12 ;enca porta.2 encb porta.3 pos edge trigger IOCAN=12 ;enca porta.2 encb porta.3 neg edge trigger pause 4000 serout2 PORTA.0,84,[ "ready",13,10] IOCAF=0 INTCON=$C8 mainloop: serout2 PORTA.0,84,[13,10, "C",#CNT] pause 1000 goto mainloop enc_isr: ev=ev<<2 ;shift last reading into position ev=ev|((porta&12)>>2) ;read enc pins 2,3 mask off others then combine this reading with last reading LOOKUP (ev&$f),[0,255, 1, 0, 1, 0, 0, 255, 255, 0, 0, 1, 0, 1, 255, 0],tmp ;lookup the decision matrix if tmp then ; decide to inc , dec or ignore if tmp.7 then cnt=cnt-1 else cnt=cnt+1 endif endif intcon.0=0 ; clean up and exit iocaf=0 @ INT_RETURN
Thanks Richard for the code.
I am just a little bit busy on these days and so I plan to try your code on next days.
As you have seen I am using pic18f452: Is your code applicable to this micro ?
If no, what should I modify or adapt ?
Thanks
Regards,
Ambrogio
Bookmarks