# How can I convert an irregular PWM signal with a duty cycle of 95 to 99% to an analog signal?

For the purpose of measuring particulate matter (PM) in air, I am trying to set up a DAC system for the PM sensor Shinyei PPD42NJ (info here and datasheet here).

I've been trying to just use a low pass filter to get an analog voltage, but I'm not sure how to calculate the appropriate capacitance and resistance. Concern: if I use the low pass filter, will past measurements affect the current measurements (unless the capacitor can be reset every time the voltage is sampled)? How often would I sample the voltage if the frequency of the LOW pulses are sometimes as low as .5 Hz?

The parameters of the PWM are Negative Logic, Digital output,Hi : over 4.0V(Rev.2) Lo : under 0.7V. Here is a picture with Channel 1 showing the usual behavior of the signal versus time.

• I wonder if Benjamin really wants an Analog output or not. If he does, the best filter is a switched integrator using the method I outlined. The voltage increases and never sags until the result is read and reset to 0. A sagging RC filter is like a leaky bucket counting rainfall. ( just a metaphor ) If you need a schematic for a simple switched integrate & dump, just ask. Someone can find, or pls indicate you prefer the PIC solution. Jul 11, 2012 at 20:28
• @Benjamin Weia << I wonder if Benjamin is still thinking about this question? Jul 18, 2012 at 23:53
• You want to sample at least twice the highest frequency of the signal to prevent aliasing: See Nyquist-Shannon Theorem. Jun 27, 2014 at 13:23

Although one could use a simple RC filter, I think one would do better to use some sort of digital filtering. The time scales you're looking at look well within the range of what a processor could handle. I would suggest that your best bet is probably to do something like sample the input pin once per millisecond and keep track of how many times the input has been low during each somewhat longer time interval (maybe one second or five seconds), and then use a digital FIR filter to add up those readings. A simple way to perform the filter FIR filter is to scale up each reading so as to be a bit short of the full range of a 16- or 32-bit integer, and then do something like (pseudo-code):

temp = new_reading
for each item in an array
new_temp = (temp + array_item)/2
array_item = temp
temp = new_temp
loop


The final value of new_temp will represent a low-pass filtered value of the input; one can vary the number of seconds per reading and the length of the array to adjust the filter characteristics. Note that if one uses e.g. a sampling interval of two seconds and an array that's 16 elements long, only the last 32 seconds of input will be considered in producing the output (meaning that the output will fully respond to any change in input conditions within 32 seconds) but relatively "stable" input conditions will yield a relatively stable output (much more stable than with an RC filter that converges reasonably fast).

If pulses count, but amplitude and duration don't, then you can trigger a monostable multivibrator with them. Then you can change to measuring time which is reasonably easy to accomplish with a counter (in a microcontroller) in contrast to measuring very short spikes through a low pass filter.

• each pulse is variable width & rate to integrate (count) total particles, according to chart. Jul 10, 2012 at 21:53

Looking at the data sheet, the "unit time" is 30 seconds.

I'm not sure why, without further details, you want to convert this to an analog signal only to then sample it again.

However, if you're committed to converting this to an analog signal, you'll need a filter with a very long time constant of the order of the "unit time".

Another option would be to integrate the signal with an op-amp integrator circuit that is sampled and reset every 30 seconds. This sounds like what you have in mind when you ask about memory of previous "measurements".

If you'll provide some more context, I can be more specific with my answer.

By the way, have you looked at this? The author interfaces this sensor to an Arduino.

• Looks like a good solution with cubic (3) coefficients to compensate for curve + offset. Cheap and Dirty solution ( no pun intended) Jul 10, 2012 at 22:06

To know what value of capacitor and resistor you want, you will need to think about the response speed you need to achieve. Looking at the waveform, it looks like you get a pulse every few seconds, and the pulses last tens of milliseconds. This is pretty slow, so:

• The analog signal will be much slower than your pulse rate. You should expect the analog signal to take about a minute to settle when the pulse rate changes.
• You will need to choose pretty large values of resistor and capacitor. The time constant of an RC filter in seconds is the product of the resistance in Ohms and the capacitance in Farads.

Since you're looking for something in the order of a minute, I'd start with 12k ohms, and 4700uF. See how that works. If you need a slower response, then use a larger resistor.

Here's what it looks like with 12k and 4700uF: There are 0.1s pulses every 2 seconds over the course of 2 minutes. As you can see, it hasn't really settled, even after two minutes, and the variation in the analog signal is still about 5%.

With a smaller resistor, you can have faster settling time, but more variation.

With a larger resistor, you can have slower settling time, but less variation.

I don't know if this is an option, but have you considered using a microcontroller to read these signals? What will be reading the analog voltage? If it was going to be an ADC and a microcontroller, I would forget about the ADC, and just let the MCU take care of it. These pulses are so slow that even a computer made out of cog wheels could reliably sample them.

• Digital > Analog Converter = DAC , visa versa = ADC Jul 10, 2012 at 21:51
• Oh yeah. Slow brain day for some reason. Jul 10, 2012 at 21:55