[Howto] Software PWM simulation for all GPIO output pins

Post Reply
ivandavidov
Posts: 13
Joined: Fri Dec 02, 2016 8:36 am
languages_spoken: english
ODROIDs: C2
Has thanked: 0
Been thanked: 2 times
Contact:

[Howto] Software PWM simulation for all GPIO output pins

Post by ivandavidov »

I own C2 device and this device has official hardware PWM support for only two of the GPIO pins. Perhaps there is similar limitation on other HardKernel devices.

But what if you need to use PWM on 3 or more pins? Typical use case would be a RGB LED where you want to control the R, G and B channels independently. Therefore you need 3 pins with PWM capabilities.

Since the C2 device has support for only 2 PWM pins, I came up with software solution which simulates PWM via Bash script which utilizes the gpio (wiringPi) command.

Here is the whole script:

Code: Select all

#!/bin/bash

if [ "$1" = "" ] ; then
  cat << CEOF

  Usage: $0 pin duty

  pin   - Physical pin
  duty  - Duty cycle in 10% steps. Valid values are 1 through 9.
          Values 0 and 10 correspond to digital write 0 and 1,
          eg 'gpio -1 write 7 0' and 'gpio -1 write 7 1'.

  Examples:

  $0 7 2
  This will send PWM signal from physical pin #7 with 20% duty.

  $0 7 8
  This will send PWM signal from physical pin #7 with 80% duty.

CEOF
  exit 1
fi

pin=$1
up=$2
down=$((10 - $2))

trap ctrl_c INT

function ctrl_c() {
  gpio -1 write $pin 0
  echo
  exit 0
}

gpio -1 mode $pin out

while true;
do
  gpio -1 write $pin 1
  sleep 0.00$up

  gpio -1 write $pin 0
  sleep 0.00$down
done
The script uses physical pin notation, i.e. pin numbers are from 1 to 40. You can exit the script with Ctrl + C. You can put the script in background by placing & in the end of the command like this:

Code: Select all

./pwm.sh 7 4 &
And then you can exit the script either by invoking pkill pwm or by using the fg command, followed by Ctrl + C.

Pros:

* You can simulate PWM on every output pin.

Cons:

* The duty step is 10% and it is not guaranteed. You can try to modify the sleep intervals to improve the duty step.
* The theoretical pulse frequency is 0.1Khz (100 times per second) and it is not guaranteed. You can try to modify the sleep intervals to improve the duty step.
* The PWM simulation has negative impact on the CPU. I get high CPU load and flickering LED (instead of stable) when I use the script on 2 or more different pins.

You should be able to get better performance if you use the same approach to simulate PWM with another wiringPi wrapper different than gpio, perhaps via Python or directly via C.

Let me know if you find this useful and/or if you run into any trouble.
These users thanked the author ivandavidov for the post (total 2):
mad_ady (Thu Oct 31, 2019 2:52 am) • rooted (Sat Nov 02, 2019 3:57 pm)

mad_ady
Posts: 8466
Joined: Wed Jul 15, 2015 5:00 pm
languages_spoken: english
ODROIDs: XU4, C1+, C2, C4, N1, N2, H2, Go, Go Advance
Location: Bucharest, Romania
Has thanked: 578 times
Been thanked: 461 times
Contact:

Re: [Howto] Software PWM simulation for all GPIO output pins

Post by mad_ady »

Thanks for posting. I'm trying to use a custom PWM with your script in order to control the brightness of my VU7. With your script I get terrible flickering, so it's switching too slowly.
I will try to access it through wiringpi and see if I can improve the switching speed and get less flickering.

User avatar
rooted
Posts: 7985
Joined: Fri Dec 19, 2014 9:12 am
languages_spoken: english
Location: Gulf of Mexico, US
Has thanked: 724 times
Been thanked: 243 times
Contact:

Re: [Howto] Software PWM simulation for all GPIO output pins

Post by rooted »

mad_ady wrote:Thanks for posting. I'm trying to use a custom PWM with your script in order to control the brightness of my VU7. With your script I get terrible flickering, so it's switching too slowly.
I will try to access it through wiringpi and see if I can improve the switching speed and get less flickering.
If you figure it out I would like to learn how.

mad_ady
Posts: 8466
Joined: Wed Jul 15, 2015 5:00 pm
languages_spoken: english
ODROIDs: XU4, C1+, C2, C4, N1, N2, H2, Go, Go Advance
Location: Bucharest, Romania
Has thanked: 578 times
Been thanked: 461 times
Contact:

Re: [Howto] Software PWM simulation for all GPIO output pins

Post by mad_ady »

Ok, here is the wiringpi python implementation:

Code: Select all

#!/usr/bin/python3
import odroid_wiringpi as wpi               
                                                                     
                                                                      
# Prerequisites:                                                           
# * wiringPi: http://odroid.com/dokuwiki/doku.php?id=en:c1_tinkering#python_example
                                                                    
#initialize wiringPi                        
wpi.wiringPiSetup()                                                                 
                                                                                           
pwmPin = 7 #GPIO 249 on Odroid C2, Pin 7
brightness = 70 #percent

#set as output pin 
wpi.pinMode(pwmPin, 1)

wpi.softPwmCreate(pwmPin,0,100) # Setup PWM using Pin, Initial Value and Range parameters
while True:
    wpi.softPwmWrite(pwmPin,brightness) # Change PWM duty cycle
