PWM reading with DUE

I need to read PWM signal - it's duty cycle and frequency

I try to use code published on:
http://www.benripley.com/diy/arduino/three-ways-to-read-a-pwm-signal-with-arduino/

The pulseIn() Function gives me very inaccurate results, and when I try to use <PinChangeInt.h> library, it shows error:
No such file or directory #include <new.h>

Is there some easy solution?

This really isn't an installation and troubleshooting sort of question. . .

The Due isn't AVR- based, and the pin change interrupt library is AVR-specific.

I'm surprised pulseIn isn't working for you, but you didn't post any code or schematic or expectations, so help is hard to give

@aixam, your topic has been moved to a more suitable location on the forum. Installation and Troubleshooting is not for problems with your project :wink: See About the Installation & Troubleshooting category.

1 Like

I posted in installation and troubleshooting because of
"No such file or directory #include <new.h>" error.

good to know that there might be a problem with using pin change interrupt library on DUE

I connected my DUE to ESP32, which provides PWM 50% duty cycle at 5000Hz, so pulsein() should show 100, but it reads different values from 100 to 149 and I can't have such a big error.

@aixam If your pulsewidths aren't any shorter than a microsecond then here's a way to measure pulsewidth:

// Sketch to calculate pulsewidth from an input signal in microseconds

#define INPUT_PIN 10                      // Arduino input pin number

volatile unsigned long isrPulsewidth;     // Define Interrupt Service Routine (ISR) pulsewidth
unsigned long pulseWidth;                 // Define Pulsewidth variable

void setup() 
{
  pinMode(INPUT_PIN, INPUT);              // Set the input pin
  attachInterrupt(digitalPinToInterrupt(INPUT_PIN), calcPulsewidth, CHANGE);   // Run the calcPulsewidth function on signal CHANGE
}

void loop() 
{
  noInterrupts();                         // Turn off interrupts
  pulseWidth = isrPulsewidth;             // Copy the isr pulsewidth to the pulsewidth variable
  interrupts();                           // Turn on interrupts
  // Work with pulsewidth here ...
  // ...
}

void calcPulsewidth()                    // Interrupt Service Routine (ISR)
{
  static unsigned long pulseStartTime;   // Start time variable
  
  if (digitalRead(INPUT_PIN) == HIGH)    // If the change was a RISING edge
  {
    pulseStartTime = micros();           // Store the start time (in microseconds)
  }
  else                                   // If the change was a FALLING edge
  {        
    isrPulsewidth = micros() - pulseStartTime;    // Calculate the pulsewidth
  }
}

The period (frequency) could be measured by storing the time between pulses in a similar fashion.

A more sophisticated option is to use timer capture detailed here: https://forum.arduino.cc/t/due-timer-capture-mode-tc0-channel-1/441820/4.

That's a programming issue - the file couldn't be found because it doesn't exist as far as the Due is concerned.

I have not used ESP32, but my experience with ESP8266 shows that it generates PWM software, not hardware. When checking the signal with an oscilloscope, large deviations are observed.

Sweet bike, by the way. I'm a rider myself.

Hi there @aixam

With tc_lib (https://github.com/antodom/tc_lib) you can measure the period and duty of a digital signal (like a PWM signal) using the DUE.

in this post you have more information about tc_lib:

The measurements are stable and can get to frequencies greater than 20 Mhz.
I hope it helps.

1 Like