From cb07fbf9eee60c43962075615dba5c90104fd95d Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 30 Sep 2024 17:05:55 +0200 Subject: [PATCH] Update dimmer code in preparation for new dimmer library --- lib/MycilaDimmer/MycilaDimmer.cpp | 44 ++++++++++++++++++++++--------- lib/MycilaDimmer/MycilaDimmer.h | 26 +++++++++++------- platformio.ini | 1 + 3 files changed, 49 insertions(+), 22 deletions(-) diff --git a/lib/MycilaDimmer/MycilaDimmer.cpp b/lib/MycilaDimmer/MycilaDimmer.cpp index 982ad00..442ce88 100644 --- a/lib/MycilaDimmer/MycilaDimmer.cpp +++ b/lib/MycilaDimmer/MycilaDimmer.cpp @@ -4,6 +4,25 @@ */ #include +// lock +#include + +// gpio +#include +#include +#include +#include + +// timers +#include + +// logging +#include + +#ifdef MYCILA_PULSE_DEBUG + #include +#endif + #ifdef MYCILA_LOGGER_SUPPORT #include extern Mycila::Logger logger; @@ -33,7 +52,7 @@ extern Mycila::Logger logger; // Minimum delay to reach the voltage required for a gate current of 30mA. // delay_us = asin((gate_resistor * gate_current) / grid_volt_max) / pi * period_us // delay_us = asin((330 * 0.03) / 325) / pi * 10000 = 97us -#define PHASE_DELAY_MIN_US (100) +#define PHASE_DELAY_MIN_US (90) #define TABLE_PHASE_LEN (80U) @@ -41,15 +60,6 @@ static const uint32_t DIMMER_MAX = (1 << MYCILA_DIMMER_RESOLUTION) - 1; static const uint32_t TABLE_PHASE_SCALE = (TABLE_PHASE_LEN - 1U) * (1UL << (16 - MYCILA_DIMMER_RESOLUTION)); static const uint16_t TABLE_PHASE_DELAY[TABLE_PHASE_LEN] PROGMEM = {0xefea, 0xdfd4, 0xd735, 0xd10d, 0xcc12, 0xc7cc, 0xc403, 0xc094, 0xbd6a, 0xba78, 0xb7b2, 0xb512, 0xb291, 0xb02b, 0xaddc, 0xaba2, 0xa97a, 0xa762, 0xa557, 0xa35a, 0xa167, 0x9f7f, 0x9da0, 0x9bc9, 0x99fa, 0x9831, 0x966e, 0x94b1, 0x92f9, 0x9145, 0x8f95, 0x8de8, 0x8c3e, 0x8a97, 0x88f2, 0x8750, 0x85ae, 0x840e, 0x826e, 0x80cf, 0x7f31, 0x7d92, 0x7bf2, 0x7a52, 0x78b0, 0x770e, 0x7569, 0x73c2, 0x7218, 0x706b, 0x6ebb, 0x6d07, 0x6b4f, 0x6992, 0x67cf, 0x6606, 0x6437, 0x6260, 0x6081, 0x5e99, 0x5ca6, 0x5aa9, 0x589e, 0x5686, 0x545e, 0x5224, 0x4fd5, 0x4d6f, 0x4aee, 0x484e, 0x4588, 0x4296, 0x3f6c, 0x3bfd, 0x3834, 0x33ee, 0x2ef3, 0x28cb, 0x202c, 0x1016}; -static uint16_t _lookupPhaseDelay(uint32_t duty, uint16_t period) { - uint32_t slot = duty * TABLE_PHASE_SCALE + (TABLE_PHASE_SCALE >> 1); - uint16_t index = slot >> 16; - uint32_t a = TABLE_PHASE_DELAY[index]; - uint32_t b = TABLE_PHASE_DELAY[index + 1]; - uint32_t delay = a - (((a - b) * (slot & 0xffff)) >> 16); // interpolate a b - return (delay * period) >> 16; // scale to period -} - void Mycila::Dimmer::begin(int8_t pin, uint32_t semiPeriod) { if (_enabled) return; @@ -70,9 +80,9 @@ void Mycila::Dimmer::begin(int8_t pin, uint32_t semiPeriod) { LOGI(TAG, "Enable Dimmer on pin %" PRId8 " with semi-period %" PRIu32 " us", pin, semiPeriod); _semiPeriod = semiPeriod; - _dimmer = new Thyristor(_pin); pinMode(_pin, OUTPUT); digitalWrite(_pin, LOW); + _dimmer = new Thyristor(_pin); _enabled = true; // restart with last saved value @@ -110,7 +120,7 @@ void Mycila::Dimmer::setDutyCycle(float newDutyCycle) { } else if (mappedDutyCycle == 1) { _delay = PHASE_DELAY_MIN_US; } else { - _delay = _lookupPhaseDelay(mappedDutyCycle * DIMMER_MAX, _semiPeriod); + _delay = _lookupPhaseDelay(mappedDutyCycle); } _dimmer->setDelay(_delay); @@ -134,3 +144,13 @@ void Mycila::Dimmer::setDutyCycleMax(float max) { LOGD(TAG, "Set dimmer %" PRId8 " duty cycle max to %f", _pin, _dutyCycleMax); setDutyCycle(_dutyCycle); } + +uint32_t Mycila::Dimmer::_lookupPhaseDelay(float dutyCycle) { + uint32_t duty = dutyCycle * DIMMER_MAX; + uint32_t slot = duty * TABLE_PHASE_SCALE + (TABLE_PHASE_SCALE >> 1); + uint32_t index = slot >> 16; + uint32_t a = TABLE_PHASE_DELAY[index]; + uint32_t b = TABLE_PHASE_DELAY[index + 1]; + uint32_t delay = a - (((a - b) * (slot & 0xffff)) >> 16); // interpolate a b + return (delay * _semiPeriod) >> 16; // scale to period +} diff --git a/lib/MycilaDimmer/MycilaDimmer.h b/lib/MycilaDimmer/MycilaDimmer.h index 48d7b59..7363824 100644 --- a/lib/MycilaDimmer/MycilaDimmer.h +++ b/lib/MycilaDimmer/MycilaDimmer.h @@ -4,13 +4,13 @@ */ #pragma once -#include -#include - #ifdef MYCILA_JSON_SUPPORT #include #endif +#include +#include + /** * Optional resolution, 15bits max */ @@ -18,6 +18,10 @@ #define MYCILA_DIMMER_RESOLUTION 12 #endif +#ifndef MYCILA_DIMMER_MAX_COUNT + #define MYCILA_DIMMER_MAX_COUNT 1 +#endif + namespace Mycila { class Dimmer { public: @@ -90,17 +94,17 @@ namespace Mycila { /** * @brief Check if the dimmer is off */ - bool isOff() const { return _dutyCycle <= _dutyCycleMin; } + bool isOff() const { return getDutyCycle() <= getDutyCycleMin(); } /** * @brief Check if the dimmer is on */ - bool isOn() const { return _dutyCycle > _dutyCycleMin; } + bool isOn() const { return getDutyCycle() > getDutyCycleMin(); } /** * @brief Check if the dimmer is on at full power */ - bool isOnAtFullPower() const { return _dutyCycle >= _dutyCycleMax; } + bool isOnAtFullPower() const { return getDutyCycle() >= getDutyCycleMax(); } /** * @brief Set the power duty @@ -154,11 +158,10 @@ namespace Mycila { /** * @brief Get the firing delay in us of the dimmer in the range [0, semi-period] - * At 0% power, delay is equal to the semi-period. - * At 100% power, the delay is 0 us - * If the firing delay is UINT32_MAX, the dimmer is off + * At 0% power, delay is equal to the semi-period: the dimmer is kept off + * At 100% power, the delay is 0 us: the dimmer is kept on */ - uint32_t getFiringDelay() const { return _delay; } + uint32_t getFiringDelay() const { return _delay > _semiPeriod ? _semiPeriod : _delay; } /** * @brief Get the phase angle in radians of the dimmer in the range [0, PI] @@ -176,6 +179,9 @@ namespace Mycila { float _dutyCycleMin = 0; float _dutyCycleMax = 1; uint32_t _delay = UINT32_MAX; + + uint32_t _lookupPhaseDelay(float dutyCycle); + Thyristor* _dimmer = nullptr; }; } // namespace Mycila diff --git a/platformio.ini b/platformio.ini index 59184f2..89d5f76 100644 --- a/platformio.ini +++ b/platformio.ini @@ -106,6 +106,7 @@ build_flags = -D MYCILA_LOGGER_SUPPORT ; ZC event is centered at the middle the pulse. Make sure it is triggered before in order to have time to stop the triacs -D MYCILA_PULSE_ZC_SHIFT_US=-100 + -D MYCILA_DIMMER_MAX_COUNT=2 ; ESPConnect ; -D ESPCONNECT_NO_MDNS ; MQTT