# Reading pulse train with DC offset

One of the analog inputs to Arduino is a pulse train with DC something like 1.5V to 3.9V pulse. This of course changes by time and Im only interested in the difference voltage (peak-to-valley). Like I want Arduino to measure (3.9V-1.5V) in the loop. I can use two analog inputs if there's no other way.

How to code this kind of measurement? Does anybody have experience with this?

duty cycle is 50% freq 3.3kHz.

• Please edit your question (click the edit button) to include some waveform and performance specs – how long the voltage stays high or low; required accuracy; what you want to measure. A solution that works if the input is audio frequency might not be adequate to handle RF inputs. Regarding what you want to measure, do you want to know the frequency, or risetimes, or pulse lengths, or voltages, or what? May 30 '17 at 0:59
• just an incoming pulse train to ADC with duty cycle is 50% freq 3.3kHz. with dc offset. i even gave an example in my question about what i need. i want to roughly measure peak to valley voltage of this type of pulse. May 30 '17 at 1:22

The proper method to use depends in part on what the data is for, and on what other processing your loop needs to do. The following example assumes there is nothing to do except compute the difference between the highest and lowest readings from among the most recent 8.

``````enum { nReads = 8 }; // # of readings = 2**3
byte rindex=0;

void loop() {
int vhi, vlo, vdiff, r;
vhi=0; vlo=1024;
for (byte i=0; i<nReads; ++i) {
if (r > vhi) vhi = r;
if (r < vlo) vlo = r;
}
vdiff = vhi - vlo;
//
// In this section, scale or use or report vdiff
//   ...
}
``````

An analog read takes about 104 μs. That, plus any time taken to scale, use, or report `vdiff`, will be the major determinant of how rapidly `loop()` runs, because the `for` loop that calculates `vhi` and `vlo` should take less than 10 or 15 μs.

For example, if `loop()` takes 125 μs per pass, the code will get about one reading per half cycle of input. (3.3 KHz is 303 μs per full cycle.) This will produce a steady precession of where the analog readings are taken within the input waveform's cycle. If that phenomenon is undesirable, you may need to use interrupt-triggered ADC reads.

If you don't need new differences as frequently as the above code produces them, you could instead on demand take several readings in a row and produce a result. For example:

``````int getDiff() {
enum { nReads = 6 };
int vhi=0, vlo=1024, r;
for (byte i=0; i<nReads; ++i) {
if (r > vhi) vhi = r;
if (r < vlo) vlo = r;
}
return vhi - vlo;
}

void loop() {
int vdiff;