Very simple class to give slow speed PWM using timers and digital out.

Example use...

#include "SlowPWM.h"
SlowPWM MyTimer1(LED1);
SlowPWM MyTimer2(LED2);
SlowPWM MyTimer3(LED3);

main()
{
    MyTimer1.setPeriod(4);
    MyTimer1.setHighTime(2);
    MyTimer1.start();
    MyTimer2.setPeriod(2);
    MyTimer2.setHighTime(1.5);
    MyTimer2.start();
    MyTimer3.setPeriod(3.8);
    MyTimer3.setHighTime(1.5);
    MyTimer3.start();
    while(true) {
        wait(1);
    }
}

SlowPWM.cpp

Committer:
AndyA
Date:
2019-06-21
Revision:
3:3f7eb3ad23d4
Parent:
2:c90e2d2f52aa

File content as of revision 3:3f7eb3ad23d4:

#include "SlowPWM.h"

SlowPWM::SlowPWM(const PinName pin ):DigitalOut(pin)
{
    _repeatTime=1;
    _timeOn=0.5f;
}

SlowPWM::SlowPWM( const PinName pin, const float period, const float highTime ):DigitalOut(pin)
{
    setPeriod(period);
    setHighTime(highTime);
    start();
}

void SlowPWM::setPeriod(const float period)
{
    _repeatTime = period;
    if (_repeatTime <= 0)   // check it's not 0 or negative
        _repeatTime = 1;
    setHighTime(_timeOn);  // perform sanity check on high time
}

void SlowPWM::setHighTime(const float highTime)
{
    if (highTime == 0) {
        stop();
        write(0);
    } else if (highTime >= _repeatTime) {
        stop();
        write(1);
    } else {
        _timeOn = highTime;
        start();
    }
}

void SlowPWM::setDutyCycle(const float cycle)
{
    if (cycle == 1) {
        stop();
        write(1);
    } else if (cycle == 0) {
        stop();
        write(0);
    } else if ((cycle >0) && (cycle <1)) {
        _timeOn = _repeatTime*cycle;
        start();
    } else
        _timeOn = _repeatTime/2; // set to 50% if invalid
}

void SlowPWM::stop()
{
    offTimer.detach();
    cycleTimer.detach();
}

// start things.
void SlowPWM::start()
{
    cycleTimer.attach(callback(this,&SlowPWM::onCycleStart),_repeatTime);
    onCycleStart();
}

void SlowPWM::onTurnOff(void)
{
    write(0);
}

void SlowPWM::onCycleStart(void)
{
    offTimer.attach(callback(this,&SlowPWM::onTurnOff),_timeOn);
    write(1);
}