High Speed Counting for Angular Encoder

Hi,

I'm running a project that has an angular encoder to trigger an ignition system on an engine. Right now I'm programming the Arduino - Uno and I have an E6 encoder from USDigital which is a quadrature angular encoder that reads 1000Pulses per revolution, hooked up to the crankshaft of an engine turning between 1000-3000RPM. My project requires me to use high speed counters to read in the values of the encoder and then output a 5V trigger signal to the ignition system once a certain angle is reached (or pulse counts in encoder terms). Right now the most efficient way program I have come up with is as follows (using some snipets from other programs found online):

int val;
int encoder0PinA = 7;
int encoder0PinB = 8;
int encoderOut = 2;
int encoder0Pos=0;
int encoder0PinALast = LOW;
int n = LOW;

void setup() {
pinMode (encoder0PinA,INPUT);
pinMode (encoder0PinB,INPUT);
pinMode (encoderOut,OUTPUT);
}

void loop() {

n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)) {
encoder0Pos++;
if(encoder0Pos==600){
digitalWrite(encoderOut,HIGH);
delay(100);
digitalWrite(encoderOut,LOW);
}
}
encoder0PinALast = n;
}

As of now, the program is too slow, I need it to be faster and I dont know how.. I've checked out this forum chat (http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1283882774/all) which is apparently "read-only" but any help or clarification for things like how to digitalReadFast?? (doesnt work on my program) or port manipulation would be greatly appreciated.

Thanks<

1000 pulses * 3000 rpm = 50KHz pulse. You're going to need interrupts for that, and even then it might not work well.

See the bottom of this for how to use interrupts with an encoder.

Do you need to read every pulse? What's the resolution that you actually require?

Could you use a down counter with zero count output feeding in to the Arduino to trigger an interrupt? Chips like the 74LS192/3 allow you to preload a count, count-down, and signal the Arduino when the count hits zero. You could, for example, use a couple of shift registers to hold the count up/count down value (programming a bank of shift registers through one pair of pins for data/clock), encode the counter with another pin, and have a fourth pin set as an input to receive the interrupt when the predetermined count is reached. The carry/borrow output could also be used to reload the counter with the value preset in the shift register.

Use the micro controller as a process controller, not a central processor ]:smiley:

delay(100); might cause problems at 50 Khz

definitely go for the interrupt. check the blink without delay example how to work without delays

It other topic someone using Timer1 library for counting .
http://arduino.cc/forum/index.php/topic,69810.0/topicseen.html

Is there a way to drive one of the atmega's timers using an external clock source? Maybe hook this into that, and set the timer so it generates an interrupt every X pulses (say 250 pulses, for 1/4 rotation or whatever) and then your interrupt service routine will reset the timer back to 250 and fire off the ignition.
I guess that's the same as the 74LS192/3 idea but without extra HW. Can't remember which ATmega chip can do it but I remember seeing it in a datasheet once.

Aeturnalus:
1000 pulses * 3000 rpm = 50KHz pulse. You're going to need interrupts for that, and even then it might not work well.

See the bottom of this for how to use interrupts with an encoder.

Thanks for the quick response. I have looked at using the interrupts based on your recommendation and that of ManicDee.. I tried the programs you referred me to without any success. What I've decided to do is purchase a 64CPR (counts per revolution) and 200CPR optical disk for my encoder this way I lower the amount of pulses per revolution. The accuracy i need for triggering the ignition system is around +-1degree (so the 200CPR should cut it, if not i have the 64CPR).

If I understand correctly the interrupts will "pause" the program and execute whatever is in the interrupt (like pulse counting). The problem with this is that the interrupt may stop the program just before the trigger execution occurs. Is there any way to read in the pulses simultaneously to outputting the trigger this way no pulses are missed during trigger events? Is it best to use some kind of external hardware that can record then send it to the arduino?

(as you can probably tell, my electronics background and programming background is not vast, so any advice and direction will be greatly appreciated).

robtillaart:
delay(100); might cause problems at 50 Khz

definitely go for the interrupt. check the blink without delay example how to work without delays

My fault, the delay is actually "delay(2)" since I only need a 2ms trigger. Plus read my post above, I have gone with less CPR. I will look into working without delays as well, thanks for the input.

ATTN: ManicDee

ManicDee:
One option is to use an external counter and latch. The incoming pulses are counted by the counter, the Timer1 interrupt simply sets a flag telling the loop to print the value, latches the value, copies the value from the latch to memory, unlocks the latch and leaves the counter to run.

In the loop, use the previous value of the "latched count" to determine how many more events have occurred. Print that number out at your leisure.

I read this on another discussion that you posted, how can I do this? can you give me an example of an external counter that I could implement thats fast enough for my application?