It works better than the GPIO implementation, but I still get the occasional flicker every couple of seconds (CPU is clocked at 1.8GHz). When the system is idle I get 100% CPU usage on one core (which is too much for me). When I run a stress test on the CPU the flickering worsens considerably.

Here is a video with the VU7 with 70% brightness using the sh script (sysfs implementation) in the first post:
https://www.youtube.com/watch?v=ZmV6pd2Q6UY

Here is a video with the VU7 with 70% brightness using wiringpi. Using C wouldn't likely improve things since wiringpi-python calls a C method in the background.
https://www.youtube.com/watch?v=f3kpna50RGU

Time for plan C - which is more complicated. As far as I know the odroid_lirc module uses the kernel to generate (and modulate) a 38KHz pulse on any GPIO. So it's software-based, but in kernel space. Now, an IR code is short and I want continuous pulses, but maybe there is a way to modify the module to generate a PWM signal from the kernel (where odds are the signal is more stable). Though it would still consume CPU, it wouldn't show up in htop because it's a kernel process...
This looks promising too: https://github.com/sarfata/pi-blaster/ and it seems it's hooked into a different PWM or PCM source, but not sure if it's PI specific...
These users thanked the author mad_ady for the post:
rooted (Mon Nov 04, 2019 7:01 pm)

User avatar
rooted
Posts: 7985
Joined: Fri Dec 19, 2014 9:12 am
languages_spoken: english
Location: Gulf of Mexico, US
Has thanked: 724 times
Been thanked: 243 times
Contact:

Re: [Howto] Software PWM simulation for all GPIO output pins

Post by rooted »

The wiringpi implementation is much better, I'm guessing with a bit more speed the flicker would be so small it would be invisible.

Good work.

mad_ady
Posts: 8466
Joined: Wed Jul 15, 2015 5:00 pm
languages_spoken: english
ODROIDs: XU4, C1+, C2, C4, N1, N2, H2, Go, Go Advance
Location: Bucharest, Romania
Has thanked: 578 times
Been thanked: 461 times
Contact:

Re: [Howto] Software PWM simulation for all GPIO output pins

Post by mad_ady »

It's not the speed that's missing, it's the unreliability caused by the software scheduler that may pause the program and keep the screen off for too long. I ran it with nice with higher priority, but didn't see much improvement. Anyway, I'm against having programs use up 100% CPU, so I need to find something else.

User avatar
rooted
Posts: 7985
Joined: Fri Dec 19, 2014 9:12 am
languages_spoken: english
Location: Gulf of Mexico, US
Has thanked: 724 times
Been thanked: 243 times
Contact:

Re: [Howto] Software PWM simulation for all GPIO output pins

Post by rooted »

mad_ady wrote:It's not the speed that's missing, it's the unreliability caused by the software scheduler that may pause the program and keep the screen off for too long. I ran it with nice with higher priority, but didn't see much improvement. Anyway, I'm against having programs use up 100% CPU, so I need to find something else.
Is using a microcontroller out of the question?

mad_ady
Posts: 8466
Joined: Wed Jul 15, 2015 5:00 pm
languages_spoken: english
ODROIDs: XU4, C1+, C2, C4, N1, N2, H2, Go, Go Advance
Location: Bucharest, Romania
Has thanked: 578 times
Been thanked: 461 times
Contact:

Re: [Howto] Software PWM simulation for all GPIO output pins

Post by mad_ady »

No, that's plan F for FUUU... :D

User avatar
joerg
Posts: 1152
Joined: Tue Apr 01, 2014 2:14 am
languages_spoken: german, english, español
ODROIDs: C1, C1+, C2, N1, N2, C4
Location: Germany
Has thanked: 55 times
Been thanked: 128 times
Contact:

Re: [Howto] Software PWM simulation for all GPIO output pins

Post by joerg »

@mad_ady: I'am using this adafruit PCA9685 breakout board to control my living room led lights from home assistant via i2c. Maybe this is a way you can go? Some clones you can get for less than 10€.
IMG_20191104_140144.jpg
IMG_20191104_140144.jpg (452.83 KiB) Viewed 2751 times

mad_ady
Posts: 8466
Joined: Wed Jul 15, 2015 5:00 pm
languages_spoken: english
ODROIDs: XU4, C1+, C2, C4, N1, N2, H2, Go, Go Advance
Location: Bucharest, Romania
Has thanked: 578 times
Been thanked: 461 times
Contact:

Re: [Howto] Software PWM simulation for all GPIO output pins

Post by mad_ady »

Well, ideally I'd like to do it without external hardware. I mean, I still have pins left unused :D
Plan D is to see if any of the RTC pins could be used as hardware pwm - maybe pins 3 or 5? https://wiki.odroid.com/accessory/displ ... c_pin_info
Plan E is to solder a wire to the pwm0 pin. That way I control both screens with one pin.

User avatar
odroid
Site Admin
Posts: 35314
Joined: Fri Feb 22, 2013 11:14 pm
languages_spoken: English, Korean, Japanese
ODROIDs: ODROID
Has thanked: 1090 times
Been thanked: 826 times
Contact:

Re: [Howto] Software PWM simulation for all GPIO output pins

Post by odroid »

"Plan E" is much more feasible.
These users thanked the author odroid for the post:
mad_ady (Tue Nov 05, 2019 2:02 pm)

Post Reply

Return to “Ubuntu (All Linux'es)”

Who is online

Users browsing this forum: No registered users and 1 guest