-
New approach to Rotary Encoder
Here is an experiment on Rotary Encoders and a different approach than the standard XOR way.
Code:
loop1:
if portb.1=0 then 'here is switch 1 of the rotary encoder
counter=counter+1
goto lcd
endif
if portb.0=0 then 'here is switch 2 of the rotary encoder
counter=counter-1
goto lcd
endif
goto loop1
lcd:
lcdout $fe,$c0,dec5 counter
while (portb.0=0 or portb.1=0):pause 10:wend
goto loop1
The key is the last While/Wend command where it checks for the next pulse comming after the first edge of either switch of the encoder.
Common of the encoder is Low and Pull Up is supposed to be active.
Ioannis
-
Can you refresh our memory and show us an example of "the standard XOR way"?
-
2 Attachment(s)
Two examples in the attachments. They use Interrupts though. When I find some spare time I wll try to make the routines work with IOC and DT-INTS too.
Ioannis
-
Re: New approach to Rotary Encoder
Did you try this code with mechanical encoder, or normal optical encoder?
-
Re: New approach to Rotary Encoder
That was with mechanical one.
Ioannis
-
Re: New approach to Rotary Encoder
With use 4 mecanic rotary encoder with this code (pic18f4550) ?
-
Re: New approach to Rotary Encoder
I don't see why not. Its fast enough.
Ioannis
-
1 Attachment(s)
Re: New approach to Rotary Encoder
A question, please? With the following "while" statement, does the program wait there until both encoder pins are high? If so, then you're only detecting one of every four AB transitions when moving continually in one direction, correct?
Code:
while (portb.0=0 or portb.1=0):pause 10:wend
Attachment 5872
-
Re: New approach to Rotary Encoder
Yes I think you are correct, this will only detect from 3 to 0 or 3 to 2. So it does not count in quadrature mode. It could be modified with a few more while loops to detect when it leaves the current state.
-
Re: New approach to Rotary Encoder
I think not since there is OR in the WHILE statement.
Ioannis
-
Re: New approach to Rotary Encoder
Quote:
Originally Posted by
Ioannis
I think not since there is OR in the WHILE statement.
But doesn't the OR mean that you're stuck in this loop while either A OR B is low? In other words, you can only get out of the loop when both A and B are high?
-
Re: New approach to Rotary Encoder
Yup, as long as one is LOW, it remains in the loop.
Robert
-
Re: New approach to Rotary Encoder
Yes it will for the time that either is in LOW state. If there is a possibility that this condition is likely to happn pemanently, then you have other options to choose.
As stated on he first post, that is an interesting experiment of another way (more simple) to do the same task. No-one is forced to accept it. Or use it. Just forget it and you will be just fine. :)
Ioannis
-
Re: New approach to Rotary Encoder
Please forgive me if it seemed that I was complaining. I was just trying to understand how your method worked.
If you're using a rotary encoder with detents as a control, detecting a single AB transition (out of four) between detents is probably preferable. That's how I do it but I use a switch state latch and simple parallel switch state logic to filter out the unwanted switch states.
Your method is simple and elegant. Thank you for sharing with us...
Cheerful regards, Mike
-
Re: New approach to Rotary Encoder
No problem Mike. I have to admit that I was a little touchy.
Yes, the idea was to read a mechanical rotary encoder with detents. Sure is better to buffer the port states and then do the processing.
Even better, use interrups to grab the port change and then do whatever you want. More, make a debounce based on interrupts since mechanical switch of the encoder do bounce a little. But this is for more advanced programmers. Maybe later when my related project allows.
Ioannis
-
1 Attachment(s)
Re: New approach to Rotary Encoder
Hello world. I have learnt a lot from lurking these threads so i thought i would try and help someone else out a bit.
All your encoder worries can be over for about 50 pence and if i can get a picture in here i will show you how...........
Attachment 6111
the thing to realise is that moving along waveform A from left to right the negative edge of A is always when B is low. moving back the other way the negative edge is always when B is high.
the jk flip flop clock input is negative edge triggered and when triggered it feeds the input on J through to Q -- but only if j and k inputs are opposite hence section 1 of the nor gate to invert the signal. j is always opposite to k now. and the clock input always gets triggered right in the middle of the high or low so it never misses.
so, when moving clockwise Q will be high and anticlockwise it will go low.
two other parts of the quad nor gate (2 and 3 above) to produce a hardware XOR on output C and producing the waveform at bottom of screen.
Now all you need to do is feed C into an input that generates interrupts on a negative edge trigger. when the interrupt fires all it has to do is look at the level of D and either add 1 to clockwise total or subtract 1. Thats it. Your programming days are over.
And, all the mushy signal edges and bounce are tidied up too. Lovely solid latched outputs.
And you are going to have to go some to bother them with speed or with slowness.
Not bad for 50p I hope you will agree.
-
Re: New approach to Rotary Encoder
Hey podgycode...
I have not tried your circuit. I would guess it works as you describe.
What I can't understand is why is this so difficult to do using two PIC pins and some code. Are these rotary encoders so difficult to read using code??
I am struggling with this very thing myself. I have two rotary encoders... one that I have wired up and done some basic testing... one that I have not tried yet.
I have also done quite a bit of searching over on the Parallax Basic Stamp forum, since the basic stamp uses VERY similar language to our PICbasic.
I really would like to use interrupts (DT instant INT's, if possible)
My real problem is TIME. If I only had more of it, I'm sure you all can relate.
Any way, if anyone has some good sample code (that used interrupts) for one to try... that they might be willing to share :)
-
Re: New approach to Rotary Encoder
Here the code for a rotary optical encoder, using quadrature.
Just connect the Channel A to portB.6 and channel B to portB.7, ground portB.5 and portB.4
Connection for LCD can be found to page 96 of PBP user manual.
Code:
include "ALLDIGITAL.pbp"
INCLUDE "DT_INTS-14.bas" ; Base Interrupt System
'INCLUDE "ReEnterPBP.bas" ; Include if using PBP interrupts
DEFINE OSC 20
' PIC 16F628
' PicBasic program to demonstrate operation of an LCD in 4-bit mode
' and reading an optical encoder in quadrature
'
' LCD should be connected as follows:
' LCD PIC
' DB4 PortA.0
' DB5 PortA.1
' DB6 PortA.2
' DB7 PortA.3
' RS PortA.4 (add 4.7K pullup resistor to 5 volts)
' E PortB.0
' RW Ground
' Vdd 5 volts
' Vss Ground
' Vo 20K potentiometer (or ground)
' DB0-3 No connect
TrisA = 000000
TrisB = 110000
PortB=0
Define LCD_DREG PORTA
Define LCD_DBIT 0
Define LCD_RSREG PORTA
define LCD_RSBIT 4
define LCD_EREG PORTB
define LCD_EBIT 0
define LCD_BITS 4
define LCD_LINES 2
define LCD_COMMANDUS 2000
define LCD_DATAUS 50
Flag var bit
wsave VAR BYTE $70 SYSTEM ' alternate save location for W
Q_New var Byte
Q_Old var byte
Q_Count var word
' Set variable value @ startup
Flag = 0
Q_New = 0
Q_Old = 0
Q_Count = 0
ASM
INT_LIST macro ; IntSource, Label, Type, Resetflag?
INT_Handler RBC_INT, _Encoder, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
@ INT_ENABLE RBC_INT ; enable external (INT) interrupts
Lcdout $fe, 1 ' Clear LCD screen
Lcdout "System Ready" ' Display message
Pause 500 ' Wait .5 second
Goto Main_Loop
Encoder:
Q_New = PortB.7 + PortB.7 + PortB.6
if Q_Old = 0 then
if Q_New = 2 then Minus_Count
if Q_New = 1 then Plus_Count
endif
if Q_Old = 1 then
if Q_New = 0 then Minus_Count
if Q_New = 3 then Plus_Count
endif
if Q_Old = 3 then
if Q_New = 1 then Minus_Count
if Q_New = 2 then Plus_Count
endif
if Q_Old = 2 then
if Q_New = 3 then Minus_Count
if Q_New = 0 then Plus_Count
endif
goto Q_Skip
Minus_Count:
Q_Count = Q_Count - 1
Flag = 1
goto Q_Skip
Plus_Count:
Q_Count = Q_Count + 1
Flag = 1
Q_Skip:
Q_Old = Q_New
@ INT_RETURN
Main_Loop:
if Flag = 1 then
Lcdout $fe, 1
Lcdout Dec Q_Count
Flag = 0
endif
goto Main_Loop
end
Enjoy
Cheers
Al.
-
Re: New approach to Rotary Encoder
heckler,
have a look at this:-
' Target PIC : 12F, 16F, 18F
' Hardware : Non specific
' Oscillator : internal or external
' Keywords : ON INTERRUPT
' Description : PICBASIC PRO program to demonstrate use of On Interrupt
' Interrupts in BASIC. Turn LED on. Interrupt on PORTB.0 (INTE) turns LED off.
' Program waits .5 seconds and turns LED back on.
led Var PORTB.7
OPTION_REG = $7f ' Enable PORTB pullups
On Interrupt Goto myint ' Define interrupt handler
INTCON = $90 ' Enable INTE interrupt
mainloop:
High led ' Turn LED on
Goto mainloop ' Do it forever
' Interrupt handler
Disable ' No interrupts past this point
myint:
Low led ' If we get here, turn LED off
Pause 500 ' Wait .5 seconds
INTCON.1 = 0 ' Clear interrupt flag
Resume ' Return to main program
Enable
End
------------------------
the main loop runs and when an interrupt happens the program jumps to the handler called myint. does what is in myint and then returns to resume where it left off in the main loop.
just set the config so your interrupt is enabled that you want to use and put the code to read it in the myint routine. the main loop can do whatever it likes.
what do you think?
-
Re: New approach to Rotary Encoder
Quote:
Originally Posted by
aratti
Connection for LCD can be found to page 96 of PBP user manual.
Do you have a link the that manual, please? I've looked at two different PBP Compiler Manuals so far and neither has a schematic for an LCD interface on page 96...
-
Re: New approach to Rotary Encoder
@ podgycode... Thanks for your example, but what I meant was I would like to implement a rotary encoder via DT's Instant Interupts. I have used "on interrupt" successfully before to detect push buttons, etc. I have yet to use InstantINT's. I am going to try aratti's example in post #18 above.
@ aratti... could you please clarify a couple of questions regarding your example...
Quote:
ground portB.5 and portB.4
Why is this necessary?
Quote:
Q_New = PortB.7 + PortB.7 + PortB.6
What does this line of code do??
Quote:
TrisA = 000000
TrisB = 110000
I assume these need % in front of the binary number??
I hope this is not considered "hijacking" of this thread... as it still regards implementing Rotary Encoders.
Thanks for your help
example
-
Re: New approach to Rotary Encoder
@ aratti... one more question
Quote:
wsave VAR BYTE $70 SYSTEM ' alternate save location for W
could you help me with this line? Is it correct or did the forum software mess it up??
thanks
P.S. Oh yea... disregard this question... I think I see how it works..
Quote:
Q_New = PortB.7 + PortB.7 + PortB.6 What does this line of code do??
-
Re: New approach to Rotary Encoder
Heckler, yes trisA and trisB need "%" (don't know Why have been removed)
PortB.4 and portB.5 are set as input and never leave an input pin floating.
Wsave is a variable used by DT INT-14.
@Mike K8LH
The PBP manual they give me with PBP ver 2.47. But you can Find it also at page 168 of PBP3 manual.
Cheers
Al.
-
Re: New approach to Rotary Encoder
Quote:
Originally Posted by
aratti
@Mike K8LH
The PBP manual they give me with PBP ver 2.47. But you can Find it also at page 168 of PBP3 manual.
I wonder if there may be a problem with the PBP3 manual at http://www.pbp3.com/downloads/PBP_Reference_Manual.pdf? It seems to stop downloading at 731 kB (consistently)... Argh!!!
-
Re: New approach to Rotary Encoder
Works fine here. I just opened it in my browser.
-
Re: New approach to Rotary Encoder
Quote:
Originally Posted by
mackrackit
Works fine here. I just opened it in my browser.
Ok, it worked today... I've got it...
-
Re: New approach to Rotary Encoder
Here I post an update of the code posted in #18. This new code has a more efficient ISR so it can read at higher frequency. I don't know the maximum frequency that the system can acheive, so if someone with some spare time will give a try and post the result, could be useful.
As the previuos code, the mainloop doesn't do much, it simply update the display.
Here the code revised:
Code:
' PicBasic program to demonstrate how to read an optical encoder
' in quadrature. The code uses a 2 lines LCD in 4-bits mode
' **** MCU USED: PIC 16F628 ***
'
' ------------------ LCD should be connected as follows -------------------
' LCD PIC Port
' --- --------
' DB4 PortA.0
' DB5 PortA.1
' DB6 PortA.2
' DB7 PortA.3
' RS PortA.4 (add 4.7K pullup resistor to 5 volts)
' E PortB.0
' RW Ground
' Vdd 5 volts
' Vss Ground
' Vo 20K potentiometer (or ground)
' DB0-3 No connected
'-------------------------------------------------------------------------
' Encoder channel A PortB.6 (use pullups resistor if necessary)
' Encoder channel B PortB.7 (use pullups resistor if necessary)
' N/U PortB.0 (output)
' N/U PortB.1 (output)
' N/U PortB.2 (output)
' N/U PortB.3 (output)
' N/U PortB.4 (input - to be grounded)
' N/U PortB.5 (input - to be grounded)
'
'-------------------------------------------------------------------------
INCLUDE "DT_INTS-14.bas" ' Base Interrupt System (by Darrel Taylor)
DEFINE OSC 20
eeprom 0,[2,0,3,1,1,3,0,2]
Define LCD_DREG PORTA
Define LCD_DBIT 0
Define LCD_RSREG PORTA
define LCD_RSBIT 4
define LCD_EREG PORTB
define LCD_EBIT 0
define LCD_BITS 4
define LCD_LINES 2
define LCD_COMMANDUS 2000
define LCD_DATAUS 50
CMCON = %00000111
TrisA = %00000000
TrisB = %11110000
PortB = 0
Flag var bit
wsave VAR BYTE $70 SYSTEM ' alternate save location for W
Q_New var Byte
Q_Old var byte
M_Count var byte [4]
P_Count var byte [4]
Q_Count var word
' ---------------------- Set variable value @ startup ----------------------
For Q_Old = 0 to 3
Read Q_Old,M_Count[Q_Old]
Read Q_Old + 4,P_Count[Q_Old]
Next Q_Old
Q_Count = 0
Q_New = 0
Q_Old = 0
Flag = 0
ASM
INT_LIST macro ; IntSource, Label, Type, Resetflag?
INT_Handler RBC_INT, _Encoder, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
@ INT_ENABLE RBC_INT ; enable external (INT) interrupts
'---------------------------- Initialize LCD ----------------------------
Lcdout $fe, 1 ' Clear LCD screen
Lcdout "System Ready" ' Display message
Pause 500 ' Wait .5 second
Goto Main_Loop
Encoder: ' ISR
Q_New = PortB.7 + PortB.7 + PortB.6 ' get port status
If M_Count[Q_Old] = Q_New then ' if M_Count code satisfied then minus
Q_Count = Q_Count - 1
Flag = 1 ' set flag to true to update display
goto Q_Skip
endif
If P_Count[Q_Old] = Q_New then ' if M_Count code satisfied then plus
Q_Count = Q_Count + 1
Flag = 1 ' set flag to true to update display
endif
Q_Skip:
Q_Old = Q_New ' update Q_Old Byte
@ INT_RETURN
Main_Loop:
if Flag = 1 then
Lcdout $fe, 1 ' Clear LCD screen
lcdout dec Q_Count ' Display encoder position (counts)
Flag = 0 ' reset flag to false, display updated
endif
goto Main_Loop
end
Cheers
Al.
-
Re: New approach to Rotary Encoder
Thanks! Aratti...
I had just finished adapting your earlier example for a 16F690 pic. It took me a while to figure out why my LCD was not working... Dang MCLR pin tripped me up untill I rememberd that it could not act as an output... then I had to move my LCD to PortC... then I had to figure out that my OLD 4 line LCD (bought it about 20 Years ago from AllElectronics) needed more time on the LCD_COMMANDUS.
Anyway it is working GREAT...
I will give your latest code a spin this weekend.
As far as update time to the LCD... it seems to be limited to any Pause or other code that is in the Main Loop. I had been blinking an LED in the main loop using a Pause statement and therefore this limited the LCD update frequency. I think I'll try and impliment another DT-Int using a timer to run the blinking LED in the main loop. This should remove any excessive delay to the LCD update.
PS. I can post Aratti's modified working code for the 16F690 if anybody is interested...
-
Re: New approach to Rotary Encoder
Quote:
Originally Posted by
Heckler
.... As far as update time to the LCD... it seems to be limited to any Pause or other code that is in the Main Loop. I had been blinking an LED in the main loop using a Pause statement and therefore this limited the LCD update frequency. I think I'll try and impliment another DT-Int using a timer to run the blinking LED in the main loop. This should remove any excessive delay to the LCD update.
May I offer insight into another way around this problem? I've always been concerned about the overhead of printing to an HD44780 compatible character display. For example, if you tie up the processor for 400 usecs while printing eight (8) characters to the LCD, you might have a problem with another process that needs to run at 100 usec intervals. Instead of updating the display the usual way, with a 40 usec delay between each write, why not refresh the LCD from a 32 character buffer as a background task using interrupts. I did this recently on a TI MSP430 Launchpad project and it worked very well.
Here's the basic idea (C code). Your main program simply writes ASCII data into a 32 character array to update the display. Array elements 0-15 and 16-31 are mapped to LCD lines 1 and 2, respectively. The driver in the ISR only writes one character at a time from the array to the LCD during each interrupt, but I used a 500 usec interrupt interval so the entire display is actually updated around 59 times each second (updates are perceived as instantaneous). Also note that the PutLCD routine (not shown) does not need to include the normal 40 usec LCD inter-character delay.
Food for thought... Regards, Mike
Code:
unsigned char lcd[32] = { " " };
Code:
void interrupt()
{ // 500 us TMR2 interrupts
static char bndx = 0x00; // lcd display buffer index, 0..31
static char line = 0xC0; // lcd display DDRAM address
pir1.TMR2IF = 0; // clear TMR2 interrupt flag
/* *
* refresh one character on the display each interrupt. entire *
* display refreshed every 17 msecs (58.8 Hz refresh rate). *
* */
if(line.7) // if "new line"
PutLCD(line ^= 64,0); // toggle LCD DDRAM "line" address
else // not "new line" so
PutLCD(lcd[bndx++],1); // refresh display, bump index
bndx &= 31; // pseudo mod 31, 0..31 inclusive
if((bndx & 15) == 0) // if new line (0 or 16)
line.7 ^= 1; // toggle b7 pseudo "new line" flag
}
-
1 Attachment(s)
Re: New approach to Rotary Encoder
For some peculiar reason that I cannot understand, Al's code is counting +/- 4 steps instead of one for each click.
Anyone can speculate why?
With a logic analyzer I have confirmed that the encoder is working fine. Here is a snapshot for 4 clicks of the encoder.
Attachment 6164
Ioannis
-
Re: New approach to Rotary Encoder
Hi Ioannis,
I haven't looked at the particular code in question but generally, you decode all 4 edges, hence the term quadrature. Look at the capture for one click, first Ch.0 goes low (1) then Ch.1 goes low (2), then Ch.0 goes high (3) and finally Ch.1 goes high (4). So, 4 counts per click.
/Henrik.
-
Re: New approach to Rotary Encoder
Hmm, thanks Henrik, it looks logic now... well...
Ioannis
-
Re: New approach to Rotary Encoder
I need a rotary encoder for manual input in flight simulator; changing radio frequency, autopilot altitude, etc. I like the "slower" detection in post #1 for this particular application or else I'd issue 4 keyboard commands in a single detent. 100 feet would change to 500 feet with a single click with no way to set to the in-between values.
But Podgy brings up a very important point; all rotary encoder datasheets I've seen mention debounce. I know most PIC inputs have Schmitt triggers, but just how effective are they in these cases? I can't test until my batch arrives.
Robert
:)
-
Re: New approach to Rotary Encoder
a couple of 100nF were needed for mine. After placing the caps to ground from each encoder output pin, false readings were a past.
Ioannis
-
1 Attachment(s)
Re: New approach to Rotary Encoder
Need help with one enconder ... a little different.
How can I read the "up/+" and "down/-" action of this particular encoder ?
Any help will be appreciated ! Thanks in advance !
-
Re: New approach to Rotary Encoder
It's ok something like this ?!
Code:
TrisA = %00000000
TrisB = %11110000
PortB = 0
Flag var bit
Q_New var Byte
Q_Old var byte
M_Count var byte [4]
P_Count var byte [4]
Q_Count var word
' ---------------------- Set variable value @ startup ----------------------
For Q_Old = 0 to 3
Read Q_Old,M_Count[Q_Old]
Read Q_Old + 4,P_Count[Q_Old]
Next Q_Old
Q_Count = 0
Q_New = 0
Q_Old = 0
Flag = 0
Goto Main_Loop
Encoder: '
Q_New = PortB.7 + PortB.6 + PortB.5 ' get port status
If M_Count[Q_Old] = Q_New then ' if M_Count code satisfied then minus
Q_Count = Q_Count - 1
Flag = 0 ' set flag for DOWN
goto Q_Skip
endif
If P_Count[Q_Old] = Q_New then ' if M_Count code satisfied then plus
Q_Count = Q_Count + 1
Flag = 1 ' set flag for UP
endif
Q_Skip:
Q_Old = Q_New ' update Q_Old Byte
Main_Loop:
if Flag = 1 then do command1
if Flag = 0 then do command2
goto Main_Loop
-
1 Attachment(s)
Re: New approach to Rotary Encoder
So far...no good :( ...
Complete "hardware" it's like in picture . I intend to use an remote with some "rotary encoder" ...
The remote controller has six wires . They are connected to three rows and three columns. This allows maximum of 3*3=9 functions. Roller takes three functions because it must be possible to know which way it is rotated (how doing this in PBP ?!?). Rest of the functions are assigned to six buttons.
I use great pice of code (keypad matrix routine) of Mr. Mister-e and the "regular" buttons works verry fine...but I want to use the function of roller too.
I can't figure out how doing this, so any "clue" will be appreciated !
-
Re: New approach to Rotary Encoder
Hi,
Without analyzing your code in detail one possible problem might be this line
Code:
Q_New = PortB.7 + PortB.6 + PortB.5 ' get port status
In this case you'll get Q_New = 1 no matter WHICH of the three pins are high. I'm not sure but I guess that's not what you want.
You could try something like Q_New = PortB & %11100000 >> 5 instead.
Here's another approach (untested) which is smaller in terms of program space and RAM but like I said it's untested so it might not even work.
Code:
oldState VAR BYTE
newState VAR BYTE
Q_Count VAR WORD
DIR VAR BIT
UP CON 1
DN CON 0
newState = (PortB & %11100000) ' Isolate top three bits, newState will be 32, 64 or 128
If newState <> 0 THEN
If newState <> oldState THEN ' Changed from last time?
Select Case oldState
Case 32
If NewState = 128 THEN ' Was 1 now 4 = Up
Q_Count = Q_Count + 1
DIR = UP
ELSE ' Was 1 now 2 = Down
Q_Count = Q_Count - 1
DIR = DN
ENDIF
Case 64
If NewState = 32 THEN ' Was 2 now 1 = Up
Q_Count = Q_Count + 1
DIR = UP
ELSE ' Was 2 now 4 = Down
Q_Count = Q_Count - 1
DIR = DN
ENDIF
Case 128
If NewState = 64 THEN ' Was 4 now 2 = Up
Q_Count = Q_Count + 1
DIR = UP
ELSE ' Was 4 now 1 = Down
Q_Count = Q_Count - 1
DIR = DN
ENDIF
END SELECT
oldState = NewState
ENDIF
ENDIF
-
2 Attachment(s)
Re: New approach to Rotary Encoder
It a real pleasure to see how generous some people can be ... Thank You, AGAIN, Mr. Henrik !
...I think I missing something ... If UP do something, If Down do something else...dont ?!
But nothing happens.
Code:
'****************************************************************
@ DEVICE pic16F628A, XT_OSC, WDT_OFF, PWRT_ON, BOD_OFF, MCLR_ON, LVP_OFF
Define OSC 4 ' 4MHz
CMCON = 7 ' Disable on-chip comparator, PORTA in digital mode
include "alldigital.pbp"
TrisA = 000000
PortB = 010000
TrisB = 000000
oldState VAR BYTE
newState VAR BYTE
Q_Count VAR WORD
DIR VAR BIT
UP CON 1
DN CON 0
Main_Loop:
newState = (PortB & 100000)
goto encoder
if dir = up then portb.0 = 1
if dir = dn then portb.1 = 1
goto Main_Loop
goto encoder
if dir = up then
portb.4 = 1
portb.0 = 1
endif
if dir = dn then
portb.4 = 0
portb.1 = 1
endif
goto Main_Loop
encoder:
If newState <> 0 THEN
If newState <> oldState THEN ' Changed from last time?
Select Case oldState
Case 32
If NewState = 128 THEN ' Was 1 now 4 = Up
Q_Count = Q_Count + 1
DIR = UP
ELSE ' Was 1 now 2 = Down
Q_Count = Q_Count - 1
DIR = DN
ENDIF
Case 64
If NewState = 32 THEN ' Was 2 now 1 = Up
Q_Count = Q_Count + 1
DIR = UP
ELSE ' Was 2 now 4 = Down
Q_Count = Q_Count - 1
DIR = DN
ENDIF
Case 128
If NewState = 64 THEN ' Was 4 now 2 = Up
Q_Count = Q_Count + 1
DIR = UP
ELSE ' Was 4 now 1 = Down
Q_Count = Q_Count - 1
DIR = DN
ENDIF
END SELECT
oldState = NewState
ENDIF
ENDIF
Or I wired the roller wrong ?
Here ( http://www.angelfire.com/nd/maza/kenwood.html ) it's a working variant, but in other "way" , using Atmega ...
-
Re: New approach to Rotary Encoder