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, 2017 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.
    – user1245
    May 30, 2017 at 1:22

1 Answer 1


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
enum { rMask = 7 };  // index-mask of 3 bits
enum { aIn = A3 };   // analog input pin #
int reads[nReads];
byte rindex=0;

void loop() {
  int vhi, vlo, vdiff, r;
  r = reads[rindex] = analogRead(aIn); // Analog read takes about .1 ms
  vhi=0; vlo=1024;
  for (byte i=0; i<nReads; ++i) {
    if (r > vhi) vhi = r;
    if (r < vlo) vlo = r;
  rindex = (rindex+1) & rMask;
  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 };
  enum { aIn = A3 };   // analog input pin #
  int vhi=0, vlo=1024, r;
  for (byte i=0; i<nReads; ++i) {
    r = analogRead(aIn); // Analog read takes about .1 ms
    if (r > vhi) vhi = r;
    if (r < vlo) vlo = r;
  return vhi - vlo;

void loop() {
  int vdiff;
  if (readingIsNeededNow) {
    vdiff = getDiff();
    // do stuff with voltage difference
  // etc 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.