I'e seen a lot of examples of simple PWM on the Pi where relatively high-precision PWM signals at a fixed duty cycle can be generated using WiringPi or pigpio in hardware PWM mode. I have tried implementing something similar but need to update the duty cycle at a fixed sample period Ts. The idea is to basically hack together a DAC using the PWM output and a one-pole RC to have a signal generator capable of emulating signals recorded from a much larger set up. The bandwidth is pretty low, so I'm trying for an effective sample rate of 200 Hz (update the PWM duty cycle every 5 ms).

I'm using pigpio in hardwarePWM mode with Python3 on GPIO 18 and have tried using time.sleep() and time.perf_counter() to get the delays but it's clear that between the Python interpreter and Linux scheduler the drift accumulates significantly within just a few seconds of signal playback.

Next step will be to try doing it in C instead of Python, but I was wondering if anyone had any input on how to potentially do this with more reliable inter-sample spacing (ie, microsecond levels of drift per "sample" update instead of ms).

One other solution that came to mind is converting the entire signal to a train of square waves first (basically call a function first to re-produce the entire "PWM signal" that would be getting written to the GPIO lines on each sample update and then just outputting that as serial data, if the clock is more reliable this way). Can also always just buy a cheap DAC but was hoping to be able to throw this together in code to keep footprint down, especially since the sample rate is pretty low. Thanks for any insight

  • 1
    dac is not precise enough, try a cheapy pwm controller module. – tlfong01 Apr 10 '20 at 3:07
  • Thanks @joan, I'm putting something together with this now. I just finished testing a version of the code using pigpio in C that used gpioDelay for the inter-sample pauses but was still ending up with ~200 ms of accumulated drift for a 7.5 second signal. I will follow up if I have any questions or issues – a ortiz Apr 10 '20 at 21:36
  • I can't quite figure out how to update the samples at a fixed interval from these examples without following the block in wavePWM that uses time.sleep() (I've already tried using and had too much timing error with). The servo part seems closer but am unsure how to adapt it. Ideally the PWM frequency is fixed around 20kHz and the program is just changing the duty cycle every 5 ms. Is there a way to build a buffer of waves at dc[0] for Ts, then add to that buffer dc[1] pulses for Ts, etc using these wave functions where there are no calls to the less reliable time.sleep waits? – a ortiz Apr 10 '20 at 22:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.