I am trying to write a simple software PWM to fade some LEDs because I don't have enough PWM I/O Ports.
The code evaluates how long you want the LED to fade, and breaks it down into a number of steps. During each step, it will evaluate the period the LED should be on.
I have the following code:
class Led{
public:
Led(int pin);
void setup();
// void updateFadeDirection();
void updateBrightness();
private:
int _pin;
unsigned long _currentTime;
unsigned long _startTime; // Very beginning of fade period
unsigned long _fadePeriod; // How long to fade on and off
int _fadeStep; // current fade step i.e. 1/255
int _fadeSteps; // How many steps to take until full brightness
int _fadeDirection; // low to high or high to low?
float _T_on; // Amount of time to turn LED on
float _T_fadeStep; // Amount of time per step increment of brightness
unsigned long _stepTime; // Start of current step period
bool _evaluated;
};
Led::Led(int pin){
_pin = pin;
}
void Led::setup(){
pinMode(_pin, OUTPUT);
_startTime = micros();
_fadePeriod = 2*1000000; //microseconds(us)
_fadeStep = 50; // start at 0 brightness here
_fadeSteps = 100;
_fadeDirection = 1;
_T_fadeStep = _fadePeriod/_fadeSteps; // i.e. 2000000us/100steps = 20000us/step of brightness
_T_on = (_fadeStep/_fadeSteps) * _T_fadeStep; // i.e. 20/100 * 20000us = 4000us on
_stepTime = micros();
delayMicroseconds(200);
}
void Led::updateBrightness(){
_currentTime = micros();
if(_currentTime - _startTime < _fadePeriod){
if (_currentTime - _stepTime > _T_on){
digitalWrite(_pin, LOW);
} else {
digitalWrite(_pin, HIGH);
}
if(_currentTime - _stepTime >= _T_fadeStep){
// _fadeStep++;
_stepTime = _currentTime;
_T_on = (_fadeStep/_fadeSteps) * _T_fadeStep;
}
}
else{
digitalWrite(_pin, HIGH);
}
}
Led LED0(0);
void setup() {
LED0.setup();
}
void loop() {
LED0.updateBrightness();
}
The current behaviour when powered on is the single LED will be turned off, then will turn on after 2 seconds.
In particular, it never seems to enter the else
part
if (_currentTime - _stepTime > _T_on){
digitalWrite(_pin, LOW);
} else {
digitalWrite(_pin, HIGH);
}
The problem is that the LED will never hit HIGH
until the outer else
is triggered.
I believe it has to do with _T_on
being an int
and the timestamps being unsigned long
and me not casting it.
The expected behaviour is 2 seconds of dimmed (50%) light, and then a full 100% when it hits the outer else
.
int
/unsigned long
- I've just tried it. Not sure why you didn't try it if you thought that was the problem!fadePeriod
). @CharlieHanson: yes it's an LED fader using PWM, which you can set duration from 0 to full brightness, as well as how many steps in that duration (to simulate smoothness or harsh steps). I did try theint
/unsigned long
, but didn't work so thought I'd throw it up here for anyone to correct me. I am not usingOCR1A/B
.