Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 06:30 29 Nov 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Micromite Feature Request Rotary Encoder

     Page 1 of 2    
Author Message
atmega8

Guru

Joined: 19/11/2013
Location: Germany
Posts: 722
Posted: 10:42pm 02 Mar 2014
Copy link to clipboard 
Print this post

Hello,

first again 1000 thanks to Geoff and everyone who helps.

Micromite is nearly perfect but what i really miss is the support for rotary encorders.
They are so helpfull and elegant for input tasks, making menues an so on.
Also they are cheap an for everyone available.
I think ( Hope) the support off this devices will use a small amount of memory.

In germany there is a very popular microcontroller Forum, and there are many guy's with lots of knowledge arround. One of them is Peter Dannegger, who also made some encoder routines which work bullet proof.

Here IS a link to the german forum, where Peter provides some stable c code whith english comments.
I think it is really easy, for people like Geoff, to translate this to the PIC controllers.

What do you think?

http://www.mikrocontroller.net/articles/Drehgeber


DS
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9308
Posted: 10:48pm 02 Mar 2014
Copy link to clipboard 
Print this post

Depending on what is involved in talking to one of these things, could you not write a sub or function to talk to it from within MMBasic?

Not sure I understand the complexities of rotary encoders though - can you link me to some examples, so I can study how they work?
Smoke makes things work. When the smoke gets out, it stops!
 
MOBI
Guru

Joined: 02/12/2012
Location: Australia
Posts: 819
Posted: 11:08pm 02 Mar 2014
Copy link to clipboard 
Print this post

  grogster said  Not sure I understand the complexities of rotary encoders though - can you link me to some examples, so I can study how they work?


They are a pretty simple device to drive. They consist of two switches and use a simple 2 bit code table. There should be plenty of info on the net on the workings of. Essentially, they give a rotating code sequence that indicates whether the sequence is going forward or backward.

I could send you some MCU code, but it is all in PIC 8 bit assembly.

If anyone is interested, I have a i2c driven RE module.
David M.
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 11:51pm 02 Mar 2014
Copy link to clipboard 
Print this post

I think the difficulty is not programming it in C but to make those values available in MMBasic and within the space available.

How would you like to use it from basic?

In a loop and then querying the current value?
In that case, what are the minimum, maximum and start values, etc...

Get an interrupt with each step?
That would be my favorite, an interrupt for each up and down step.

Any other ways of using it from basic?

Microblocks. Build with logic.
 
MOBI
Guru

Joined: 02/12/2012
Location: Australia
Posts: 819
Posted: 11:54pm 02 Mar 2014
Copy link to clipboard 
Print this post

Here is some data I dug up years ago

rotary encoder

This is the second go at trying to post. The net is so slow tonight that I could crawl faster.

@TZA - interrupt is the safer way. If the encoder is included in a dedicated firmware loop, then you can pretty well get away with testing for bit pattern and sequence.

Usually set up a counter variable and increment/decrement it.Edited by MOBI 2014-03-04
David M.
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3196
Posted: 12:37am 03 Mar 2014
Copy link to clipboard 
Print this post

Sounds like a good idea. I will investigate.
Geoff Graham - http://geoffg.net
 
atmega8

Guru

Joined: 19/11/2013
Location: Germany
Posts: 722
Posted: 03:50am 03 Mar 2014
Copy link to clipboard 
Print this post

@ Grogster:
google IS also your friend;-)...

To all:

The most reliable method is not interrupt driven.
It is based on cyclic checking the encoder state, where the cycle time something about 10 ms.
In The Main routine you can then Check a variable if it incrased or decreased and based on this the encoder could be read.
Some encoders also differ in the mechanical construction, but this can be mastered in the code.
The cycle time should be adjustabel to get reliable readings ( System variable?).

The encoders have also a push button, could be used like an " enter" function.

The Code from Peter dannegger to wich i linked Works very well an stable to all encoders i have tested ( Panasonic, Albs, etc.)
It is c code for Atmegas, but i think Geoff will convert it in minutes ;-)...

Picaxe, Arduino, bascom, Luna AVR, all support rotary encoders.

Mmbasic should also support ;-).

Geoff will make it work;-)
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 05:03am 03 Mar 2014
Copy link to clipboard 
Print this post

