i have a general question regarding a project. I have a rotary encoder on a crankshaft to measure engine speed with 3600 increments per revolution. At 750 rpm that comes down to a pulsed signal at 45 kHz. For the device "further down the line" this fequency is too high, so I want to process the encoders signal in a way that only every third (or fourth) pulse is taken and put through. I plan to work on this with an Arduino Uno but I am unsure about the feasibility. I can handle the code but my electronics knowledge is not the best so wonder if I'm overlooking something hardware-wise.
is the Arduino Uno a working choice for this solution? Is this solution reasonable in general?
If it is exactly 1-in-N pulses, then a simple counter (as suggested by @jim-p) will be all that's needed. Divisions other than 2,4,8 should also be possible using other chips.
But if the ratio isn't exactly 1-in-N, then an Arduino might be the easiest way. For example it might need to be 3.15-in-7 or some such.
The UNO processor has an external input for Timer1. You can use this, with appropriate setup to divide the external signal by an integer amount and trigger an interrupt on a compare match.
Thanks for the suggestion. No I wouldn't work on electrics that will be crucial on the road, It's for a stationary engine and research reasons. I have a high-speed camera that recording the combustion in an engine. The camera needs a trigger signal, so I can assign each frame to a discrete crankshaft angle. The cam only takes signals for that up to 20kHz-ish.
Sounds much simpler. In fact I'd like to divide the signal by 3 which makes this IC not plug and play if I saw that correctly. But I will look further into that. Thanks!
Sorry, I misunderstood your requirements.
So you want the option to be able to divide by three or divide by four, correct?
The title says "every other pulse" so do you also want to divide by two?
I do not see anywhere you relate to an angle, because there is no angle without knowing the other side of the angle. Where is the stationary point your count begins from, for each crank position? Is there a missing tooth on a gear or some such indicator?
As a first step it's helpful already if the crank angle difference between to images is fixed. With this it's possible to claim that between each frame is a difference of 0.3° crank angle. But you're right, to "fix" it in a way, that I can say "this picture was taken at 392.3°" I need to apply a second signal. I already have a 5V square pulse at my ignition TDC that comes out of my control unit as well as my camera trigger of course. Which means I can relate everything to that. I didn't figure out yet on how exactly tho - the problem described here was a first step.
I got it to work with my Arduino and noticed a delay in the signal. Out of interest I wanted to see how this behaves on another board (Elegoo 2560) and noticed a slightly different delay. For anyone interested I attached two measurements (First one Uno, second one Elegoo). It's no biggie tho and the solution with the Uno will be sufficient. I'd be interested in an explanation tho, since I am by no means an expert on electronics/arduino stuff.
As soon as I have time for it, I will apply the solution by gilshultz with a flipflop since this is probably faster and less overkill than an entire board just for a little signal conditioning.
Sure my bad. I used the following code for both boards. I'm aware that delays within an interrupt are probably a bad idea but I don't know how to do it better...
The resetCounter is not yet used, so you can ignore that part.
#include <Arduino.h>
// Define the input and output Pin
const int inputPin = 2;
const int outputPin = 13;
const int startPin = 18;
volatile int pulseCount = 0;
void setup() {
pinMode(inputPin, INPUT);
pinMode(outputPin, OUTPUT);
pinMode(startPin, INPUT);
digitalWrite(outputPin, LOW);
sei();
// interrupt to the input pin
attachInterrupt(digitalPinToInterrupt(inputPin), handlePulse, RISING);
attachInterrupt(digitalPinToInterrupt(startPin), resetCounter, RISING);
}
void loop() {
// everything is handled by the interrupt
//digitalWrite(outputPin, HIGH);
//delay(1);
//digitalWrite(outputPin, LOW);
//delay(1);
}
void handlePulse() {
pulseCount++;
if (pulseCount >= 3) {
pulseCount = 0;
digitalWrite(outputPin, HIGH);
delayMicroseconds(2);
digitalWrite(outputPin, LOW);
delayMicroseconds(2);
}
}
void resetCounter() {
pulseCount = 0;
}
Not a native speaker. By "every other pulse" I meant that I'm looking for a solution where I can change the division and I am looking for a general solution - three or four are the most likely case since it's my personal setup. But I imagine that other people will be relying oin it too.
I will try your proposal with a counter IC too tho. Taking the opportunity to learn working with datasheets (again)
You can get away with a few microseconds, although it's not necessary to have delay in your ISR to put out this waveform.
The delay between the Arduino output and the input waveform is likely simply due to the high-level code overhead. The Arduino/C++ instructions aren't very atomic if you look at how they work out in machine code.
You could get better performance by using more low-level coding.