7#define MYCILA_DIMMER_VERSION "2.1.0"
8#define MYCILA_DIMMER_VERSION_MAJOR 2
9#define MYCILA_DIMMER_VERSION_MINOR 1
10#define MYCILA_DIMMER_VERSION_REVISION 0
12#ifdef MYCILA_JSON_SUPPORT
13 #include <ArduinoJson.h>
17#include <esp32-hal-gpio.h>
24 virtual void begin() = 0;
25 virtual void end() = 0;
26 virtual const char* type()
const = 0;
38 _dutyCycleLimit = _contrain(limit, 0, 1);
39 if (_dutyCycle > _dutyCycleLimit)
50 _dutyCycleMin = _contrain(min, 0, _dutyCycleMax);
61 _dutyCycleMax = _contrain(max, _dutyCycleMin, 1);
98 _powerLUTEnabled =
false;
102 if (semiPeriod > 0) {
104 _semiPeriod = semiPeriod;
107 if (_semiPeriod == 0) {
108 ESP_LOGE(
"MycilaDimmer",
"enablePowerLUT: semiPeriod must be provided or must be already set when enabling power LUT");
110 assert(_semiPeriod > 0);
112 _powerLUTEnabled =
true;
137 bool isOnline()
const {
return _enabled && _online; }
146 _dutyCycleFire = 0.0f;
191 _dutyCycle = _contrain(dutyCycle, 0, _dutyCycleLimit);
195 if (_powerLUTEnabled) {
197 _dutyCycleFire = 0.0f;
198 }
else if (mapped == 1) {
199 _dutyCycleFire = 1.0f;
201 _dutyCycleFire = 1.0f -
static_cast<float>(_lookupFiringDelay(mapped, _semiPeriod)) /
static_cast<float>(_semiPeriod);
204 _dutyCycleFire = mapped;
222 float getDutyCycleMapped()
const {
return _dutyCycleMin + _dutyCycle * (_dutyCycleMax - _dutyCycleMin); }
242 bool readHarmonics(
float* array,
size_t n)
const {
243 if (array ==
nullptr || n == 0)
250 if (_dutyCycleFire <= 0.0f) {
251 for (
size_t i = 0; i < n; i++) {
257 if (_dutyCycleFire >= 1.0f) {
259 for (
size_t i = 1; i < n; i++) {
266 for (
size_t i = 0; i < n; i++) {
272 const float firingAngle = M_PI * (1.0f - _dutyCycleFire);
273 const float sin_2a = sinf(2.0f * firingAngle);
276 const float i1_rms = sqrtf((2.0f / M_PI) * (M_PI - firingAngle + 0.5f * sin_2a));
278 if (i1_rms <= 0.001f)
284 static constexpr float inv_pi_2 = 2.0f / M_PI;
285 static constexpr float inv_sqrt2 = 0.70710678f;
286 const float scale_factor = inv_pi_2 * inv_sqrt2 * 100.0f / i1_rms;
290 for (
size_t i = 1; i < n; i++) {
291 const float n_f =
static_cast<float>(2 * i + 1);
292 const float n_minus_1 = n_f - 1.0f;
293 const float n_plus_1 = n_f + 1.0f;
296 const float coeff = cosf(n_minus_1 * firingAngle) / n_minus_1 -
297 cosf(n_plus_1 * firingAngle) / n_plus_1;
300 array[i] = fabsf(coeff) * scale_factor;
306#ifdef MYCILA_JSON_SUPPORT
312 virtual void toJson(
const JsonObject& root)
const {
313 root[
"type"] = type();
314 root[
"enabled"] = _enabled;
315 root[
"online"] = _online;
316 root[
"state"] =
isOn() ?
"on" :
"off";
317 root[
"duty_cycle"] = _dutyCycle;
319 root[
"duty_cycle_fire"] = _dutyCycleFire;
320 root[
"duty_cycle_limit"] = _dutyCycleLimit;
321 root[
"duty_cycle_min"] = _dutyCycleMin;
322 root[
"duty_cycle_max"] = _dutyCycleMax;
323 root[
"power_lut"] = _powerLUTEnabled;
324 root[
"power_lut_semi_period"] = _semiPeriod;
329 bool _enabled =
false;
330 bool _online =
false;
332 float _dutyCycle = 0.0f;
333 float _dutyCycleFire = 0.0f;
334 float _dutyCycleLimit = 1.0f;
335 float _dutyCycleMin = 0.0f;
336 float _dutyCycleMax = 1.0f;
338 bool _powerLUTEnabled =
false;
339 uint16_t _semiPeriod = 0;
341 static uint16_t _lookupFiringDelay(
float dutyCycle, uint16_t semiPeriod);
343 virtual bool _apply() = 0;
345 static inline float _contrain(
float amt,
float low,
float high) {
346 return (amt < low) ? low : ((amt > high) ? high : amt);
354 virtual void begin() { _enabled =
true; }
355 virtual void end() { _enabled =
false; }
356 virtual const char* type()
const {
return "virtual"; }
359 virtual bool _apply() {
return true; }
363#include "MycilaDimmerDFRobot.h"
364#include "MycilaDimmerPWM.h"
365#include "MycilaDimmerThyristor.h"
void off()
Turn off the dimmer.
float getDutyCycleFire() const
Get the real firing duty cycle applied to the dimmer in the range [0, 1].
bool isOnline() const
Returns true if the dimmer is marked online.
uint16_t getPowerLUTSemiPeriod() const
Get the semi-period in us used for the power LUT calculations. If LUT is disabled,...
float getDutyCycleMax() const
Get the remapped "1" of the dimmer duty cycle.
bool isOn() const
Check if the dimmer is on.
bool isEnabled() const
Check if the dimmer is enabled (if it was able to initialize correctly)
void setDutyCycleMin(float min)
Duty remapping (equivalent to Shelly Dimmer remapping feature). Useful to calibrate the dimmer when u...
float getDutyCycle() const
Get the power duty cycle configured for the dimmer by teh user.
void setOnline(bool online)
Set the online status of the dimmer.
void on()
Turn on the dimmer at full power.
bool isPowerLUTEnabled() const
Check if the power LUT is enabled.
float getDutyCycleLimit() const
Get the power duty cycle limit of the dimmer.
float getDutyCycleMapped() const
Get the remapped power duty cycle from the currently user set duty cycle.
bool setDutyCycle(float dutyCycle)
Set the power duty.
bool isOff() const
Check if the dimmer is off.
bool isOnAtFullPower() const
Check if the dimmer is on at full power.
void enablePowerLUT(bool enable, uint16_t semiPeriod=0)
Enable or disable the use of power LUT for dimmer curve The power LUT provides a non-linear dimming c...
float getDutyCycleMin() const
Get the remapped "0" of the dimmer duty cycle.
void setDutyCycleMax(float max)
Duty remapping (equivalent to Shelly Dimmer remapping feature). Useful to calibrate the dimmer when u...
void setDutyCycleLimit(float limit)
Set the power duty cycle limit of the dimmer. The duty cycle will be clamped to this limit.