2

I am building a pure sine wave dc/ac inverter and looking at the possibility of using the Rpi to control the h-bridge. I need a sinusoidal encoded pwm signal at around 20kHz. So the pulses would change in width acording to a sine function and loop every 20ms. Does anybody know if this can be done? I have used pigpio to generate pwm before but I am not familiar enough with the program to know if this is possible.

  • How many steps do you need between PWM off and PWM fully on? At a 2 µs sample rate pigpio has 25 steps at 20 kHz, would that be enough? Is this a repeating waveform, i.e. is it repeated every 20 ms or will the next 20 ms waveform be potentially different to the previous one? – joan Mar 4 '15 at 21:06
  • Hi Joan. Yes 25 different pulse widths could be enough but the more the better, can hardware pwm be used for something like this? Yes the encoded waveform will repeat every 20 ms. I've got a picture of what I need to control the h-bridge. [IMG]i59.tinypic.com/2a6vyx0.png[/IMG] – James Mar 4 '15 at 21:38
  • I've reduced the pwm frequency to 1kHz for the picture. – James Mar 4 '15 at 21:41
  • It's still a little overkill to use a RPi for that task? – Ghanima Mar 4 '15 at 22:12
1

This is my interpretation of what you want.

20kHz is a pulse every 50 µs. In 20 ms there will be 400 pulses.

I've assumed a sin wave going from zero to maximum back to zero over the 400 pulses. The duty cycle varies from 0 to 50 back to 0 in that cycle.

I'm using waveforms to generate the PWM. It's the most accurate way for such varying signals.

#!/usr/bin/env python

# inverter.py
# 2015-03-04
# Public Domain

import sys
import time
import math

import pigpio

RUNTIME=30

HERTZ=20000
PERIOD=20000 # microseconds

GPIO=4

if len(sys.argv) > 1:
   hertz = int(sys.argv[1])
else:
   hertz = HERTZ

if len(sys.argv) > 2:
   period = int(sys.argv[2])
else:
   period = PERIOD

if len(sys.argv) > 3:
   runtime = int(sys.argv[3])
else:
   runtime = RUNTIME

pulse_width = 1000000 / hertz
steps = period / pulse_width

print("pw={} steps={}".format(pulse_width, steps))

wf = []

for s in range(steps):
   angle = (s * math.pi) / steps
   duty_cycle = int((math.sin(angle) * pulse_width) + 0.5)

   print("s={} dc={}".format(s, duty_cycle))

   off_time = pulse_width - duty_cycle

   if duty_cycle:
      wf.append(pigpio.pulse(1<<GPIO, 0, duty_cycle)) # switch on

   if off_time:
      wf.append(pigpio.pulse(0, 1<<GPIO, off_time)) # switch off

pi = pigpio.pi() # Connect to local Pi.


pi.set_mode(GPIO, pigpio.OUTPUT)

pi.wave_clear()
pi.wave_add_generic(wf)
wid = pi.wave_create()

if wid >= 0:
   pi.wave_send_repeat(wid)
   time.sleep(runtime)
   pi.wave_tx_stop()
   pi.wave_delete(wid)

pi.stop()

Inverter pulses repeated every 20 ms Inverter pulses repeated every 20 ms

Detail of inverter pulses Detail of inverter pulses

  • Nice answer and details! +1 – Piotr Kula May 4 '15 at 21:21

Your Answer

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

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