Software PWM Library

WiringPi includes a software-driven PWM handler capable of outputting a PWM signal on any of the Raspberry Pi’s GPIO pins.

There are some limitations… To maintain a low CPU usage, the minimum pulse width is 100μS. That combined with the default suggested range of 100 gives a PWM frequency of 100Hz. You can lower the range to get a higher frequency, at the expense of resolution, or increase to get more resolution, but that will lower the frequency. If you change the pulse-width in the driver code, then be aware that at delays of less than 100μS wiringPi does it in a software loop, which means that CPU usage will rise dramatically, and controlling more than one pin will be almost impossible.

Also note that while the routines run themselves at a higher and real-time priority, Linux can still affect the accuracy of the generated signal.

However, within these limitations, control of a light/LED or a motor is very achievable.

To use:

#include <wiringPi.h>
#include <softPwm.h>

When compiling your program you must include the pthread library as well as the wiringPi library:

cc -o myprog myprog.c -lwiringPi -lpthread

You must initialise wiringPi with one of wiringPiSetup() or wiringPiSetupGpio() functions beforehand. wiringPiSetupSys() is not fast enough, so you must run your programs with sudo.

The following two functions are available:

  • int softPwmCreate (int pin, int initialValue, int pwmRange) ;

This creates a software controlled PWM pin. You can use any GPIO pin and the pin numbering will be that of the wiringPiSetup() function you used. Use 100 for the pwmRange, then the value can be anything from 0 (off) to 100 (fully on) for the given pin.

The return value is 0 for success. Anything else and you should check the global errno variable to see what went wrong.

  • void softPwmWrite (int pin, int value) ;

This updates the PWM value on the given pin. The value is checked to be in-range and pins that haven’t previously been initialised via softPwmCreate will be silently ignored.

Notes

  • Each “cycle” of PWM output takes 10mS with the default range value of 100, so trying to change the PWM value more than 100 times a second will be futile.
  • Each pin activated in softPWM mode uses approximately 0.5% of the CPU.
  • There is currently no way to disable softPWM on a pin while the program in running.
  • You need to keep your program running to maintain the PWM output!

Comments

