Hello world
I'm working on a project wish consists of designing a system that manages the injection of a diesel engine
I'm working on a arduino uno board and my aim for now is to detect the signal from the camshaft wish is responsible of telling the system the stroke of the first cylinder. This signal is a square wave. It contains three single pulses and one double pulse, and I need to detect only the double pulse. You can see the from of the sensor signal in the attached file. The code that I wrote for that doesn't work and I need your help to do that. You can find the code bellow.
Any help is very much appreciated.
thank you all in advance.
int clk=0;
int oldclk=0;
int i=0;
const int redled = 3;
const int greenled = 4;
unsigned long lastTimeReading = 0;
void setup()
{
// put your setup code here, to run once:
pinMode (7, INPUT);
pinMode (redled, OUTPUT);
pinMode (greenled, OUTPUT);
}
void loop()
{
// put your main code here, to run repeatedly:
lastTimeReading = millis();
clk=digitalRead (7);
while (((millis()-lastTimeReading) < 4)&& (i < 3))
{
if ((oldclk == LOW) && (clk == HIGH))
{
i++;
}
if (i==2) digitalWrite (greenled, HIGH);
else digitalWrite(greenled, LOW);
oldclk=clk;
}
lastTimeReading = millis();
}
What is the difference between two pulses and a double pulse? In other words: how do you know it's one of the three pulses or the first pulse of the double pulse, out of a total of five pulses?
Hi,
OPs image;
What is the yellow signal
How many cylinder diesel?
2 stroke or 4 stroke?
So the start of, or the end of, the double pulses indicates Cylinder 1, TopDeadCentre?
If the engine is 4 cylinder then from your blue trace the last of the pair will represent No1 Cyl TDC.
What is the amplitude of the pulses?
Your biggest problem is the fact that the pulse width and intervals will not be constant , but change with speed.
For that issue I based my algorithm on timing, that's where the function millis() is for. It's correct that a double pulse is actually two pulses, but the time laps between them is shorter than the others. You can find in the code that I detect the rising edge in a precise periode of time (based on the original signal of the sensor) and a counter to count if within this particular periode of time there's two edges, if so I set a pin, otherwise it's closed.
TomGeorge:
Hi,
OPs image;
What is the yellow signal
How many cylinder diesel?
2 stroke or 4 stroke?
So the start of, or the end of, the double pulses indicates Cylinder 1, TopDeadCentre?
If the engine is 4 cylinder then from your blue trace the last of the pair will represent No1 Cyl TDC.
What is the amplitude of the pulses?
Your biggest problem is the fact that the pulse width and intervals will not be constant , but change with speed.
Tom...
The yellow signal is the output (if the double pulse is detected i set a pin).
It is a 4 stroke 4 cylinder engine (cylinder one has 2 teeth of the camshaft disk and 2,3 and 4 have only one tooth). Based on that if the system detects a double pulse, I know that the cylinder1 is in compression stroke.
Yes you got the point TomGeorge, it is related to the speed of the engine. But for now I based my program on one speed.
Looking at it, the way to detect a double pulse APPEARS to be that the interval between the pulses is shorter than the length of the pulse itself. Furthermore, the second of the double pulse appears to be the data point you're looking for (that one looks like it's pretty much in sync with the other three pulses).
So that would make detection of the double pulse quite straightforward: record the length of the pulse, and if the next pulse comes within that time span that is the pulse you're looking for. So upon startup of the sketch it looks for the double pulse, and then it can just count, ignoring every fifth pulse (the "pre-pulse" for the double one) for timing, maybe using that to confirm no pulses were missed in the process.
wvmarle:
How does your scope image change as the speed of the motor changes?
For now I'm not changing the speed. But even with that I see that I'm independent with the pulse width, because I'm detecting the rising edge not the state. But to answer your question as the speed increases the pulses are getting closer, and the pulse width shorter.
Gon_FREEKS:
The code that I wrote for that doesn't work and I need your help to do that.
You need to tell us what the program actually does and what you want it to do that is different.
Would it matter if you missed the very first occurrence of the double pulse when the engine starts?
I presume you are aware that you can only identify a double pulse after the two have happened.
Your diagram shows 3 single pulses between every double pulse - can that pattern be relied on? If so I would detect double pulse, then start counting single pulses, and then the first pulse after the 3rd pulse will be the first of the next pair of double pulses. Reset the count when every double pulse is detected.
If this was my project I would use a RISING interrupt to detect each pulse and I would measure the time using micros() for greater accuracy.
Gon_FREEKS:
as the speed increases the pulses are getting closer, and the pulse width shorter.
That's great, it means that you can rely on ratios between pulse length and time to detect the double pulse, rather than absolute numbers.
I would consider using two interrupts: a RISING and a FALLING - or even simply a CHANGE followed by detection of what happened - as you need to know both the pulse length and the time between the two pulses, this for the double pulse detection.
This way, if you detect a rising edge, and the time since the last falling is less than say two times the duration of the previous pulse, you instantly know you have the second pulse of the double pulse, regardless of the actual number.
As this is a motor, fastest speed would be something like 10,000 rpm or 700 pulses per second, that's about 1.4 ms between pulses. Definitely requires micros() timing as each pulse would last some 100-200 µs based on that scope image.
Robin2:
You need to tell us what the program actually does and what you want it to do that is different.
I actually did say that my aim is to control the injection of a 4 stroke diesel engine and for now I want to know the position of cylinder 1. This information can be red from the camshaft sensor.
Robin2:
Would it matter if you missed the very first occurrence of the double pulse when the engine starts?
No it doesn't matter.
Robin2:
Your diagram shows 3 single pulses between every double pulse - can that pattern be relied on?
Yes it can be, because it is a periodic signal, double pulse corresponds to cylinder 1, than, based on the injection cycle (1,3,4,2) every pulse corresponds to one teeth of the cylinders 3, 4 and 2.
wvmarle:
I would consider using two interrupts: a RISING and a FALLING - or even simply a CHANGE followed by detection of what happened - as you need to know both the pulse length and the time between the two pulses, this for the double pulse detection.
I red some examples on how to use RISING and FALLING interrupts and I could understand some of their applications. I could figure out that those interrupts help me detect the change of the state of the input, but I couldn't find how to enter the timing issue. Could you please write some code in order to make your point clearer?
thank you.
How fast are your eyes? Can you really see an LED that blinks for 1 ms? Do a Serial.print() or so instead (for testing only as you're bound to start missing pulses due to the slow Serial). Or at least connect your scope to the output pin, as that way you can make the signal visible much easier.
Also for testing I'd make sure I at least detect the interrupts - so have your interrupts do a digitalWrite() on an OUTPUT and see if you see the exact same pattern on your scope for both the input and the output signals.
How is everything connected? Grounds connected? What is the actual voltage coming out of that sensor?
How fast are your eyes? Can you really see an LED that blinks for 1 ms? Do a Serial.print() or so instead (for testing only as you're bound to start missing pulses due to the slow Serial). Or at least connect your scope to the output pin, as that way you can make the signal visible much easier.
My observations were not obviously based on seeing an LED blinking for 1ms. I used an oscilloscope on PROTEUS platforme. the blue line is the input signal and the output is the yellow one.
the sensor's signal is generated with another arduino, so it's 0 to 5V. you can see screenshots bellow.
I suggest you only detect the rising interrupt and record the value of micros(). Calculate the time since the previous interrupt. If the time is very much shorter (say less than a quarter) of the previous interval then you have the double pulse. Something like this
if (newPulse == true) {
prevPulseMicros = latestPulseMicros; // save the last value
noInterrupts();
latestPulseMicros = isrPulseMicros;
newPulse = false;
interrupts();
pulseCount ++;
latestIntervalMicros = latestPulseMicros - prevPulseMicros;
if (latestIntervalMicros < prevIntervalMicros / 4) {
// we have the double pulse
pulseCount = 0;
// do whatever needs to be done
}
prevIntervalMicros = latestIntervalMicros;
}
Just looking in more detail at your code, this is an issue:
attachInterrupt (0, risingISR, RISING);
It seems you have your signal connected to pin 0, one of the Serial pins. OK as you don't use Serial in this case. Still it's a pin that's best used last. Worse, the external interrupts (RISING, FALLING) are only available on pins 2 and 3. That's another problem. More details here.
As interrupt numbers and pin numbers are not related, you have to use the digitalPinToInterrupt(pin) function, and you get this: