Reading a PWM Signal with varying pulse width and frequency

Hello,

i am not sure if this is right part of the forum.
Also, i do currently own the Arduino Uno from the starter kit. Not sure how much of a difference this makes.

Anyway, back to what i want to do. I want to read a PWM signal from a engine management to interpret the signals and do further stuff with it. So everything is 12v

I do have some details about the signal. Its frequency ranges from 1 Hz to 10 Hz and the high time is between 5ms and 100 ms and the low time is between 200ms and 750ms (all approximately).

I tried using the pulseln function, but i cant really get it to work. To clarify, the program itself works, but there is no useful data coming from it.

I also tried to find some information about varying frequency, but all i could find was information on how to write a varying frequency. I only need to read it, not write it.

Thank you in advance.

Lance

Welcome to the forum

How are you reducing the 12V down to 5V in order that the signal can be read ?

I don't see a program.

You can use pulseIn() to separately measure both the HIGH time and the LOW time. From the two results you can calculate the frequency and duty cycle.

If the incoming PWM signal is of type VVVF (variable voltage and variable frequency), the pulseIn() function might not be able to evaluate the signal's characteristics (ON time and OFF time).

I did not yet reduce the 12v to 5v. I was wondering if i get data without needing to go down to 5v , and apparently i do not get useful data. I was looking for whats the source, and came across that its a signal with varying frequency and pulse width and wasnt sure if the arduino can even read that signal. Especially since the 1-10Hz of the sensor is much lower than the standard configuration (which is around 500Hz).

Next question is, if i reduce the voltage to 5 v with resistors, doesnt that have an impact on the signal?

other than the voltage level itself, the waveform itself should remain fairly the same

1 Like

Is there a way to read this signal with an arduino?

For better understaning, i had the Arduino before i came up with the idea to read the signal from the car. If the Arduino cant read the signal, and i would need to buy something else, thats fine. I just figured, i already have the Arduino at hand, so i might try it with it.

the short answer is yes it can.

as to whether it would be possible to then working with the data (ie correctly interprete the data), that would need some evaluating.

Do you have the datasheet for the decoding the signal. probably would be insightful to all of us here! :wink:

No, i do not have the datasheet. That is part of the later problem.

Its basically a sensor which encodes how much oil is in the engine in the low time and what the oil temperature is in the high time. Deeper information is however i assume classified to the producer of the car.

I can however find out how much oil is in my engine by removing oil and looking what the sensor does at various stages of oil. With that information i can send information utilize the low time and letting the arduino tell me when my oil level is low.

Oil temperature is more tricky, but i should be able to access the oil temperature directly from the engine management software. By driving and heating up the oil i can then check what my high time is and cross reference that to what the oil temperature is of the engine software. Given enough data, i should be able to build a table which has a temperature value for every high value.
I also dont know how the sensor behaves, like if it is a linear increase or exponential. But i think that can be figured out with enough data.

More important right now is the low time as its easier to do, because i need essentially only two values (one oil low, one for oil full; set oil level light when low and only erase the light when oil level is full again), and i can do that without having to drive the car (which i currently cant).

We can start with never run a signal exceeding 5 volts into an Arduino UNO input pin, analog or digital. A dignal greater than 5.0 volts should be attenuated by using a voltage divider circuit.

Next, depending on actual wave shape yes, on and off time can be measured using the pulseIn() function. You may want to give this a read. You can as mentioned earlier look at the High and Low pulse in. Assing the two will give you the period and 1/period the frequency.

Ron

Feed the incoming PWM signal into this voltage divider: 4.7k-2.2k and then connect the tap point at the INT0-pin of UNO. Keep counting/displaying the number of falling edge interrupts over 200-sec in order to ascertain that the incoming signal is a fixed frequency signal and then we may proceed to measure the ON-time which will give proportional information about the oil level/temperature.

That’s an interesting encoding technique. What is the vehicle make and model?

Well, the engine is from a BMW E39 M5.

For more information regarding the sensor, have a look at this document: https://www.techtips.ie/Hella-Ireland/thermal-oil-level-sensor.pdf

Newer sensor can even send more information by sending e.g. 3 pulses in a given time frame where the first pulse is temperature, second is oil level and third is diagnostics for example.

I only found generic information on how this sensor works, not actual values. But as i said, i can compare the values to the actual oil level and temperature and then write something for myself. The engine is not in its original model, thats why i try finding a way with an arduino.

Thanks! I have owned an E30 and an E36 M3. I’m going to have to think about how to use this technique for something, just for fun.

Well, the engine is in a E30. If you are familiar with the E30, you know the Check Control which is for checking Oil level. But they had different sensor back then.

I also want to add Oil temperature like the E30 M3 (and all subsequent M3 and M5) had in the Instrument cluster.

Now, i could change the oil level sensor to one which the E30 understand and add an additional sensor for oil temp, but i thought, why not use the existing sensor which can do both and just convert the signal.

I guess shoehorning a V8 where an inline 4 went is not that difficult. It sounds like you have the right approach for converting the sensor. Enjoy!

int pin = 6;
unsigned long durationHigh;
unsigned long durationLow;

void setup() {
  Serial.begin(9600);
  pinMode(pin, INPUT);
}

void loop() {
  durationHigh = pulseIn(pin, HIGH);
  durationLow = pulseIn(pin, LOW);
  Serial.print("High: ");
  Serial.print(durationHigh);
  Serial.print(" Low: ");
  Serial.println(durationLow);
}

As some have asked for the code, this is the code i currently use. It should just show me the values. It does not however.

In fact it shows 0 for high and low when nothing is plugged in, however when i plug the cable from the starter set into it, then i suddenly have values, depending on how i hold the cable. Sometimes its still 0, sometimes its 10100 at high and 9700 for low, or 4000 high and 15000. Sometimes its quite constant, then shifhting to different values as i move my hand.

Thats currently confusing me the most. Why is there any input when its just me holding the cable?

Posting an accurate schematic diagram of your setup would help.

If you're having problems, use the gear you have to try to help debug your way out.

// Jumper pin 3 to pin 6
const byte pin = 6;

void setup() 
{
  Serial.begin(115200);
  pinMode(pin, INPUT);
  analogWrite (3, 64); // roughly 25% duty cycle 
}

void loop() 
{
  uint32_t  durationHigh = pulseIn(pin, HIGH);
  uint32_t  durationLow = pulseIn(pin, LOW);
  Serial.print("High: ");
  Serial.print(durationHigh);
  Serial.print(" Low: ");
  Serial.println(durationLow);
  delay (1000); // yes, delay is justified here
}