//#define DEBUG
#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))
struct Pulse
{
uint32_t startTime; // us
uint16_t pulseWidth; // us
bool isOn;
bool trigger;
uint8_t pin;
};
uint32_t timerInterval = 2000;
// software pwm pin configuration
Pulse pwm[] =
{
{0, 250, false, false, 13, },
{0, 500, false, false, 12, },
{0, 1000, false, false, 11, },
};
// reference pin for timebase in logic analyser
uint8_t refPin = 10;
void setup()
{
Serial.begin(115200);
Serial.println(F("Software PWM with 3 LEDs"));
pinMode(refPin, OUTPUT);
for (uint8_t cnt = 0; cnt < NUMELEMENTS(pwm); cnt++)
{
pinMode(pwm[cnt].pin, OUTPUT);
}
}
void loop()
{
// run software PWM
softPWM();
}
/*
softPWM
Create the timebase
*/
void softPWM()
{
static uint32_t startTime;
static boolean refStatus = false;
static bool trigger = false;
if (micros() - startTime >= timerInterval)
{
startTime = micros();
refStatus = !refStatus;
trigger = true;
digitalWrite(refPin, refStatus == true ? HIGH : LOW);
}
if (trigger == true)
{
for (uint8_t cnt = 0; cnt < NUMELEMENTS(pwm); cnt++)
{
pwm[cnt].trigger = true;
pwm[cnt].startTime = startTime;
}
trigger = false;
}
for (uint8_t cnt = 0; cnt < NUMELEMENTS(pwm); cnt++)
{
// do we need the condition?
if (pwm[cnt].trigger == true)
{
pulse(cnt);
}
}
}
/*
Create a pulse
In:
index of pwm pin to control
Returns:
true if pulse is in progress, else false
*/
bool pulse(uint8_t idx)
{
if (pwm[idx].pulseWidth == 0)
{
digitalWrite(pwm[idx].pin, LOW);
return false;
}
if (pwm[idx].isOn == false)
{
digitalWrite(pwm[idx].pin, HIGH);
pwm[idx].isOn = true;
pwm[idx].startTime = micros();
return true;
}
if (micros() - pwm[idx].startTime >= pwm[idx].pulseWidth)
{
digitalWrite(pwm[idx].pin, LOW);
pwm[idx].isOn = false;
pwm[idx].trigger = false;
return false;
}
}