Software PWM Library — 51 Comments

  1. First of all – Thank You for your tremendous job for RPi community.

    Back to topic:
    So lets say I don’t realy need PWM, but I want to use it as square wave generator for stepper motor driver.
    My motor have highest torque between 400 and 1000Hz.
    What is the proper pwmRange value and how to compute it to generate 400Hz wave?

    • With the softPwm library, the simple answer is that … it’s tricky.

      It all revolves round a pulse width of 100uS. So, 1000Hz, is 500uS on, 500uS off. That’s 10 “units” of 100uS pulses, so the range needs to be set to 10. Set the range to 10, set the value to 5 and you’ll get a 1000Hz square wave.

      For 400Hz, the period is 1/400 = 0.0025s – that’s 25 periods of 100uS, so set the range to 25, and the value to 12 and you get a slightly asymetrical square wave at 400Hz.

      Any value in-between just do the calculation: Range = 1 / Frequency / 0.0001, and the value is Range / 2.

      However this may not be the best way to generate an arbitary frequency for stepper motors. It would be far better to re-code it to be a frequency generator rather than a PWM generator – and that’s not too hard to do – but one limitation is the pulse width of a minimum of 100uS. Obviously it can be longer, but not shorter.

      Well, it can be shorter, but that’s then generated via a software timing loop and consumes 100% CPU, so you can only run one thread.

      One more thing – while it’s fesable, I do not think this is a suitable way to drive stepper motors. Linux can still interrupt your program – you may notice LEDs having the odd flicker to full or zero brightness during PWM – imagine a glitch like that to a loaded stpper motor running at speed – it has the potential to miss steps or even stall. It will probably work most of the time though – but is that good enough for you? I don’t know. I don’t think I’d like to trust something like a 3-d printer to it, and definatly not a CNC lathe/mill…

      -Gordon

  2. Thanks for detailed explaination, maybe I will try to define separate square generator function later, as it might be less cpu time hungry. Will Your delayMicrosecondsHard() be good enought for delay?

    For my Pi’s purpose i don’t really care about accuracy because steppers will be used for robot wheels :)

    For 3D printer purpose I keep few STM32′s.

    Thanks again, Janek.

    • delayMicroseconds calls delayMisrosecondsHard when the time is < 100uS. That works by setting a value in a register that is decremented once every 1uS and when it reaches zero, we return. The down-side of that is that the program is polling the result constantly, so it runs at 100% CPU, leavling little else for anything else to run.. So you could use it to control one motor with good accuracy, but that’s all…

      And as there is only one hardware timer, trying to call it from two different threads will produce some “intersting” results…

      I’d give it a go by modifying the code that uses the 100uS pulses first though.

      -Gordon

  3. Hi!
    I need to control a servo at 50Hz (20mS) and,to make it still, I have to set the pin “high” for 1.5mS.
    I tried to set pwmRange to “200″ and value to “7,5″ (but it didn’t work); I’ve calculated these values following this reasoning:

    1) 0,020 (mS) = 200 ‘units’ of 100uS

    2) 100 : 20 (mS) = x : 1,5 (mS)
    where 100 represent the max value (when the pin is high for all the time)
    then x = 7,5 = (100*1,5) / 20

    Did I made mistakes?

    Thanks for helping me!

    • It’s unlikely to work like that. And I don’t recommend that you try to use the softPWM code like this anyway.

      The ‘range’ is periods of 100 microseconds and the value is an integer, so setting it to 7.5 won’t work. (in-fact you should have had a compiler warning – please compile with -Wall)

      So 2 things, one is a kernel module to control servos – this should be better than anything in user-land, however the 2nd this is that I have written some experimental software servo control software. I’ll email you a copy and you can test it for me ;-)

      -Gordon

      • Hello
        I do have the same problem, I am using PWM to control my BLDC motor with ESC in middle, to generate max torgue i need to set it to 1.5ms at 50Hz and may be some value at 50hz for zero. So i need help to control this including the settings.. . .

  4. Hi,

    I’m looking to control a servo as well. I see in your source code there’s a softServo unit, but no mention of it on this site. Is that unit ready to use?

    I tried using softServoCreate and softServoWrite, but the servo just seems to pull to one side, no matter what value I give it.

    Had a quick glance at softServo.c, softServoWrite restricts value to between -250 and 1250 which seemed odd, I assume you have your reason for doing so?

    Any help in getting the servo control to work would be appreciated, thanks!

    Robo

    • There’s not documentation (yet ;-) as it’s sort of experimental. Looks like it might not be working for you though – I’m waiting on some real servos myself to try it out – only tried it on a ‘scope so-far…

      The numbers would be from 0 (hard left) to 1000 (hard right). The under/over values provide a little bit of undershoot and overshoot which some servos can handle. The number actually refers to the number of microseconds of the pulse. So 0 is a 1000uS pulse, or 1mS. 1000 is 2mS. -250 is 750uS.

      I’ll have another check on my scope later this weekend and see what it looks like again.

      -Gordon

        • No. Please don’t use it. It was really just an experiment to see if it would work – which it does, but it suffers from too much jitter – the servos buzz/twitch which isn’t good for them at all. There is an example program in the examples directory if you want to see how it works though.

          Lookup the servoblaster kernel module – I’m told that’s the best thing for RC servos on the Pi.

          -Gordon

  5. Hello there!
    First, I want to thank you for a great job. We’ve just migrated from the python PWM implementation on the GPIO, and the results are so good, we’re testing if we’re even gonna need to migrate to a real time os.

    One question about the realization. We ran your methods in a endless loop, however that generated a 98% cpu load for a single pwm.
    Here is the code example:

    #include
    #include
    int main (void)
    {
    if (wiringPiSetupGpio() == -1)
    exit (1) ;

    softPwmCreate(17, 0, 50);
    while(1){
    softPwmWrite (17, 1);
    }

    Please advise us what to do to get the reduced CPU load.

    • Well, only calling softPwmWrite() ONCE would be a help.

      You only need to call it once – after that it does the PWM for you. You do not need to continually call it.

      Also note that each PWM cycle takes 10mS, so there is no point calling it quicker than every 10mS if you want to update the value anyway.

      So:

      wiringPiSetup () ;
      softPwmCreate (0,0,50) ;
      softPwmWrite (0, 1) ;

      for (;;) delay (1000) ;

      is all you need.

      -Gordon

  6. Gordon. You know nice things. Mu question is about brushless outrunner
    (Motors) & the ESC (Speed Control) have 3 wires to control the outrunner.
    I think there is a PWM. Where can I find the timing diagram and better
    the algorithm the outrunner is controlled. Thanks.

    • Do you want to remove the ESC or send the right control to the ESC? Most ESCs used in Radio Control applictions take standard Radio Control “PWM” signals which isn’t really PWM in the classic sense, but a pulse width from 1 to 2mS. Where 1mS is hard left (for a servo, or fully off for a motor controller), and 2ms is hard right, or fully on for a motor…

      My softPwm module can not generate this sort of signal. There is an un-documented softServo module which can, but it is not good enough – search for ‘servoblaster’ to do this from the Pi.

      If you want to replace the ESC – then the Pi is not the device to do it with IMO. If you take these apart you’ll usually find a little PIC or Atmel microcontroller inside them… It translates the incoming PWM signal to the right motor control signals in real-time.

      -Gordon

      • http://www.google.com/imgres?imgurl=http://web.uvic.ca/~arasbm/quadcopter/www/images/AeroQuadUVicWiring.png&imgrefurl=http://web.uvic.ca/~arasbm/quadcopter/www/&h=1037&w=937&sz=233&tbnid=3tXvnRdyXmh5UM:&tbnh=90&tbnw=81&zoom=1&usg=__TvL6zEc3NEDtpKHJUkYwCXRk21s=&docid=Kipa3PZ8P1O42M&sa=X&ei=-y1UUYeBMIWO4gSGm4G4CA&ved=0CDkQ9QEwAQ&dur=18
        Thank u Gordon!
        My goal is to control the ESC
        from the Raspi using python. Can u made
        in The future some example program
        in Python. I think a ready to use ESC
        control from the gyro & accelerometr.
        What Hardware I need except Raspberry Pi? What Do u think about it?
        Thank You.
        Sven.

        • You will need to use the servoblaster kernel module to accomplish the control you need. WiringPi isn’t accurate enough to control RC type servos or ESCs.

          -Gordon

      • Gordon!
        Thank u So much.
        I do not want to Replace the ESC, I wish to send the right control to the
        ESC.
        I figured out there are two wires
        to control the ESC I can buy.
        It would be nice if I can do it in
        Python.
        I have Children to do this Job and I
        think the “C” language is too hard to
        understand. Python must be the right.
        By myself I can “C” but not “C++”.
        It will be hard to teach “C” and Python
        at the same time.
        Sorry to talk so much. Yes I need
        help and u are the right person to
        talk.
        Thanks.
        Sven.

        • I don’t know any Python. I only do C and BASIC. (on the Pi).

          To control servos of any kind (RC servos or ESCs) then at present you need to use the servoblaster kernel module. There is nothing in wiringPi that will help you here.

          You’ll need to look for Python examples using the servoblaster kernel module.

          Even if you program in C and use wiringPi, then my current servo module is not good enough for real control. The motors will work and they will turn, but there may be too much jitter – especially for mechanical servo motors which will overheat.

          -Gordon

          • Gordon!
            Why u’re not sleep?
            I’ve programmed K&R “C”
            about 10 years.
            Yet I’m programming with
            Python about 3 years. I know that NASA are programming with Python.
            it’s a very easy to learn and debug programs.
            I recommend u to try.
            In Pythob there is all
            you need.
            try “youtube”
            Bucky python tutorial
            It’s a great tutorial.
            I’m sure u will love
            Python.
            Thank u very much for
            your support.
            Once more sorry about my
            English but seems u can
            understand it.
            Maybe we can cooperate?
            I try to use the Rasperry
            Pi. I have one at my home.
            By, By Gordon.

      • Hi, I’m also trying to get an ESC working with this code, to make a quadcopter.

        So I wrote all my code w/ SoftPWM in mind and created a 100Hz signal with a 1.0ms-2ms “on” time in a 10ms period.

        void throttToPWM(int pin, int throttle)
        {

        /*
        pulses between 1ms and 2ms. (1ms shutdown, 1.5ms 50%, 2ms 100%)
        send updates at least 20-30Hz update rate.
        throttle = 1-100, pulseWidth_ms = 1-2, frequency = constant 100Hz
        */

        float pulseWidth_ms = throttle/100 + 1;

        float period_ms = 10;

        softPwmWrite(pin, (pulseWidth_ms/period_ms)*100);
        //should be 10-20%

        }

        Do you think it’ll work? Or should I use some PWM generator chip instead? What do you recommend?

        By the way, thanks so much for wiringPi and softPWM, it was super helpful :)

        • Oh wait, nevermind, I read some comments. Okay, no ESC control. Allriigght. Seems like enough people have bugged you about it.

          Okay, so is there a PWM generating chip thing that you can recommend? Or some other library doodad?
          Thanks a ton for your work.

          • The softPwm reall isn’t suited to driving servos – there is a softServo module in there too, however it suffers too much jitter to drive mechanical servos – I’ve not used it with ESCs though. What you might want to look at ia the servoblaster kernel module for the Pi – that’s much better suited to drive servos (and possibly ESCs)

            -Gordon

  7. Hi Gordon!
    I’ll try to make me clear about my problem:
    There is a system that can rotate only around X – axis.
    The stabily is if X == 0
    Z; Y; can’t rotate around they are fixed.
    Servo has to set to X == 0
    Servo take stepping motor or
    propeller with outrunner brushless controlled with ESC.
    Program have to set to X == 0
    Input from MPU 6050. Gyro & accelerometer.
    I think MPU 6050 –> Andruino –> I2C — python program on raspberry pi
    on output ESC — > brushless outrunner –> propeller
    or stepper motor
    the goal is to move the system to X == 0
    if x < 0:
    force = delta-x in direction X == 0 # F = += C # C constant Maybe 1 ??
    else:
    force = delta-x in direction X == 0 # F = -= C
    Sorry of my bad English! it's for Fool's!

    • You can be as clear as you like and I’ll keep on telling you that I can not help you to control an ESC with wiringPi. It will not work. You need to use the servoblaster kernel module and lookup (via google or whatever) how to drive that from Python. Once you have achieved that then you can move on to the aerodynamics, but the softwarePWM in wiringPi which this page is about is not the tool for you to control ESCs with.

      -Gordon

  8. Good day,
    i am a beginner in c programming language. i learnt about generating PWM by software and am trying to use it to light LEDs (purple white n green)on a pic18 micro controller.How can i go about doin it.
    Thanks

  9. First and foremost, thank you for your contribution, currently trying to generate a simple frequency generator from 40hz to 40Khz and i am having trouble to identify the correct values, could you or any other use be so kind to give 2 or 3 settings examples for eg. 10Hz 200Hz 5kHz so i get the hang of what does what as i am doing it as a bash script.
    Thanks in advance.

  10. Hi i’m trying to use the WiringPI to control a DC motor. I’ve followed the Adafruit steps as far as wiring up the breadbard and GPIO pins (http://learn.adafruit.com/assets/3654) but i’m at a loss as to why my code does not work. Any ideas?
    Code below:
    #include
    #include
    #include
    #include
    #include
    void setup()
    {
    //check for root user code here
    //setup wiringPI using wiringPiSetup()
    softPwmCreate(7, 0, 100);
    softPwmCreate(0, 0, 100);
    }
    int main()
    {
    printf(“Spinning Up!\n!);
    softPwmWrite(7, 100);
    softPwmWrite(0, 0);
    delay(5000); //let it spin for 5 seconds
    printf(“Stopping…\n”);
    softPwmWrite(7, 0);
    return 0;
    }

    thanks in advance!

  11. Hi I was trying to make PWM with varibale frequency and pulse width using softPwm. My approch is some thing like

    case FREQUENCY : softPwmWrite (GPIO, PULSE_WIDTH) ;//Change

    case PULSEWIDTH: softPwmCreate (GPIO,PULSE_WIDTH, PWM_FREQUENCY);

    I need to change the PWM freqency while PWM is running on current GPIO. But it seems some problem using above code. Do I need to stop the pwm on current GPIO to change its frequency, if so how can I do that.
    Thanks in advance….

    • You’ve not given me any code… just 2 lines of what looks like a switch statement.

      softPwmCreate () does not take a pulse width and frequency parameter – it’s an initial value and range (which realistically should be 100). The frequency is fixed at 10KHz.

      My softPWM module doesn’t support variable frequency – only variable mark:space ratio. The softTone module does support variable frequency at a fixed mark:space ratio. (in the range 0 to 5KHz)

      If you want to modify my code, you need to look at it – it uses the posix threads library. You’ll need to re-write it to preserve the thread handle so you can shut down the thread and re-start it if you need to change frequency. Note that pulse widths of less than 100µS will consume 100% CPU.

      -Gordon

      • Hi Gordon thanks for your reply,

        So I understood your point. So how can I stop the PWM running on current GPIO.

        And I have few more doubts

        1. My CRO showing Frequency 100Hz instead 10 KHz with pwmRange 100 or I am wrong ?.

        2. If I need multple PWM in MHz range then what is the suggeated method as RPi has only GPIO(GPIO18) supports high frequency.

        and please ignore the below commant.

  12. Is there a example? I want to control a led from the cmd.
    So just want to have one command to write, that the pwm starts, like “start-pwm 8(ms high) 10(ms frequency) 5(pin)” or something like that…

    Greece from Germany :)

    • You can use PWM from the command line on the single hardware PWM line (Pin 1)

      e.g

      gpio mode 1 pwm
      gpio pwm 1 512 # Half
      gpio pwm 1 1024 # full

      and so on. If you want to fiddle with the frequencies then look at the manual page (man gpio)

      -Gordon

    • It works for me, but you’ll need to give me more to go on.

      If you mean the pwn.c program in the examples directory – then it’s an example program – you can use it as an example to see how to use the pwm functions inside wiringPi from your own programs.

      -Gordon

      • Hi Gordon,
        I wish to use a compatible LCD I2C HD44780 and http: //www.adafruit.com/ products/815, I build a cockpit of helicopter around FSX. I made make out a will under pythons but that does not turn rather fast, there are problems with the times of transfer. I use the protocol UDP to exchange my datas. Thank you again for your help.
        Cordially FX; op

        Small video of start of my project on Arnuino UNO, today i work on Raspberry Pi :
        http://mediafx.fr/318/Panel/horizon%20artificiel/horizonHarti.wmv

          • I’m not that sure what you’re after here – I think you’re saying Python is too slow, but for what? then you mention UDP – that would be communicating betwen 2 devices- what 2 devices?

            -Gordon

          • OK, I plant the decoration(set): my project uses a pc master(teacher) on which works FSX and soft one house. Soft house gets back the data of FSX and passes on(transmits) them in the network via the protocol UDP in Raspberry Pi on which there is a billposter LDC I2C and a PWM I2C module which manages my servos. I wish to encode ‘ C ‘ my interface on Rpi because in Python there is of big delay of data processings. Thus, confirm me you that I can pilot the LCD I2C and the PWM I2C module with wiringPi, as I manage the same module on a card(map) Arduino UNO?
            Cordially.
            ————————
            Ok, je plante le décor : mon projet utilise un pc maître sur lequel fonctionne FSX et un soft maison. Le soft maison récupère les données de FSX et les transmet dans le réseau via le protocole UDP à un Raspberry Pi sur lequel il y a l’afficheur LDC I2C et le module PWM I2C qui gère mes servos. Je souhaite encoder en ‘C’ mon interface sur le Rpi car en Python il y a de gros retard de traitements des données. Donc, me confirmez vous que je peux piloter le LCD I2C et le module PWM I2C avec wiringPi, comme je gère ces même module sur une carte Arduino UNO ?
            Cordialement.

          • wiringPi can talk to most character based LCD displays – see http://wiringpi.com/dev-lib/lcd-library/ however that’s driving them directly and not via I2C. (The Adafruit one uses I2C to talk to a GPIO expander chip though rather than some intelligent microcontroller controlling the display). There shouldn’t be an issue with the PWM module – wiringPi already talks to one PWM module – the one that’s used in the PiGlow add-on board.

            -Gordon

  13. Hi Gordon,

    I want to build a raspberryPi based robot and hence need to drive two motors using 2 PWM signals of the Pi. (I need 2 separate pwm signals to drive 2 motors bacause I want to apply PID control mechanism on them). Since there is only one hardware pwm available on Pi, I thought of using software pwm for the 2nd motor. I have set both of their range same,100 using pwmSetRange(). Now, due to the difference between the frequencies of two pwm: software at 100 Hz and hardare pwm at 600 KHZ(by default), the two motors run differently, even when given same speed(same “value” parameter). I understand that software pwm can not be operated at frequency greater than 100 Hz, but how can I lower down the freq of hardware pwm? the function pwmSetClock() didn’t seem to work for this! you said in one of the posts that you have set default frequency 600 KHZ,for changing this, which file/module I’ll need to edit in your library?
    Also, as I have put my problem before you, can you suggest me anything else for running two motors using raspberry Pi?

    Thanks.

    Garima

    • Are you aware that the default ranges on the hardware vs. software PWM are different?

      ie. half speed on the hardware pin is 512 and half speed on the software one is 50.

      Why not make both pins use the software driver?

      -Gordon

      • Hi,
        Thanks for reply :)
        Yes I know that the default range of two are different!
        I will try to use two software pwms and see if it works.

        Thanks.

  14. Thanks for the awesome work, first off!

    I might have missed it somehow, but what is a way to set the max-range of the hardware PWM pin on the Raspberry Pi to a value other than the default (1023)?
    I’m using one software PWM plus the hardware PWM and I’d like them both to have the same range, say 100.

  15. This is a brilliant set of tools, and really well presented on this site (although I have a bit of problem finding the example source files). I used the PWM (softPwmCreate)to generate a loop-back, free-running, 10ms hardware interrupt onto one of the GPIO pins running in one process, which is then serviced by wiringPiISR in my main process. This 10ms interrupt is ideal for servicing timers, flashers, etc. Looks rock solid on a ‘scope.
    Great job!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Current day month ye@r *