What sort of frequencies are you talking about?
pigpio can do this with waves (hardware timing).
E.g. http://abyz.me.uk/rpi/pigpio/examples.html#Python_wavePWM_py
My new lg library can do this using software timed PWM.
E.g. Python http://abyz.me.uk/lg/py_lgpio.html#tx_pwm
pigpio example using pigs (command line)
G1=12
G2=13
OFFSET=500
B1=$((1<<$G1))
B2=$((1<<$G2))
pigs m $G1 w
pigs m $G2 w
pigs wvag $B1 $B2 $OFFSET $B2 $B1 $OFFSET
pigs wvcre
pigs wvtxr 0
lgpio C example (local GPIO)
#include <stdio.h>
#include <stdlib.h>
#include <lgpio.h>
/*
gcc -o lt1 lt1.c -llgpio
./lt1
*/
#define G1 12
#define G2 13
#define FREQ 1000
#define DUTY 50
#define ON_MICS (int)(1e6 / FREQ * DUTY / 100.0)
#define LFLAGS 0
int main(int argc, char *argv[])
{
int h;
h = lgGpiochipOpen(0);
if (h < 0)
{
printf("gpiochip open failed\n");
exit(-1);
}
if (lgGpioClaimOutput(h, LFLAGS, G1, 0) != LG_OKAY)
{
printf("gpio claim output failed\n");
exit(-1);
}
if (lgGpioClaimOutput(h, LFLAGS, G2, 0) != LG_OKAY)
{
printf("gpio claim output failed\n");
exit(-1);
}
lgTxPwm(h, G1, FREQ, DUTY, 0, 0);
lgTxPwm(h, G2, FREQ, DUTY, ON_MICS, 0);
lguSleep(30);
lgGpiochipClose(h);
}
rgpio C example (local and remote GPIO)
#include <stdio.h>
#include <stdlib.h>
#include <lgpio.h>
#include <rgpio.h>
/*
gcc -o rt1 rt1.c -lrgpio
./rt1
*/
#define G1 12
#define G2 13
#define FREQ 1000
#define DUTY 50
#define ON_MICS (int)(1e6 / FREQ * DUTY / 100.0)
#define LFLAGS 0
int main(int argc, char *argv[])
{
int sbc;
int h;
sbc = rgpiod_start(NULL, NULL);
if (sbc < 0)
{
printf("connection failed\n");
exit(-1);
}
h = gpiochip_open(sbc, 0);
if (h < 0)
{
printf("gpiochip open failed\n");
exit(-1);
}
if (gpio_claim_output(sbc, h, LFLAGS, G1, 0) != LG_OKAY)
{
printf("gpio claim output failed\n");
exit(-1);
}
if (gpio_claim_output(sbc, h, LFLAGS, G2, 0) != LG_OKAY)
{
printf("gpio claim output failed\n");
exit(-1);
}
tx_pwm(sbc, h, G1, FREQ, DUTY, 0, 0);
tx_pwm(sbc, h, G2, FREQ, DUTY, ON_MICS, 0);
lgu_sleep(30);
gpiochip_close(sbc, h);
rgpiod_stop(sbc);
}
lgpio Python module (local GPIO)
import time
import lgpio as sbc
G1=12
G2=13
FREQ=1000
DUTY=50
ON_MICS = int(1e6 / FREQ * DUTY / 100.0)
h = sbc.gpiochip_open(0) # Pi's main gpiochip
sbc.gpio_claim_output(h, G1) # claim G1 of gpiochip
sbc.gpio_claim_output(h, G2) # claim G2 of gpiochip
sbc.tx_pwm(h, G1, FREQ, DUTY)
sbc.tx_pwm(h, G2, FREQ, DUTY, pulse_offset=ON_MICS)
time.sleep(30)
rgpio Python module (local and remote GPIO)
import time
import rgpio
G1=12
G2=13
FREQ=1000
DUTY=50
ON_MICS = int(1e6 / FREQ * DUTY / 100.0)
sbc = rgpio.sbc()
if not sbc.connected:
exit()
h = sbc.gpiochip_open(0) # Pi's main gpiochip
sbc.gpio_claim_output(h, G1) # claim G1 of gpiochip
sbc.gpio_claim_output(h, G2) # claim G2 of gpiochip
sbc.tx_pwm(h, G1, FREQ, DUTY)
sbc.tx_pwm(h, G2, FREQ, DUTY, pulse_offset=ON_MICS)
time.sleep(30)
Simplest method just sets one GPIO to active low.
import time
import lgpio as sbc
G1=12
G2=13
FREQ=1000
DUTY=50
h = sbc.gpiochip_open(0) # Pi's main gpiochip
sbc.gpio_claim_output(h, G1) # claim G1 of gpiochip
sbc.gpio_claim_output(h, G2, lFlags=sbc.SET_ACTIVE_LOW) # claim G2 of gpiochip
sbc.tx_pwm(h, G1, FREQ, DUTY)
sbc.tx_pwm(h, G2, FREQ, DUTY)
time.sleep(30)