Merge pull request #8160 from s-hadinger/dimmerrange_pwm

Add ``DimmerRange`` for PWM lights (#8120)
This commit is contained in:
Theo Arends 2020-04-13 21:31:04 +02:00 committed by GitHub
commit 4ff2e5d2c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 9 deletions

View File

@ -31,6 +31,7 @@
- Add support for AS3935 Lightning Sensor by device111 (#8130) - Add support for AS3935 Lightning Sensor by device111 (#8130)
- Fix prevent multiple pings to run concurrently - Fix prevent multiple pings to run concurrently
- Fix Scheme 2-4 brightness when SetOption68 1 (#8058) - Fix Scheme 2-4 brightness when SetOption68 1 (#8058)
- Add ``DimmerRange`` for PWM lights (#8120)
### 8.2.0.2 20200328 ### 8.2.0.2 20200328

View File

@ -293,6 +293,9 @@ struct LIGHT {
uint16_t fade_end_10[LST_MAX]; // 10 bits resolution target channel values uint16_t fade_end_10[LST_MAX]; // 10 bits resolution target channel values
uint16_t fade_duration = 0; // duration of fade in milliseconds uint16_t fade_duration = 0; // duration of fade in milliseconds
uint32_t fade_start = 0; // fade start time in milliseconds, compared to millis() uint32_t fade_start = 0; // fade start time in milliseconds, compared to millis()
uint16_t pwm_min = 0; // minimum value for PWM, from DimmerRange, 0..1023
uint16_t pwm_max = 1023; // maxumum value for PWM, from DimmerRange, 0..1023
} Light; } Light;
power_t LightPower(void) power_t LightPower(void)
@ -1270,6 +1273,25 @@ bool LightModuleInit(void)
return (light_type > LT_BASIC); return (light_type > LT_BASIC);
} }
// compute actual PWM min/max values from DimmerRange
// must be called when DimmerRange is changed or LedTable
void LightCalcPWMRange(void) {
uint16_t pwm_min, pwm_max;
pwm_min = change8to10(LightStateClass::DimmerToBri(Settings.dimmer_hw_min)); // default 0
pwm_max = change8to10(LightStateClass::DimmerToBri(Settings.dimmer_hw_max)); // default 100
if (Settings.light_correction) {
pwm_min = ledGamma10_10(pwm_min); // apply gamma correction
pwm_max = ledGamma10_10(pwm_max); // 0..1023
}
pwm_min = pwm_min > 0 ? changeUIntScale(pwm_min, 1, 1023, 1, Settings.pwm_range) : 0; // adapt range but keep zero and non-zero values
pwm_max = changeUIntScale(pwm_max, 1, 1023, 1, Settings.pwm_range); // pwm_max cannot be zero
Light.pwm_min = pwm_min;
Light.pwm_max = pwm_max;
//AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("LightCalcPWMRange %d %d - %d %d"), Settings.dimmer_hw_min, Settings.dimmer_hw_max, Light.pwm_min, Light.pwm_max);
}
void LightInit(void) void LightInit(void)
{ {
Light.device = devices_present; Light.device = devices_present;
@ -1291,6 +1313,7 @@ void LightInit(void)
// if RGBW or RGBCW, and SetOption37 >= 128, we manage RGB and W separately // if RGBW or RGBCW, and SetOption37 >= 128, we manage RGB and W separately
Light.device--; // we take the last two devices as lights Light.device--; // we take the last two devices as lights
} }
LightCalcPWMRange();
#ifdef DEBUG_LIGHT #ifdef DEBUG_LIGHT
AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightInit Light.pwm_multi_channels=%d Light.subtype=%d Light.device=%d devices_present=%d", AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightInit Light.pwm_multi_channels=%d Light.subtype=%d Light.device=%d devices_present=%d",
Light.pwm_multi_channels, Light.subtype, Light.device, devices_present); Light.pwm_multi_channels, Light.subtype, Light.device, devices_present);
@ -1904,13 +1927,9 @@ void LightAnimate(void)
} }
// final adjusments for PMW, post-gamma correction // final adjusments for PMW, post-gamma correction
uint16_t min = 1;
#ifdef USE_PWM_DIMMER
if (PWM_DIMMER == my_module_type) min = Settings.dimmer_hw_min;
#endif // USE_PWM_DIMMER
for (uint32_t i = 0; i < LST_MAX; i++) { for (uint32_t i = 0; i < LST_MAX; i++) {
// scale from 0..1023 to 0..pwm_range, but keep any non-zero value to at least 1 // scale from 0..1023 to 0..pwm_range, but keep any non-zero value to at least 1
cur_col_10[i] = (cur_col_10[i] > 0) ? changeUIntScale(cur_col_10[i], 1, 1023, min, Settings.pwm_range) : 0; cur_col_10[i] = (cur_col_10[i] > 0) ? changeUIntScale(cur_col_10[i], 1, 1023, 1, Settings.pwm_range) : 0;
} }
// apply port remapping on both 8 bits and 10 bits versions // apply port remapping on both 8 bits and 10 bits versions
@ -2085,7 +2104,9 @@ void LightSetOutputs(const uint16_t *cur_col_10) {
for (uint32_t i = 0; i < (Light.subtype - Light.pwm_offset); i++) { for (uint32_t i = 0; i < (Light.subtype - Light.pwm_offset); i++) {
if (pin[GPIO_PWM1 +i] < 99) { if (pin[GPIO_PWM1 +i] < 99) {
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Cur_Col%d 10 bits %d"), i, cur_col_10[i]); //AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Cur_Col%d 10 bits %d"), i, cur_col_10[i]);
analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - cur_col_10[(i + Light.pwm_offset)] : cur_col_10[(i + Light.pwm_offset)]); uint16_t cur_col = cur_col_10[i + Light.pwm_offset];
cur_col = cur_col > 0 ? changeUIntScale(cur_col, 0, Settings.pwm_range, Light.pwm_min, Light.pwm_max) : 0; // shrink to the range of pwm_min..pwm_max
analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - cur_col : cur_col);
} }
} }
} }
@ -2742,9 +2763,8 @@ void CmndDimmerRange(void)
Settings.dimmer_hw_min = parm[1]; Settings.dimmer_hw_min = parm[1];
Settings.dimmer_hw_max = parm[0]; Settings.dimmer_hw_max = parm[0];
} }
#ifdef ESP8266 LightCalcPWMRange();
if (PWM_DIMMER != my_module_type) restart_flag = 2; Light.update = true;
#endif // ESP8266
} }
Response_P(PSTR("{\"" D_CMND_DIMMER_RANGE "\":{\"Min\":%d,\"Max\":%d}}"), Settings.dimmer_hw_min, Settings.dimmer_hw_max); Response_P(PSTR("{\"" D_CMND_DIMMER_RANGE "\":{\"Min\":%d,\"Max\":%d}}"), Settings.dimmer_hw_min, Settings.dimmer_hw_max);
} }
@ -2765,6 +2785,7 @@ void CmndLedTable(void)
Settings.light_correction ^= 1; Settings.light_correction ^= 1;
break; break;
} }
LightCalcPWMRange();
Light.update = true; Light.update = true;
} }
ResponseCmndStateText(Settings.light_correction); ResponseCmndStateText(Settings.light_correction);