chipKIT® Development Platform

Inspired by Arduino™

Last edit: 2021-03-21 22:34 by Majenko

SoftPWMServo

SoftPWMServo
Quick Look
Hardware (External hardware)
Include SoftPWMServo.h

This library allows every single pin on a PIC32 Based ChipKit Board to be used (simultaneously) for PWM output or RC Servo output.

  1. Detailed Introduction

  2. Wiring

  3. Introductory Programs

    1. Simple PWM

    2. Simple Servo

  4. Full library usage

    1. SoftPWMServo

      1. Constructors

        1. SoftPWMServoInit(void))

      2. Constants

      3. Public Functions

        1. SoftPWMServoUnload(void)

        2. SoftPWMServoPinEnable(uint32_t Pin, bool PinType)

        3. SoftPWMServoPinDisable(uint32_t Pin)

        4. SoftPWMServoRawWrite(uint32_t Pin, uint32_t Value, bool PinType)

        5. SoftPWMServoServoWrite(uint32_t Pin, float Value)

        6. SoftPWMServoPWMWrite(uint32_t Pin, uint8_t Value)

        7. SoftPWMServoRawRead(uint32_t Pin)

        8. SoftPWMServoServoRead(uint32_t Pin)

        9. SoftPWMServoPWMRead(uint32_t Pin)

        10. SoftPWMServoSetFrameTime(uint32_t NewTime)

        11. SoftPWMServoSetServoFrames(uint32_t NewFrameCount)

  5. External Links

Detailed Introduction

The SoftPWMServo library was written primarily to allow existing Arduino sketches to be more easily ported to the ChipKIT boards. Since the PIC32 does not have as many available PWM outputs or RC Servo outputs, this library implements in software what would normally be done almost entirely in hardware. It allows for every single pin on a PIC32 based boards to be used (simultaneously) for PWM output or RC Servo output. Since it is a software based library, it does come with some negatives such as increased CPU usage and jitter.

Because the pin transitions are driven by software, there are limits to how accurate the pulses are, but for almost all uses, this library will work just fine, even with a large number of pins being used for PWM or Servo. Also, this library does add CPU load to the system, which is proportional to the number of pins being used for PWM or Servo output.

Wiring

300px

This library can utilize any pin on a PIC32 based ChipKit Board enabling it to produce a PWM (Pulse Width Modulation) signal. Therefore the following wiring information is only one example of how you could use this library.

Servos have 3 wires (Power, Ground, and Signal). They consume a considerable amount of power and therefore the Power and Ground wires should be connected to a suitable power source and are often connected to an external power source instead the 5V pin on the ChipKit as shown here. Signal wires need a return path. Therefore, make sure the ground wire of the power power supply is connected to the ground pin of the ChipKit. The Signal wire of the servo should connected to an unused digital pin. Refer to the Fritzing Wiring Diagram.

Introductory Programs

The following sketch examples demonstrated how to use the SoftPWMServo library object.

Simple PWM

Ramps the value on up to 3 different pins from 0 to 255 (0 to 100%). Simply un-comment the line(s) of code which corresponds to the pins you would like to increment.

// Simple PWM demonstration using SoftPWMServo library
// by Brian Schmalz http://www.schmalzhaus.com
// This example code is in the public domain.

// We take 3 pins (could be any at all) and slowly
// ramp them up from 0% to 100%. You could put
// red, green and blue LEDs on these pins and have a neat
// little color fader.

#include <SoftPWMServo.h>
 
// Pick 3 pins, any 3 pins, and use them for our PWM output
const int PinOne = 10;
const int PinTwo = 35;
const int PinThree = 22;

// Start each pin out at a different PWM value
char PinOneValue = 0;
char PinTwoValue = 100;
char PinThreeValue = 200;
 
void setup() 
{ 
} 
 
void loop() 
{ 
  // Set each of our three pins as PWM outputs, with their respective values
  SoftPWMServoPWMWrite(PinOne, PinOneValue);
  SoftPWMServoPWMWrite(PinTwo, PinTwoValue);
  SoftPWMServoPWMWrite(PinThree, PinThreeValue);
  
  // Incriment each PWM value - they will roll over after 255 due to being chars
//  PinOneValue++;
//  PinTwoValue++;
//  PinThreeValue++;

  // Wait just a tad so we don't go too fast.  
  delay(15);
}

Simple Servo

Tells a servo to go from a position defined by a 1ms pulse to a position defined by a 2ms pulse in increments of 10us with a 25ms delay between each step. This routine then repeats forever.

// Simple Servo demonstration using SoftPWMServo library
// by Brian Schmalz http://www.schmalzhaus.com
// This example code is in the public domain.

// We take a pin (could be any pin) and use it as a servo
// output. We sweep from 1ms pulse to 2ms pulse to show
// that the servo can be controlled.

// Note that you could easily write a little function to 
// convert from 'desired angle in degrees' to 'microseconds'
// so that you could specify a degree value to your servo.

#include <SoftPWMServo.h> 

int pos = 0;         // variable to store the servo position, in microseconds
const int pin = 10;  // Choose _any_ pin number on your board
 
void setup() 
{ 
} 
 
void loop() 
{ 
  for(pos = 1000; pos < 2000; pos += 10)  // goes from 1ms to 2ms
  {                                       // in steps of 10us
    SoftPWMServoServoWrite(pin, pos);     // tell servo to go to position in variable 'pos' 
    delay(25);                            // waits 25ms for the servo to reach the position 
  } 
} 

Full library usage

SoftPWMServo

Constructors

SoftPWMServoInit(void))

int32_t SoftPWMServoInit(void); 

