@@ -19,6 +19,7 @@ struct APB::Heater::Private {
1919 APB::Heater *q;
2020 Heater::Mode mode{Heater::Mode::off};
2121 float maxDuty;
22+ float minDuty = 0 ;
2223 std::optional<float > temperature;
2324 float targetTemperature;
2425 float dewpointOffset;
@@ -126,20 +127,21 @@ uint8_t APB::Heater::index() const {
126127}
127128
128129
129- bool APB::Heater::setTemperature (float targetTemperature, float maxDuty, float rampOffset) {
130+ bool APB::Heater::setTemperature (float targetTemperature, float maxDuty, float minDuty, float rampOffset) {
130131 if (!this ->temperature ().has_value ()) {
131132 Log.warningln (TEMPERATURE_NOT_FOUND_WARNING_LOG, d->log_scope );
132133 return false ;
133134 }
134135 d->targetTemperature = targetTemperature;
135136 d->maxDuty = maxDuty;
137+ d->minDuty = minDuty;
136138 d->mode = Heater::Mode::target_temperature;
137139 d->rampOffset = rampOffset >= 0 ? rampOffset : 0 ;
138140 d->loop ();
139141 return true ;
140142}
141143
142- bool APB::Heater::setDewpoint (float offset, float maxDuty, float rampOffset) {
144+ bool APB::Heater::setDewpoint (float offset, float maxDuty, float minDuty, float rampOffset) {
143145 if (!this ->temperature ().has_value ()) {
144146 Log.warningln (TEMPERATURE_NOT_FOUND_WARNING_LOG, d->log_scope );
145147 return false ;
@@ -150,6 +152,7 @@ bool APB::Heater::setDewpoint(float offset, float maxDuty, float rampOffset) {
150152 }
151153 d->dewpointOffset = offset;
152154 d->rampOffset = rampOffset >= 0 ? rampOffset : 0 ;
155+ d->minDuty = minDuty;
153156 d->maxDuty = maxDuty;
154157 d->mode = Heater::Mode::dewpoint;
155158 d->loop ();
@@ -178,6 +181,13 @@ std::optional<float> APB::Heater::rampOffset() const {
178181 return {d->rampOffset };
179182}
180183
184+ std::optional<float > APB::Heater::minDuty () const {
185+ if (d->mode != Mode::dewpoint && d->mode != Mode::target_temperature) {
186+ return {};
187+ }
188+ return {d->minDuty };
189+ }
190+
181191std::optional<float > APB::Heater::temperature () const {
182192 return d->temperature ;
183193}
@@ -234,12 +244,13 @@ void APB::Heater::Private::loop()
234244 Log.traceln (" %s current temperature=`%F`" , log_scope, currentTemperature);
235245 if (currentTemperature < dynamicTargetTemperature) {
236246 float rampFactor = rampOffset > 0 ? (dynamicTargetTemperature - currentTemperature)/rampOffset : 1 ;
237- float targetPWM = std::max (0 .f , std::min (1 .f , rampFactor * maxDuty));
238- Log.infoln (" %s - temperature `%F` lower than target temperature `%F`, ramp=`%F` and max PWM is `%F`, ramp factor=`%F`, setting PWM to `%F`" ,
247+ float targetPWM = std::max (0 .f , std::min (1 .f , rampFactor * ( maxDuty-minDuty) + minDuty ));
248+ Log.infoln (" %s - temperature `%F` lower than target temperature `%F`, ramp=`%F` and PWM range is `%F- %F`, ramp factor=`%F`, setting PWM to `%F`" ,
239249 log_scope,
240250 currentTemperature,
241251 dynamicTargetTemperature,
242252 rampOffset,
253+ minDuty,
243254 maxDuty,
244255 rampFactor,
245256 targetPWM
@@ -289,7 +300,7 @@ float APB::Heater::Private::getDuty() const {
289300}
290301
291302void APB::Heater::Private::writePinDuty (float pwm) {
292- int16_t newPWMValue = MAX_PWM * pwm;
303+ int16_t newPWMValue = std::max ( int16_t { 0 }, static_cast < int16_t >( std::min ( MAX_PWM, MAX_PWM * pwm))) ;
293304 if (newPWMValue != pwmValue) {
294305 pwmValue = newPWMValue;
295306 Log.traceln (" %s setting PWM=%d for pin %d" , log_scope, pwmValue, pinout->pwm );
0 commit comments