# WiringPi + softPwm calculation to determine duty cycle

For my project we got a pre-installed rpi with all the working libraries and an example program to set a servo in middle position.

The info: in a period of 20ms (50hz) we need 1,5ms to set it to middle position, 2ms to set it to the right, 1ms to set it to the left.

If one would use only softPwm I suppose it would look something like this to set it to the middle:

``````    pinMode(0,output);
digitalWrite(1,LOW);
softPwmCreate(1,0,200);
softPwmWrite(1,185);
``````

But my teacher added: `pwmSetClock(500);` And his example program (which doesn't put the servo spot on in the middle but just a little off):

``````   pinMode(0,output);
digitalWrite(1,LOW);
pwmSetClock(500);
softPwmCreate(1,0,500);
softPwmWrite(1,14);
``````

I thought that softPwm uses the 'time off duration' values, so in the example it would mean its off for 486ms? Or did the pwmSetClock(500) change the entire calculation?

Basicly, with these values I would not know how to calculate the values to insert in softPwmWrite() to set the servo to the left or right. The other pwm values (like pwmRange etc) are default as far as I know.

My question: I want to understand how to calculate the value needed for softPwmWrite, to set the pwm to 2ms or 1ms, and how pwmSetClock() changes/affects the calculation. I've been browsing internet for concrete info about this but I can't find any explanations which take pwmSetClock into consideration.

I don't use those functions so this is gleaned from the documentation.

The basic pulse unit is 100 micros long.

The final paramater in softPwmCreate says how long each cycle is in basic pulse units.

softPwmCreate(1,0,200) says create a cycle 20 ms long made up of 200 steps (20 ms as 200 * 100 = 20000 microseconds).

softPwmWrite(1,185) says keep the pulse high for 18.5 ms in every 20 ms cycle (18.5 ms as 185 * 100 = 18500 microseconds). That is way too long. Servos nominally respond to 1 ms - 2 ms pulses. So you should choose values 10 - 20.

softPwmCreate(1,0,500) says create a cycle 50 ms long made up of 500 steps.

softPwmWrite(1,14) says keep the pulse high for 1.4 ms in every 50 ms cycle. This will be close to the central position. A correct value would be 15 (again nominally values 10-20 should be used).

The 20 ms cycle is more correct for servos as it will give a nominal update of 50 Hz. A 50 ms cycle will only update at 20 Hz.

In my opinion pwmSetClock(500) has nothing to do with what you are doing and can be ignored. If it changes anything it'll be the frequency output on gpio18 (Broadcom numbering).

Why not teach your teacher something and use a library which controls servos properly?

My own pigpio or servoblaster or RPIO.GPIO (note, NOT RPi.GPIO), etc.

I just confirmed my understanding by running the following program and viewing the output with piscope.

gcc -o wpi wpi-servos.c -lwiringPi

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

#define GPIO1 4
#define GPIO2 7

int main(int argc, char *argv[])
{
if (wiringPiSetupGpio() < 0) return 1;

pinMode(GPIO1, OUTPUT);
digitalWrite(GPIO1, LOW);
softPwmCreate(GPIO1, 0, 200);
softPwmWrite(GPIO1, 15);

pinMode(GPIO2, OUTPUT);
digitalWrite(GPIO2, LOW);
softPwmCreate(GPIO2, 0, 500);
softPwmWrite(GPIO2, 15);

sleep(30);
}
``````

webm video

• Wow, I had been going over this in my head a 1000 times thinking the setPwmClock(500) was the reason my teacher used softPwmCreate(1, 0 , 500) instead of 1, 0 ,200. Because we want a 20ms cycle. But apparantly he just used the wrong numbers, because if I use 200 the whole thing works just fine! Thanks, I think I understand the concept now Commented Sep 19, 2014 at 18:48
• @joan I've been trying for days to get 100 or 180 positions out of the servo, (orangepi with wiringPi). Your the first person i've seen who states what i've found to be true, that you'll only get about 0-14-24 left-mid-right position, yet i've seen arduino libraries that can give 180 positions, 1 per degree, any ideas why this would be? Commented Oct 6, 2016 at 7:50
• It's just a limitation of the software as implemented. The base timing unit is 100µs. You could alter the library function but I wouldn't bother. Unless you have a very simple servo application software timed PWM will be too jittery to control an ESC or servo. Buy a proper Pi or find a way of using any hardware PWM provided by the orangepi.
– joan
Commented Oct 6, 2016 at 7:58