encoder=0
:o
Printable View
encoder=0
:o
Quote:
Had to resort to a tiny bit of ASM, getting the high word of a 16*16bit multiplication back from PBP without resorting to actually using LONGs.
did you and dt make this ? , i use it if req
;32 bit multiply result
A32bitVar var word[2]
Dummy var word
ASM
GetMulResult macro Dword
MOVE?WW R2, Dword ; Low Word
MOVE?WW R0, Dword + 2 ; High Word
endm
ENDASM
Dummy = 1000
Dummy = Dummy * Dummy
@ GetMulResult _A32bitVar
Thanks, hadn't seen (or did not remember seeing, certainly can't take credit for it) that macro but that's pretty much what I did except I copied the value byte-by-byte instead of using the MOVE?WW macros.
Henrik,
I tested your last code with a mechanical quadrature encoder and works just fine with a couple of 100nF debouncing capacitors and internal pull ups of the PIC.
I noticed though, a jump on the position variable due to mechanical problem of the encoder. Say you are at the beginning with position at 0. One click on the right increments to 4 and one to left gets back to 0. Sometimes due to little more movement of the axis of the encoder you may get a 65535 then back to 0. This of course is not a software problem, rather a pure mechanical, but a user may perceive it as a program error.
Ioannis
Yes, it's because your particular encoder has 4 counts per detent and, as you say, sometimes it will "overshoot" the detent slightly causing the code register one count before it "springs back" into the detent position. The important thing is that the code DOES register it "springing back" so that it doesn't lose position.
These mechanical encoders exists with either 4 counts (one quadrature cycle) per detent or 1 count (1/4 quadrature cycle) per detent. Using 1x decoding with an encoder that has 1 count per detent means you'd have to turn it 4 clicks for each increment. However, with the type of encoder you have using 1x decoding might be better.
Absolutely agree. Code works as expected and is fast enough for manual rotation. Have not tested for faster resposne.
The encoder indeed has a detent that produces 4x pulses so yeah. It is not appropriate for that code.
Ioannis
Not the best programming techniques but uses interrupts and is fast enough for x4 encoders like ALPS with push switch used to reset the position counter.
Based on Henrik's example and tested on 16F886.
IoannisCode:intcon=%10001000
iocb=7
Encoder VAR BYTE
Old_Enc VAR BYTE
Test VAR BYTE
Dir VAR WORD ' Must be same size as Position variable
position var word
ch_a var portb.0
ch_b var portb.1
detent var byte
flag var bit
clear
INCLUDE "DT_INTS-14.bas" ' Base Interrupt System
INCLUDE "ReEnterPBP.bas" ' Include if using PBP interrupts
wsave var byte $70 system
':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler RBC_INT, _rotary, PBP, yes
endm
INT_CREATE
ENDASM
@ INT_ENABLE RBC_INT ; Enable PortB.0 interrupt for signal reception
goto main
rotary:
'-------------------------------------------------------------
'--------------Poll encoder and keep count -------------------
'-------------Alternative routine with 4x decoding------------
'-------------------------------------------------------------
Encoder.0 = Ch_A
Encoder.1 = Ch_B
Test = Encoder ^ Old_Enc
Dir = 0
If Test = 1 THEN
If Old_Enc = 0 THEN Dir = 1
IF Old_Enc = 1 THEN DIR = -1
IF Old_Enc = 2 THEN Dir = -1
If Old_Enc = 3 Then Dir = 1
ENDIF
IF Test = 2 THEN
IF Old_Enc = 0 THEN DIR = -1
IF Old_Enc = 1 THEN Dir = 1
IF Old_Enc = 2 THEN Dir = 1
IF Old_Enc = 3 THEN Dir = -1
ENDIF
if !portb.2 then 'Reset counter
position=0
flag=1
endif
if Old_Enc <> Encoder then
Old_Enc = Encoder
detent=detent+1 'Increment position after 4 pulses (one detent on ALPS encoder)
if detent = 4 then
Position = Position + Dir
detent=0
flag=1
endif
endif
@ INT_RETURN
main:
while 1
if flag then
hserout [#position,13,10]
flag=0
endif
'other code stuff here
wend
END