I've written a library that controls a rgb ledstrip.
I'm looking for optimization so that the time to change the color gets faster.
The code that needs optimization is goes as follows:
void RGB::setFromHSV(double hue, double saturation, double value){
double RGB[3]; // to store the 3 values of R, G & B
//H = hue, S = saturation (saturation), V = Value(blackness) http://en.wikipedia.org/wiki/HSL_and_HSV
_H = hue;
_S = saturation;
_V = value;
double f, p, q, t;
if (_H > 359) _H = 0.0;
_H = constrain(_H, 0.0, 360.0);
int Hi = floor((_H / 60));
f = _H / 60.0 - (Hi);
p = (_V * (1.0 - _S));
q = (_V * (1.0 - f * _S));
t = ((_V * (1.0 - (1 - f) * _S)));
switch (Hi) {
case 0:
RGB[0] = _V;
RGB[1] = t;
RGB[2] = p;
break;
case 1:
RGB[0] = q;
RGB[1] = _V;
RGB[2] = p;
break;
...(other cases similar)...
default:
RGB[0] = 0;
RGB[1] = 0;
RGB[2] = 0;
}
RGB[0] = round((RGB[0] * 255.0));
RGB[1] = round((RGB[1] * 255.0));
RGB[2] = round((RGB[2] * 255.0));
_r = RGB[0];
_g = RGB[1];
_b = RGB[2];
writeLeds();
}
Now for the optimization: I'm thinking that the most efficient way to speed things up, is to change the analogWrite to the method using the PWM registers directly?
I'm limited to the pins 9,10 & 11 due to hardware restrictions (pcb is already made etc...) I'm using the arduino nano.
Also, I think I shouldn't change the timer registers, because I'm also using a RTC and LCD and delay() functions?
Will changing the pwm method help me to run the code faster? and if so, how do I edit the duty cycle on those 3 pins without changing frequency?
Other ways to speed up the code are welcome too
Now for the optimization: I'm thinking that the most efficient way to speed things up, is to change the analogWrite to the method using the PWM registers directly?
That will make little, if any, difference. analogWrite just sets the PWM registers. The PWM is then done by hardware.
There is a little mucking around translating the requested pin to a register, but after that, it is plain sailing (example):
// connect pwm to pin on timer 1, channel A
sbi(TCCR1A, COM1A1);
OCR1A = val; // set pwm duty
and if so, how do I edit the duty cycle on those 3 pins without changing frequency?
That can be done if you want to. There is a trade-off between available frequencies and the range of duty-cycles available.
As an example, if you need the counter to count to 4 to give you a desired frequency, there can be only 4 possible duty cycles: 0, 1, 2, 3.
edit @robtillaart:
My code took +-150 µs; the changes you proposed, made it 67µs faster @Nick Gammon:
Indeed, the 3 analogWrite's together take only 40µs; so it seems like there is little to improve on that part.
I changed my main loop so that the code that reads the current time from the rtc is runned only once every 500th loop too.
after all, the result is that the main loop runs at 1780Hz instead of 530Hz. quite an improvement I'd say. (: