Welcome! Log In Create A New Profile

Advanced

Using a shaft (Rotary) encoder without interrupts

Posted by Joshua Merchant 
Using a shaft (Rotary) encoder without interrupts
August 30, 2008 07:29AM
I'm working on my motors right now, and it has come to my attention that my Arduino Diecimila (I have to look up the spelling on that every fricken time...) has only 2 pins (Arduino pins 2 and 3) that can be used for external interrupts (with the attachInterrupt() function).

All the rotary encoder firmware I have seen so far (the magnetic encoder and some other stuff on the blog) has the encoder's input read by calling attachInterrupt() and setting an interrupt function that increments/decrements the angular position whenever one of the two quadrature bits changes (apparently it only uses 1 interrupt pin, as the second bit can be read in the same interrupt to give a direction of rotation; I'm not sure if this is allows the same positional accuracy as, say, putting both on interrupt pins would, though). See the short firmware example under the Quatrature Output subheader here [www.reprap.org].

Anyway, the point is that an encoder would use at least one of the two interrupt pins on my Arduino, if I set it up this way. I need input from 4 encoders, though - the three axes and the extruder (I'd actually settle for just the 3 axes right now, however). That leaves me with -2 interrupt pins left, which might get me in a bit of trouble with, well, reality.

Would it be a terrible thing to just check the encoders in the loop() function instead of using interrupts? Has anyone tried this? Would I lose an extreme amount of precision?
I'm guessing I might have a buildup of inaccuracy over time, at worst, and a few missed pulses at best.
Re: Using a shaft (Rotary) encoder without interrupts
August 30, 2008 08:39AM
I process my extruder shaft encoder with a fast timer interrupt rather than using edge triggered interrupts. That allows me to debounce the signals as well. They were too noisy for edge triggering interrupts because of the close proximity to the GM3 which generates lots of RFI.

Code example here: [hydraraptor.blogspot.com]. Note that it has an infinite loop to detect if it is not scanning fast enough. You probably want a better error handler! It only happens on my extruder when the clutch slips.


[www.hydraraptor.blogspot.com]
Ru
Re: Using a shaft (Rotary) encoder without interrupts
August 30, 2008 03:02PM
It might be worth your whlie looking at adding extra hardware to handle all that stuff.

Is this There are plenty of servo drive projects out there, but they will add non-trivial amounts of expense, by the looks of things.

It seems to me that you might be able to do something cunning with a fairly small uC between the controller board and the motor driver board... have a device that takes step and direction inputs from the controller, quadrature inputs from the encoder and step and direction outputs to the driver. It could then keep an account of steps out to steps detected and either add extra steps or skip some steps when the two counters differ.

Course, you'd need to nail together a board for this, and grab a few attinies or something, and learn some assembler... but on the flip side you don't need to eat up any extra pins on the controller.

Or alternatively, experiment with doing encoder checking in the loop winking smiley Its free, and it might just work. It could give you *acceptable* accuracy, and you could avoid serious errors accumulating over time by returning axes to the endstops periodically. This might be inconvenient with a darwin z axis though.
Re: Using a shaft (Rotary) encoder without interrupts
August 30, 2008 05:00PM
Quote

and learn some assembler

You've got to be joking, nothing in RepRap needs assembler with MCU's designed this side of the millennium.


[www.hydraraptor.blogspot.com]
Ru
Re: Using a shaft (Rotary) encoder without interrupts
August 30, 2008 06:14PM
Quote

You've got to be joking, nothing in RepRap needs assembler with MCU's designed this side of the millennium.

But this isn't something in reprap; I was suggesting additional uCs. 8-pin ATtiny chips cost pennies, for example. To be fair, you could probably make something in C that would do the job, but there seems to be a handful of trivial examples like [www.helicron.net] that skip the whole compilation step winking smiley
Re: Using a shaft (Rotary) encoder without interrupts
August 30, 2008 06:26PM
Yes but you get tiny MSP430's that are sub $1 in volume that are a 16 bit 16 MIP risk CPU so you can do this sort of stuff entirely in C.

Why anybody bothers with 8 bit MCUs and assembler these days, when 32 bit are the same price, I don't know.


[www.hydraraptor.blogspot.com]
Ru
Re: Using a shaft (Rotary) encoder without interrupts
August 30, 2008 07:07PM
Quote

Why anybody bothers with 8 bit MCUs and assembler these days, when 32 bit are the same price, I don't know.

Heh, now you point that out, I don't know either. Those little TI chips look quite nice... I guess 'twice as big' and 'twice as expensive' aren't really quite so important at these sizes and prices smiling smiley
Re: Using a shaft (Rotary) encoder without interrupts
August 30, 2008 09:35PM
nophead Wrote:
-------------------------------------------------------
> I process my extruder shaft encoder with a fast
> timer interrupt rather than using edge triggered
> interrupts. That allows me to debounce the signals
> as well. They were too noisy for edge triggering
> interrupts because of the close proximity to the
> GM3 which generates lots of RFI.
>
> Code example here:
> [hydraraptor.blogspot.com].
> Note that it has an infinite loop to detect if it
> is not scanning fast enough. You probably want a
> better error handler! It only happens on my
> extruder when the clutch slips.


I looked over the code, and I must admit that I don't really understand it (being extremely inexperienced with Arduino development). How exactly do your interrupts work? What is a "timer interrupt" as you use it? How is the interrupt triggered, and how do you specify the function to be called?

I searched around for a while but I still couldn't quite understand the material.

I imagined I might be able to feed a PWM signal into one of the interrupt pins from one of the digital PWM pins, but this seems like a bit of a bad idea, and I'm not sure if I could change the frequency from the default 490Hz (as that seems pretty slow).
Re: Using a shaft (Rotary) encoder without interrupts
August 31, 2008 05:21AM
That's not Arduino code, I don't know anything about them, but all modern micro's have several timers than can be programmed to give regular interrupts. That is generally how you get things to be done in real time, e.g. stepping steppers at regular intervals. I.e. rather than have a polling loop that runs at indeterminate speed you have the same code called regularly from an interrupt.

The arduino should have a library function to set up a timer. If not you can always read the datasheet. It normally only takes half a dozen lines to initialise a timer and arrange the interrupt to call your routine but it is highly processor / compiler dependent.

My extruder controller actually uses the same interrupt to read the temperature, process the shaft encoder and generate the PWM for the motor. The interrupt runs at about 32KHz. The debounce looks to see the signals the same for three cycles so the maximum encoder rate it can keep up with is 10 Kpps. With an 816 step encoder that is about 700RPM, ten times faster than the GM3 can move, except when the clutch slips and it snaps backwards!

Another timer runs at the rate I want the shaft to move and just updates where it should be. The PWM value is then a function of the difference between where it is and where it should be.

The comms to the main controller also uses interrupts so the main program is just initialisation followed by an empty loop. For more complex comms protocols I put the comms code in the main loop and just do character I/O with interrupts.

I have attached my extruder code.


[www.hydraraptor.blogspot.com]
Attachments:
open | download - main.c (16.1 KB)
Re: Using a shaft (Rotary) encoder without interrupts
August 31, 2008 08:15AM
Interesting.

So, then, can anyone tell me or point to a tutorial that explains how to use the ATmega168's timers (http://www.atmel.com/dyn/resources/prod_documents/doc2545.pdf says it has 2 8 bit timers and 1 16 bit timer) to implement internal firmware interrupts to allow high frequency checking of encoders (well, obviously, I don't need a tutorial that includes the encoder checking part)?

I've been looking around and I just can't figure it out (I've been looking so much that the word "then" at the beginning of the previous paragraph no longer looks like an English word...).
Sorry, only registered users may post in this forum.

Click here to login