Servo module reference

Header :
#include <Servo.h>
Makefile :
MODULES+=tc
UTILS_MODULES+=Servo

Description

This class is a shallow layer above the TC module which makes controlling servomotors easier.

Each servo output uses a TC channel to generate the PWM output. This channel must not be used for other purposes. See the TC module reference for more information on TC channels.

When using servos, be careful about the way you power them. The 3.3V output is too low for most servos to operate properly, and is limited to 300mA, which is easily reached except maybe by the smallest servos with no load. If a battery is plugged in and properly charged, Vbat might provide enough voltage and current for small to medium servos. The best solution is to power the servo externally, such as from an RC BEC circuit which is designed for this exact purpose and easily available in the same stores as the servos themselves.

Examples

API

Servo(TC::Channel tcChannel, GPIO::Pin pin={GPIO::Port::A, 0xFF})
Initialize the servo using the given TC channel. If pin is given, GPIO::setPin() is called to set the pin used by this channel, otherwise the default pin is used (see the Pin muxing tutorial).
void set(unsigned int percent)
Set the servo position in percent. This will translate to different angles according to the angular range of the servo.
void setPWMTimings(unsigned int highTime0=DEFAULT_HIGH_TIME_0, unsigned int highTime100=DEFAULT_HIGH_TIME_100, unsigned int period=DEFAULT_PERIOD)
By default, the PWM output will have a period of 10000µs and a hightime between 1000µs and 2000µs (for 0% and 100%). If the servomotor you are using expects non-standard timings (800µs to 2200µs for example), use this function to configure it. Calling this function with no argument resets the default values.

Hacking

This class is extremely simple and the PWM format used to control servomotors is fairly straightforward, there isn't much room for customization.

Code

Header

#ifndef _SERVO_H_
#define _SERVO_H_

#include <tc.h>
#include <gpio.h>

// This class is a shallow helper to use a TC channel as a PWM generator to control a servomotor
class Servo {
private:
    TC::Channel _tcChannel;
    GPIO::Pin _pin;
    unsigned int _period;
    unsigned int _highTime0;
    unsigned int _highTime100;
    unsigned int _percent;
    bool _disabled;

    static const unsigned int DEFAULT_PERIOD = 10000;
    static const unsigned int DEFAULT_HIGH_TIME_0 = 1000;
    static const unsigned int DEFAULT_HIGH_TIME_100 = 2000;

public:
    // Constructor : must specify the underlying TC channel to use
    Servo(TC::Channel tcChannel, GPIO::Pin pin={GPIO::Port::A, 0xFF});

    // Set the servo position in percent
    // This will translate to differant angles according to the exact servo angular range
    void set(unsigned int percent);

    void disable();

    // Customize the PWM timings
    // Passing no argument resets the default values
    void setPWMTimings(unsigned int highTime0=DEFAULT_HIGH_TIME_0, unsigned int highTime100=DEFAULT_HIGH_TIME_100, unsigned int period=DEFAULT_PERIOD);

};

#endif

Module

#include "Servo.h"

// Constructor : must specify the underlying TC channel to use
Servo::Servo(TC::Channel tcChannel, GPIO::Pin pin) {
    // Save the parameters
    _tcChannel = tcChannel;
    _pin = pin;

    // Default values
    _percent = 50;
    _disabled = true;

    // If a custom pin is specified, set it
    if (pin.number != 0xFF) {
        TC::setPin(tcChannel, TC::PinFunction::OUT, pin);
    }

    // Initialize the TC channel to output the PWM signal
    TC::init(tcChannel, DEFAULT_PERIOD, 0, true);

    // Set default timings
    setPWMTimings();
}

// Set the servo position in percent
// This will translate to different angles according to the angular range of the servo
void Servo::set(unsigned int percent) {
    // Check value
    if (percent > 100) {
        percent = 100;
    }

    // Save the value
    _disabled = false;
    _percent = percent;

    // Compute and set the hightime
    TC::setHighTime(_tcChannel, _highTime0 + percent * (_highTime100 - _highTime0) / 100);
}

void Servo::disable() {
    _disabled = true;
    TC::setHighTime(_tcChannel, 0);
}

// Customize the PWM timings
// Passing no argument resets the default values
void Servo::setPWMTimings(unsigned int highTime0, unsigned int highTime100, unsigned int period) {
    // Save the timings
    _highTime0 = highTime0;
    _highTime100 = highTime100;
    _period = period;

    // Reset the high time
    TC::setHighTime(_tcChannel, 0);

    // Set the period
    TC::setPeriod(_tcChannel, period);

    // Recalculate the hightime based on the new timings
    if (!_disabled) {
        set(_percent);
    }
}