Well, i would put the A on an interrupt enabled pin, and on every interrupt i would read the state of B.
The B will tell the direction (Up or Down). Update a variable accordingly.
This will not use a timer (Peter Dannegger's code does), so that the timer can be used for other purposes like setticks ,PWM and Servos.



Microblocks. Build with logic.
 
atmega8

Guru

Joined: 19/11/2013
Location: Germany
Posts: 722
Posted: 05:24am 03 Mar 2014
Copy link to clipboard 
Print this post

  TZAdvantage said   Well, i would put the A on an interrupt enabled pin, and on every interrupt i would read the state of B.
The B will tell the direction (Up or Down). Update a variable accordingly.
This will not use a timer (Peter Dannegger's code does), so that the timer can be used for other purposes like setticks ,PWM and Servos.




Is this " speaking knowledge" or do you have deeper experience with encoders?

You should test it yourself.
Looking forward what you will tell then;-)

 
robert.rozee
Guru

Joined: 31/12/2012
Location: New Zealand
Posts: 2350
Posted: 05:37am 03 Mar 2014
Copy link to clipboard 
Print this post

the code to run a rotary encoder is pretty simple. as noted, it has a 2-bit output. one merely needs to keep track of the previous state, and for each of the possible states (after a state change): one previous state indicates anti-clockwise rotation, another indicates clockwise rotation, and the third is an invalid combination.

the following bit of code should more-or-less do the trick:


encoder = 0
last = 0
SETPIN 2, INTB, rotary
SETPIN 3, INTB, rotary

...

:rotary
next = (PIN(2) * 2) + PIN 3
IF ((last+next) AND 1) = 1 THEN ' two-step change is an error
IF ((next-last)=1) OR ((last-next)=3) THEN encoder = encoder + 1
IF ((last-next)=1) OR ((next-last)=3) THEN encoder = encoder - 1
ENDIF
last = next
IRETURN


would have been much cleaner to write if MMbasic had a MOD function!

rob :-)Edited by robert.rozee 2014-03-04
 
atmega8

Guru

Joined: 19/11/2013
Location: Germany
Posts: 722
Posted: 06:40am 03 Mar 2014
Copy link to clipboard 
Print this post

Robert,

this code will work in theory and not with all type of encoders.
There is no debounce and if you rotate to fast or to slow it will loose counts.
If the encoder contacts are not in neutral Position it will bounce like hell.
There are lots of encoders ( Panasonic for example) where in " neutral" positionthe contacts are connected. This must be eleminated via software.
Encoders/Software which counts don't follow the "haptic" are disappointing and you like to throw it in The Basket....;-), try it, test it...
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 07:06am 03 Mar 2014
Copy link to clipboard 
Print this post

It is knowledge from the 'old days' where i had to keep track of position on servo motors.
Without interrupts it is impossible, and even with interrupts it had its limits.

For slower and hand operated encoders you also do not need to process all 4 steps of the Gray encoding.

[code]
_____ _____ _____
A | | | | | |
______| |_____| |_____| |__

1 2 3 4 1 2 3 4 1 2 3 4
_____ _____ _____
B | | | | | |
____| |_____| |_____| |_____

[/code]
There are four distinct times, each is a change of a logic level on either line A or B.

Lets imagine you are turning the encoder clockwise.
You then go from left to right through the steps 1-2-3-4-1-2-3-4 etc.
The A line goes from '0' to '1' on step 2.
If you sample the B line at moment '2' you see that it is always '1'

Now imagine going the other way, turning counter clockwise or going from right to left. The steps are now 4-3-2-1-4-3-2-1 etc.
The A line goes from '0' to '1' on step 4.
If you sample the B line at moment '4' you see that it is always '0'

So, what you do is setup a low to high interrupt on the pin connected to A.
And depending on the value on the pin connected to B you increase or decrease the value.

I do not have a uMite available at the moment so this is without testing
[code]
RotaryValue = 0
SETPIN 2, INTH, RotaryInterrupt

...
'do other usefull stuff
...

SUB RotaryInterrupt
IF PIN(3) = 1 then
RotaryValue = RotaryValue + 1
ELSE
RotaryValue = RotaryValue - 1
ENDIF
' Even shorter but is only faster when done in C
' RotaryValue += (ReadPin(3)<<1) - 1;
END SUB

[/code]

For this to work you need to debounce a mechanical rotary encoder, a small cap will be sufficient.
You can also do it in software by measuring the time between interrupts. If it is shorter then a certain amount then ignore the interrupt. I prefer the small cap.Edited by TZAdvantage 2014-03-04
Microblocks. Build with logic.
 
robert.rozee
Guru

Joined: 31/12/2012
Location: New Zealand
Posts: 2350
Posted: 07:22am 03 Mar 2014
Copy link to clipboard 
Print this post

"not in neutral Position": not quite sure what you mean there. in the past this has worked passably with 3-wire encoders.

the line "IF ((last+next) AND 1) = 1 THEN..." filters out the 50% of possible states that are invalid, while the occasional back-stepping error will likely have little impact in real-world situations. one can add small caps to the input pins if desperately worried about this, but in applications where one might have a volume control (for example) with 30 or so steps the occasional glitch in a single step is unimportant.
 
CircuitGizmos

Guru

Joined: 08/09/2011
Location: United States
Posts: 1425
Posted: 07:49am 03 Mar 2014
Copy link to clipboard 
Print this post

I would guess that the implementation would be good for rotary encoders turned by human. Will it be fast enough for motor position feedback? (Not insanely high RPM, but faster than volume control knobs.)
Micromites and Maximites! - Beginning Maximite
 
robert.rozee
Guru

Joined: 31/12/2012
Location: New Zealand
Posts: 2350
Posted: 08:59am 03 Mar 2014
Copy link to clipboard 
Print this post

  CircuitGizmos said   I would guess that the implementation would be good for rotary encoders turned by human. Will it be fast enough for motor position feedback? (Not insanely high RPM, but faster than volume control knobs.)


given no upper speed limit, no software solution could be guaranteed to be fast enough. if dealing with a fast-turning shaft, a better approach would perhaps be to count complete revolutions, sensing the direction off whatever is driving it round. or count pulses away from an end-stop if the direction if fixed. or having the shaft drive a linear measurement device (ie, if moving the head of a lathe). or monitor the drive into the stepper motor rotating the shaft (if that is how it is driven).

but then, what non-specialist applications exist that require this? the rotary encoders the average hobbyist deal with are attached to a human-driven knob.
 
jwettroth

Regular Member

Joined: 02/08/2011
Location: United States
Posts: 71
Posted: 09:35am 03 Mar 2014
Copy link to clipboard 
Print this post

I have a lot of experience with these little buggers. I designed the Digital Readout for the Sherline Mill and Lathe DRO that has sold a bunch over about 15 years. It was originally designed to be used by hand but wss robust enough to keep up with CNC setups with no changes. It is coded in assembly on a 12 MHz (1 mips) 8051 and simultaneously keeps track of three encoders, continuously displays them and corrects for backlash and never drops a count. It also reads out spindle speed simultaneously.

The best way to implement this code is to have a fast timer tick (.1 ms), do a debounce pass and a then a state transtion pass to inc and dec counts. Keep the tick irq very fast and bail out quickly if nothng intersting is going on, set a flag on changes- That's it. If you look at a fast rotation speed for a CNC- perhaps a 60" per minute rapid, with a 10 turn per inch thread-, this is only 600 RPM or 10 rev/sec. With an encoder with 100 states per turn, this is about 1000 edges on the AB inputs. You'd have to go a minimum of twice this fast without debounce. 100 uS is 10x this fast.
Another point- Fancy/Fast debounce and very fast inputs are generally mutually exclusive. Fast inputs will usually use optical type encoders that don't bounce. The little mechanical encoders only have about 32 ticks/revoluion and are very forgiving on debounce.

I agree that it would be a nice background function to have on Micromite if Geoff can squeeze it in.. There are a lot of people that want to make DRO's if nothing else.
John Wettroth
 
CircuitGizmos

Guru

Joined: 08/09/2011
Location: United States
Posts: 1425
Posted: 11:01am 03 Mar 2014
Copy link to clipboard 
Print this post

  robert.rozee said  
but then, what non-specialist applications exist that require this? the rotary encoders the average hobbyist deal with are attached to a human-driven knob.


Robotics.
Micromites and Maximites! - Beginning Maximite
 
atmega8

Guru

Joined: 19/11/2013
Location: Germany
Posts: 722
Posted: 11:24am 03 Mar 2014
Copy link to clipboard 
Print this post

  CircuitGizmos said  
  robert.rozee said  
but then, what non-specialist applications exist that require this? the rotary encoders the average hobbyist deal with are attached to a human-driven knob.


Robotics.


I also think that the main use case is a human-driven encoder as an input device for menues, setting values for variables and so on.

Give it a chance Geoff;-)
 
mbramwel

Regular Member

Joined: 10/07/2013
Location: Canada
Posts: 42
Posted: 12:01pm 03 Mar 2014
Copy link to clipboard 
Print this post

Do your encoders use natural binary or graycode binary?

With 2-bits, natural binary gives us the following sequence: 00,01,10,11
With gray codes, only 1-bit changes from state to state giving us: 00,01,11,10

With gray codes, you can wrap the code around 10 becomes 00
whereas natural binary has both bits changing from time to time.

With gray codes, if the current read differs more than 1-bit from the previous read, you missed a step or have a bad reading.
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3196
Posted: 12:30pm 03 Mar 2014
Copy link to clipboard 
Print this post

  robert.rozee said  would have been much cleaner to write if MMbasic had a MOD function

It does, it is called the MOD operator! You use it the same as the multiply or divide operators.

I was going to implement the function using 1 mSec polling (the fastest that can be conveniently used) and that would restrict it to less than 500 steps/sec as John pointed out. Also, I was not planning to implement contact debounce as a bounce translates into one step back plus one step forward (ie, neutral).

BUT Rob's code written in MMBasic is so elegant and simple that I am now wondering if I should bother adding this to the language in the first place.

I don't have much practical experience with these devices so all comments will help.

GeoffEdited by Geoffg 2014-03-04
Geoff Graham - http://geoffg.net
 
     Page 1 of 2    
Print this page
© JAQ Software 2024