Just a follow-up to state that after making the change specified in the post above to my copy of the libraries, I can confirm the behavior is now as I would expect.
Chart
One thing I noticed when parsing the function -- it calculates the value based on the current time in seconds. With a 12-bit slope, though, you would need at least a 70 minute (linear) ramp to take full advantage of all 4095 levels available. I wonder if it isn't possible to increase the resolution to tenths (or even hundredths) of a second, e.g., by multiplying the start, end and current values by 10, and adding (current_millis()%1000 - current_millis()%100)/100 to the current value, as in this function (which also takes PWM start and end values as 12-bit values instead of percentages):
Code: Select all
int PWMSmoothRampHighestRes(byte startHour, byte startMinute, byte endHour, byte endMinute, int startPWMint, int endPWMint, byte slopeLength, int oldValue)
{
LightsOverride=true;
int current_hour = hour();
long current_millis = millis()
long start = NumMins(startHour, startMinute)*600L;
long end = NumMins(endHour, endMinute)*600L;
long slopeLengthTenthSecs = slopeLength*600L;
if (start > end) // Start is greater than End so it is over midnight
{
if (current_hour < endHour) start -= 1440L*600L; // past midnight
if (current_hour >= startHour) end += 1440L*600L; // before midnight
}
long current = NumMins(current_hour, minute())*600L + second()*10L + (current_millis()%1000 - current_millis()%100)/100L;
if (slopeLengthTenthSecs > ((end-start)/2) ) slopeLengthTenthSecs = (end-start)/2; // don't allow a slope length greater than half the total period
if (current <= start || current >= end)
return oldValue; // it's before the start or after the end, return the default
else
{ // do the slope calculation
int pwmDelta = endPWMint - startPWMint;
float smoothPhase;
if ((current > (start + slopeLengthTenthSecs)) && (current < (end - slopeLengthTenthSecs)))
return endPWMint; // if it's in the middle of the slope, return the high level
else if ((current - start) < slopeLengthTenthSecs)
{ // it's in the beginning slope up
smoothPhase = (((float)(current-start)/(float)slopeLengthTenthSecs)*180.0) + 180.0;
}
else if ((end - current) < slopeLengthTenthSecs)
{ // it's in the end slope down
smoothPhase = (((float)(end-current)/(float)slopeLengthTenthSecs)*180.0) + 180.0;
}
return startPWMint + (int)(pwmDelta*((1.0+(cos(radians(smoothPhase))))/2.0));
}
}