rotary encoder code problem

moosound

Member
Hi All,

I found this code on the forum, which works well, that interfaces a rotary encoder and counts and detects direction and outputs to a LCD.

I have found that it sends a dir=0 and dir = 2 for the detection,

question is, could i get it to output a pin high or pin low from this as well?

much help appreciated...I have tried but failed ..

Code:
;Forum Th 271011
#picaxe 18M2

symbol getBits = b0
symbol dir = b1
symbol counter = b3

setint %00000010,%00000010 ,C
main:
do
sertxd("Main loop - Counter=",#b3,13,10)
sertxd("Main loop - dir=",#b1,13,10) 'added to monitor random changes
pause 1000

loop

interrupt:
bit2 = pinC.2: bit1 = pinC.1 

getBits = getBits & %000000110
if getBits <> 0 then 
dir = bit2 * 2 'direction: if bit2=low then dir=0; if bit2=high then dir=2
counter = counter - 1 + dir 
do while getBits <> 0 

getBits = pinsC & %000000110

loop
endif
setint %00000010,%00000010 ,C
return
Pete
 
Last edited:

eclectic

Moderator
I added two LED/res, on B.3 and B.4

Added a few lines to the program (****)

Code:
;Forum Th 271011
#picaxe 18M2

 Let DirsB = %11111111 ; ************

symbol getBits = b0
symbol dir = b1
symbol counter = b3
setint %00000010,%00000010 ,C

main:
do
sertxd("Main loop - Counter=",#b3,13,10)
sertxd("Main loop - dir=",#b1,13,10) 'added to monitor random changes
pause 1000

 If DIR = 0 then  ;****************
 High B.3 : Low B.4
 else
 Low B.3 : High B.4
 endif            ;************

loop
interrupt:
bit2 = pinC.2: bit1 = pinC.1

getBits = getBits & %000000110
if getBits <> 0 then 
dir = bit2 * 2 'direction: if bit2=low then dir=0; if bit2=high then dir=2
counter = counter - 1 + dir 
do while getBits <> 0 
getBits = pinsC & %000000110
loop

endif
setint %00000010,%00000010 ,C
return
Not elegant I know, but you can experiment from there.

e
 

Armp

Senior Member
Thanks - I had previously tried 'b' on a 20M2 some time ago, and got the expected syntax error.
I was hoping I'd missed an upgrade!
 

moosound

Member
Hi Eclectic,

That worked!

I am getting confused between bits and bytes i think,

in the begining of the program it defines Dir as b0, which Is a byte.

So a bit later in the program it defines bit2 = c.2

and then later in the program it mentions dir = bit2 * 2

man it really is baking my noodle now,

so i was unsure what to call up to make my pin high,

I guess the first question is why are we defining dir = b1 ? this is a byte correct? but why?

Best
Pete
 

hippy

Ex-Staff (retired)
To understand the 'dir' variable you need to look at -

counter = counter - 1 + dir

That either adds 1 or subtracts 1 depending on 'dir' which is either 2 or 0.

There are a number of other ways to achieve the same adjustment of 'counter' based upon the value of 'bit2'. The hardware and code could be optimised for higher performance but no need if it performs as expected.
 

moosound

Member
To understand the 'dir' variable you need to look at -

counter = counter - 1 + dir

That either adds 1 or subtracts 1 depending on 'dir' which is either 2 or 0.

There are a number of other ways to achieve the same adjustment of 'counter' based upon the value of 'bit2'. The hardware and code could be optimised for higher performance but no need if it performs as expected.

Hi Hippy,

Ok I see, I'll read up on the counter function, it's weird to see the negative and positive either side of the 1...

I would love to see your enhancements to the code if poosible,

Best
Pete
 

hippy

Ex-Staff (retired)
Untested, and not sure if it's an improvement or not, but should technically be faster. Swap the two wires in to pin C.1 and pin C.2.

Code:
#picaxe 18M2

 Let DirsB = %11111111 ; ************

symbol getBits = b0
symbol counter = b3
setint %00000100,%00000100 ,C

main:
do
sertxd("Main loop - Counter=",#b3,13,10)
sertxd("Main loop - dir=",#bit1,13,10) 'added to monitor random changes
pause 1000

 If bit1 = 0 then  ;****************
 High B.3 : Low B.4
 else
 Low B.3 : High B.4
 endif            ;************

loop
interrupt:
getBits = pinsC & %000000110
if getBits <> 0 then 
  counter = getBits & 2 + counter - 1
  do  
  loop while pinC.2 <> 0 Or pinC.1 <> 0
endif
setint %00000100,%00000100 ,C
return
 

moosound

Member
Hi Hippy that works fine, I will test both and report back.

One thing though, I am getting a few syntaxes trying to simulate on a 40x2, what is it about the 40x2 that differs from the 18m2? I have read the manual, and that talks about 40x2 having extra memory and being faster, but i can not see any reference to having to use different code, what am I missing?

thanks
Pete

EDIT : I am being silly...using the 40x in the sim and not the 40x2...forget the above..
 

moosound

Member
OK, So both codes are working great in the real world, occasional miss read...

I am wondring what the pause of 1000 is there for though? I did change it to 10 and 10000 lengths but i did not notice any change in the way it works..be interested to know why it is there?

Pete
 

hippy

Ex-Staff (retired)
I'm not sure about the intent of the PAUSE 1000 other than to stop the code from repeatedly and frequently reporting 'no change' SERTXD. The misreads are likely a result of the SERTXD as while they are executing no interrupts will occur.

One of the problems with any high-speed counting method is that it's hard to do accurate counting and report the results of that without losing accuracy. It's like counting passing cars using a mechanical tally; as soon as you look down to read the count you'll be missing passing cars.

Change the two SERTXD to the following shorter and faster executing code and you'll likely get less misreads, and / or add a SETFREQ M32 and adjust the baud rate of Terminal and the PAUSE 1000 to PAUSE 8000...

SerTxd( #counter )
SerTxd( " " )
 

moosound

Member
OK, still geting a mis read, but only in one direction, so i reversed the wiring on the encoder and it flipped to the other direction....so perhaps its the encoder, Ill buy another more expensive type and see what happens..im sure the code is good, must be..

Now this might be out of scope of the technology, but could a picaxe detect the speed of the encoder? slow speed = high pin1, med speed = high pin2, fast speed = high pin3, some thing like that? would that be possible?
 

hippy

Ex-Staff (retired)
An error in one direction of counting could be a flaw in the counter detection code, waiting for both pins to be low rather than just the clock signal to go low.

It's probably possible to add speed control; running a timer between interrupts or a sequences of pauses and determining which one is interrupted. Starts to get a bit complex though.
 

moosound

Member
An error in one direction of counting could be a flaw in the counter detection code, waiting for both pins to be low rather than just the clock signal to go low.
Ok, I'll investiget this.

It's probably possible to add speed control; running a timer between interrupts or a sequences of pauses and determining which one is interrupted. Starts to get a bit complex though.
Ok, over night I have thought of another possible way to get round my issue, how about this, In the original code I think there was a counter that counted up in one direction and down in the other.

I assume it counts for every pulse from the encoder? If so, can I hserout instead for every pulse?

So the function would be for every pulse in one direction I would output hserout (midi hex data for FWD) and in the other direction I would output hserout (midi hex data for REW)

Thus when not the encoder is not moving I would not be outputting at all, which would be perfect.

Ill have an experiment now, but just thought I'd get the idea out there too see how best this might be done..

Pete

.
 

hippy

Ex-Staff (retired)
I assume it counts for every pulse from the encoder? If so, can I hserout instead for every pulse?
Yes and you could even simplify the code ...

Code:
#Picaxe 18M2

Symbol CLK = pinC.1
Symbol DAT = pinC.2

SetFreq M32
HSerSetup B31250_32,%000

Do
  Do : Loop While CLK = 0
  If DAT = 1 Then
    HSerOut 0,( ...FWD... )
  Else
    HSerOut 0,( ...REV... )
  End If
  Do : Loop While CLK = 1
Loop
 

moosound

Member
Hippy - I am yet again amazed, the simplicity of your code but soo effective...i could not work it out for a while but I slowly unpicked it and again is quite simply genious..

and! it will work on a 8m2 quite happily..

cool!
 
Top