Returns: SOFTPWMSERVO_OK

Initializes the SoftPWMServo library. It clears out all internal variables to their default states, and hooks the SoftPWMServo CoreTimer ISR function into the main CoreTimer interrupt. Call this function before calling any others from this library (optional, as SoftPWMServoPinEnable and SoftPWMServoWrite calls will call this function on their own if necessary.)

Constants

Name Default Value Description
SOFTPWMSERVO_VERSION [version] Software version of this library
SOFTPWMSERVO_MAX_PINS NUM_DIGITAL_PINS Max number of pins the library can handle (from variant Board_Defs.h)
SOFTPWMSERVO_ERROR -1 Returned when a function fails
SOFTPWMSERVO_OK 0 Returned when a function passes
SOFTPWMSERVO_SERVO 1 Used to enable a pin for servo operation
SOFTPWMSERVO_PWM 0 Used to enable a pin for PWM operation
MIN_PULSE_WIDTH 544 The shortest pulse sent to a servo (us)
MAX_PULSE_WIDTH 2400 The longest pulse sent to a servo (us)
DEFAULT_PULSE_WIDTH 1500 Default pulse width when servo is attached (us)
DEFAULT_FRAMES_PER_SECOND 400 2.5ms per frame
SOFTPWMSERVO_DEFAULT_FRAME_TIME (F_CPU / 2 / DEFAULT_FRAMES_PER_SECOND) Number of 40MHz CoreTimer ticks of the default frame time
CORE_TICKS_PER_US (F_CPU / 2 / 1000000) How many CoreTimer ticks are there per microsecond
SOFTPWMSERVO_DEFAULT_SERVO_FRAMES 10 Default number of frames between servo rising edges
usToTicks(_us) (CORE_TICKS_PER_US * _us) converts microseconds to 40MHz CoreTimer ticks
ticksToUs(_ticks) (((uint32_t)_ticks ) / (float)CORE_TICKS_PER_US) Converts from 40MHz ticks to microseconds

Public Functions

SoftPWMServoUnload(void)

  int32_t SoftPWMServoUnload(void);

Removes the SoftPWMServo CoreTimer ISR function hook from the main CoreTimer ISR in wiring.c

SoftPWMServoPinEnable(uint32_t Pin, bool PinType)

  int32_t SoftPWMServoPinEnable(uint32_t Pin, bool PinType);            

Sets up a particular pin for use with the SoftPWMServo library. Pin is set to valid pin number for the board you are using (0 to SOFTPWMSERVO_MAX_PINS). PinType is set to either SOFTPWMSERVO_SERVO or SOFTPWMSERVO_PWM.

SoftPWMServoPinDisable(uint32_t Pin)

int32_t SoftPWMServoPinDisable(uint32_t Pin);

Disables a pin from use by the SoftPWMServo library

SoftPWMServoRawWrite(uint32_t Pin, uint32_t Value, bool PinType)

int32_t SoftPWMServoRawWrite(uint32_t Pin, uint32_t Value, bool PinType);

Sets a particular pin to have a new PWM or Servo pulse high-time and sets the pin to be a Servo or PWM pin. Pin is set to valid pin number for the board you are using (0 to SOFTPWMSERVO_MAX_PINS). PinType is set to either SOFTPWMSERVO_SERVO or SOFTPWMSERVO_PWM. Value is specified in Ticks. Hint: use usToTicks(Value) to specify the value in microseconds.

This function is called internally by ServoWrite and PWMWrite. You do not need to call it unless you want full control over the pin's high time. This function allows you to specify the high time of the pin in 40MHz units.

SoftPWMServoServoWrite(uint32_t Pin, float Value)

int32_t SoftPWMServoServoWrite(uint32_t Pin, float Value);           

Use this function to set a pin to be a servo output, and to specify the pin's pulse width. Pin is set to valid pin number for the board you are using (0 to SOFTPWMSERVO_MAX_PINS). Value is specified in microseconds.

Note that if Value is greater than the current FrameTime (normally around 2ms) then FrameTime is used (since that's the longest pulse that can be generated.) Use SoftPWMServoSetFrameTime() to use a longer frame time if you need your servo to go further.

SoftPWMServoPWMWrite(uint32_t Pin, uint8_t Value)

int32_t SoftPWMServoPWMWrite(uint32_t Pin, uint8_t Value);  

Use this function to set a pin to be a PWM pin, and specify its pulse width. Equivalent to the normal analogWrite() call. Pin is set to valid pin number for the board you are using (0 to SOFTPWMSERVO_MAX_PINS). Value is specified as an integer between 0 and 255 (0% t0 100%) representing the time you want your pin to stay high.

SoftPWMServoRawRead(uint32_t Pin)

int32_t SoftPWMServoRawRead(uint32_t Pin); 

Returns the current pulse width, in 40MHz ticks, of Pin.

SoftPWMServoServoRead(uint32_t Pin)

float SoftPWMServoServoRead(uint32_t Pin); 

Returns the current pulse width, in microseconds, of Pin.

SoftPWMServoPWMRead(uint32_t Pin)

int8_t SoftPWMServoPWMRead(uint32_t Pin);

Returns the current pulse width, from 0 to 255, of Pin.

SoftPWMServoSetFrameTime(uint32_t NewTime)

 int32_t SoftPWMServoSetFrameTime(uint32_t NewTime);

Sets a new frame time, in 40MHz ticks for the library

SoftPWMServoSetServoFrames(uint32_t NewFrameCount)

int32_t SoftPWMServoSetServoFrames(uint32_t NewFrameCount);

Sets a new value for how many frames between rising edges of the servo pins.

External Links

List some links to external resources, such as: