I have (2) different kinds of pressure transducers in my engine fleet that control engine throttles. I've recently found out that one of them is programmable; I can change the duty cycle with respect to air pressure. I want to make the transducers the same, as I am running engines in tandem with a single pneumatic throttle control valve.
I believe this tutorial I found will head me down the right road...
However, this only counts the "ON" time. I think I can use this and also program to count the total (ON and OFF) time, divide the ON time by the total time and have the duty cycle.
Is this easy enough, or is there a better way? It would be so much easier to do these tests in shop with an Arduino rather than having to hook up and "trial and error" in the field. Thanks.
I've copied the code exactly from the pulseIN example, but when I try to verify, it gives me an error - 'pulseIN' was not declared in this scope.
I have little to no programming experience. Is the pulseIN example I posted earlier missing something? Thanks.
Ok. Stumped again. Got my code to verify, but returns only zeros. I checked with multimeter, and I'm getting around 2.3 volts at pin 7. Is that too low for Arduino to recognize as high? Or, is the arithmetic function in my program screwed up? Thanks.
Code...
unsigned long time;
unsigned long duration;
int pin = 7;
in DutyCycle;
The time returned by micros keeps incrementing. The time returned by pulseIn is the time it takes the input pin to go HIGH.
If you are feeding a PWM signal into pin 7, you have no way of knowing where in the cycle you are measuring from.
| |___
Suppose your signal looks like this. When pulseIn is called, where along that wave form are you? All you know is how long it takes to get to next transition to HIGH.
Duration is an integer. Time is an integer, which is larger than duration. The result of the integer division will be 0. Multiplying that by 100 is not going to make it greater than 0.
What I am attempting to do is measure my ON time and divide it by the total time hence giving me the duty cycle of the transducer for that particular air pressure. I was expecting to get some fraction, which I multiplied by 100 just to put into percent, the normal duty cycle unit, not to try and make 0 bigger :). Evidently pulseIn is not what I need, so what function(s) do you suggest?
I'd be inclined to use two interrupts, one for the RISING edge, and one for the FALLING edge.
In each ISR, copy thisRisingTime to lastRisingTime (or the falling equivalents), and set thisRisingTime to micros().
Periodically, in loop, use the difference between rising times and the difference between the falling times to give you the duty cycle.
The duty cycle is not an integer, so the times, which are, (or, more accurately, the difference between the times) need to be cast to floats, divided, multiplied by 100.0 (not 100), and stored in a float.
The presumption behind the code you posted is that the pulseIn command is called precisely when the pin transitioned to LOW, so the time returned in durationHigh is actually the time that the pin was LOW (the names for the times are reversed, by the way).
But, there is no way of knowing how long the pin was already LOW when the first call is made, so the time that the function spends waiting for a transition doesn't tell us anything.
Perhaps three calls to pulseIn, waiting for a transition to HIGH that you throw away, then timing for the transition to LOW, which you keep, then timing for the next transition to HIGH, which you keep, would be useful.
Interesting problem so I had a look at the pulsIn() code
// wait for any previous pulse to end
while ((*portInputRegister(port) & bit) == stateMask)
if (numloops++ == maxloops)
return 0;
// wait for the pulse to start
while ((*portInputRegister(port) & bit) != stateMask)
if (numloops++ == maxloops)
return 0;
// wait for the pulse to stop
while ((*portInputRegister(port) & bit) == stateMask)
width++;
Looks like it handles the situation properly by waiting for the first edge before timing.
However
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
* or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds
* to 3 minutes in length, [glow]but must be called at least a few dozen microseconds
* before the start of the pulse[/glow]. */
So there is the chance of some race condition or though that would be rare (depending on the frequency of the pulses).
Maybe catching an edge with an interrupt so you know you're well "inside" a pulse, then calling pulseIn(). (As long as the pulses are > the interrupt latency)
I thought the pulseIn() command had been 'upgraded' to automatically not start counting time until it sees the the start of the transistion it is looking for, high or low?
Reference:
Reads a pulse (either HIGH or LOW) on a pin. For example, if value is HIGH, pulseIn() waits for the pin to go HIGH, starts timing, then waits for the pin to go LOW and stops timing. Returns the length of the pulse in microseconds. Gives up and returns 0 if no pulse starts within a specified time out.
Thanks. I would have never thought this would be this difficult. I get what the problem is, but the codes retrolefty or graynomad suggested would probably give info accurate enough. Remember, when I first started this thread I stated I was attempting to "sync" transducers...so if I can just get identical data, slightly "off" or not, between the transducers, it should still yield the same rpm's per psi. Thanks for all of your help, and you all have a merry xmas.