Let's Make Robots!

AVR Interrupt Question

Hi all, here is my dilema:

I am attempting to fashion my own rotary encoder to detect wheel rotation speeds.  My approach is to use a disc with a slotted pattern cut into it and a photo interrupter.

This is the photo interrupter I have on hand: http://www.sparkfun.com/datasheets/Components/GP1A57HRJ00F.pdf 

I am looking to measure the speed of 4 separate wheels.  Each wheel will have 1 disc, and 1 photo-interrupter (only using a single channel as direction is not important to me).  The photo-interrupters will be attached to an Arduino Mega. The way I am considering capturing the data is by simply attaching the "gate pins" (the ones that output the information) of each photo-interrupter to pins of my Arduino that support external interrupts.  I would then write some sort of interrupt service routine that would simply increment a counter each time the interrupt was triggered.  What I am curious is if this will take up too much CPU time and essentially deadlock my processor?

 Here is my reasoning (hope it is not flawed):

Assuming I went with say 32 notches on my disc and spun it at the max speed of 500 rpm (8.33 rev/s).  That would be ~267 pulses per wheel / second.  That would be 1068 pulses from all 4 motors / second.  That means 1068 ISRs would run every second.  

Assuming an add instruction works as follows: 

B+ C  ---> A   (where C = counter, B = 1, A = memory spot to store)

Fetch instruction (add) from memory address PC. 
Increment PC to address of next instruction. 
Decode the instruction and operands. 
Load the operands B and C from memory. 
Execute the add operation. 
Store the result into memory location A. 

That is 6 clock cycles for an add.  Assuming each time an ISR runs I am just adding to a counter.  6*1068 = 6400 clock cycles consumed every second.  This is out of a total 16,000,000 (16MHZ crystal on the Arduino Mega).  

Perhaps I am over simplifiying the time it would take to run the ISR (due to overhead of backing up registers before running the ISR, etc.) and the time it takes to run the ISR is say 100 cycles.  100 * 1068 = 106,800 cycles.  Out of a total 16 Million.  

In either case I wouldn't be close to locking up the CPU.   Does this make sense? 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

IMO, one timer interrupt is the better solution, than multiple pin change or external interrupts. I've been using this for the quadrature encoders for my Ardubot. In this case the timer interrupt runs at 1000Hz and the interrupt function needs 20µs without optimization (pure Arduino code).

 

Here is the code:

http://code.google.com/p/robotfreak/source/browse/trunk/ardubot/QadratureEncoder.cpp

Thanks RobotFreak,

 I took a look at your code, perhaps you can tell me if I am reading it correctly.  My understanding is your ISR is running at a constant rate, in which you read the values on each of your quadrature lines?

So I assume you simply take a rate that is faster than the max rate your quadratures are expected to turn at? 

It works exactly this way. On a timer interrupt every ms the input signals are readed. The counter will increase only on a pin level change. In case of using quadrature encoders, a state machine has been used to detect the square wave signals with a 90° phase. The timer frequency must be as high that each input level must be detected at least once (oversampling).

I see one problem with this solution: when the wheel stops between the low and high position the counter may grow, where the wheel is not turning. But I think you will have the same problem when using the pin change or external interrupt.

Maybe you should try both solutions and choose the best one.

 

Due to the integration of an ALU (Arithmetic Logic Unit) with the main processor, incrementing a byte in memory usually only takes 1 cycle in a modern microcontroller, and the ATmegas are no exception to this. As you have already surmised, much more time is spent performing tasks like saving the current state of working registers, program counter, etc.
What language are you programming your ATmega in? You can always break the ISR down into individual operations to figure out how long it'll take in more exact terms.

In any case, the ISR should be less than 100 cycles, unless your compiler takes a really unusual approach to implementing it.

I am programming in C, so not as easy to figure out the actual time without looking at the assembly code I suppose.  Either way it seems I should be safe against deadlocking the processor regardless.

 

Thanks for your input!