PDA

View Full Version : [Question(s)] Keeping Track Of High Clickcount Encoders



ROBOTMAN
01-23-2011, 04:18 PM
I have been setting up code for the motor driver on my bot and ran in to an issue with high click per revolution encoders. I am using an arduino ATMEGA168 with interrupts on pin 2 and 3. The code simply increments the encoder value and prints it via the serial monitor. If the two encoders exceed one click per 25ms clicks start getting "dropped". Is there a way to prevent this? Also I will be running the wiring i2c library which uses software interrupts and PID control. I assume this means I will "drop" even more clicks?

If I run my motors at full power with 300 cpr there are 2,400 clicks per second! Around two per millisecond; would my main loop PID code even execute?

The only solutions I can think of is to lower the cpr to well under 100, or use two arduinos to gather the clicks and another to control the motors. Is there a better way?

lnxfergy
01-23-2011, 04:39 PM
Are you sending the count *every* time you receive a tick? Serial communications is *very* slow compared to the encoder counting + PID.

-Fergs

ROBOTMAN
01-23-2011, 06:10 PM
Slower than a pid loop? I will remove that and see how fast In go...

ROBOTMAN
01-23-2011, 06:58 PM
You where right! Without the Serial.println(); command it I could go as fast as 2 ticks per 1ms. Thanks!

I have one more sub question, can an interrupt interrupt an interrupt? I know that interrupts interrupt the main loop then return to control back to the line it was on, but what if interrupt is triggered during my lengthy i2c software interrupt? Most tutorials don't mention anything about this.

lnxfergy
01-23-2011, 07:11 PM
I have one more sub question, can an interrupt interrupt an interrupt? I know that interrupts interrupt the main loop then return to control back to the line it was on, but what if interrupt is triggered during my lengthy i2c software interrupt? Most tutorials don't mention anything about this.

Not by default on the AVR architecture. For that reason, you should keep your ISR (interrupt service routine, the function which is called when the interrupt triggers) as short as possible.

-Fergs

Xevel
01-23-2011, 07:20 PM
If I remember correctly, the default behavior is that when the mcu is in an interrupt, other interrupts will wait until this one is finished (I don't think it's true for all of them, read the ATMega doc for details).
But you can explicitly enable interrupt again in the interrupt handler by using sei() (SEt Interrupt).

A few years back I wrote a code similar to what you are doing now, and it's possible to get up to 20 coder ticks per ms, while still having the PID and more running in the background. When an I2C interruption would come up, I would immediately use sei() to let the encoders tick freely in the meantime.

EDIT: Seems I was a little confused, so I checked back my old code (http://svn.assembla.com/svn/XD_DSbot/tags/2009/Arduino/CarteMoteur/) ... I did not use sei() for the I2C interrupts, but only for the timer interrupts (that occurred every 5ms and computed odometry and PID). I don't remember the I2C interrupts blocking the external interrupts from happening...

Xevel
01-23-2011, 07:50 PM
Not on the AVR architecture. For that reason, you should keep your ISR (interrupt service routine, the function which is called when the interrupt triggers) as short as possible.

-Fergs

Sorry, but I am quite certain this is not the case (the impossibility, not the fact that you should keep your ISR as short as possible).
From p.14 of the atmega168 datasheet :


When an interrupt occurs, the Global Interrupt Enable I-bit is cleared and all interrupts are dis-
abled. The user software can write logic one to the I-bit to enable nested interrupts. All enabled
interrupts can then interrupt the current interrupt routine. The I-bit is automatically set when a
Return from Interrupt instruction – RETI – is executed.
The I-bit refered to here is set with sei(), and cleared with cli() when you don't want to mess yourself with registers and bitmasks.

lnxfergy
01-23-2011, 08:09 PM
Sorry, but I am quite certain this is not the case (the impossibility, not the fact that you should keep your ISR as short as possible).

I really meant to say "not by default".

-Fergs

ROBOTMAN
01-25-2011, 06:56 PM
Thanks, my code works brilliantly now. Ill have to check out that bit about nested interrupts it sounds like may be useful if I "up" the cpr.


I don't remember the I2C interrupts blocking the external interrupts from happening... Really? I use the arduino "wire" i2c library so I do not really know what is going on behind the scenes, but it appears to be necessary to use a software interrupt. I assume that would prevent external interrupts correct?

[EDIT]
Unless you used the code you recommended to re-enable them.

Xevel
01-26-2011, 04:21 AM
Really? I use the arduino "wire" i2c library so I do not really know what is going on behind the scenes, but it appears to be necessary to use a software interrupt. I assume that would prevent external interrupts correct?

[EDIT]
Unless you used the code you recommended to re-enable them.

I may be wrong on this. I can't remember if I checked it properly and it was some time ago...

ROBOTMAN
05-01-2011, 05:51 PM
In case anybody stumbles along this thread and wonders how many clicks per second the arduino can handle accurately I ran some test and its 128 clicks per millisecond. This was done using an arduino generating "clicks" aka high/low pulses into both hardware interrupt ports. If my math is right "unlikely :) " that is around 768,000 clicks per second.

Tommy_T
05-16-2011, 04:55 AM
http://usdigital.com/assets/general/LS7166.pdf


Tommy

jdolecki
05-18-2011, 05:56 AM
Scroll down and read the part about encoders

http://www.hessmer.org/blog/tag/arduino/

ROBOTMAN
05-21-2011, 07:07 PM
I think I will need board to take care of counting my encoders because the program is interrupted so much that I can't send valid pulses to my motor controller.

Thanks for the link I'll look into those boards.

ROBOTMAN
05-21-2011, 07:23 PM
Do you know anywhere where I could get a sample wiring diagram for those boards? I assume you have to do more than just connect the i2c line, power, and your encoders?