Skip to content

Commit

Permalink
Update dimmer code in preparation for new dimmer library
Browse files Browse the repository at this point in the history
  • Loading branch information
mathieucarbou committed Sep 30, 2024
1 parent efc0a37 commit cb07fbf
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 22 deletions.
44 changes: 32 additions & 12 deletions lib/MycilaDimmer/MycilaDimmer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,25 @@
*/
#include <MycilaDimmer.h>

// lock
#include <freertos/FreeRTOS.h>

// gpio
#include <driver/gpio.h>
#include <esp32-hal-gpio.h>
#include <hal/gpio_ll.h>
#include <soc/gpio_struct.h>

// timers
#include <inlined_gptimer.h>

// logging
#include <esp32-hal-log.h>

#ifdef MYCILA_PULSE_DEBUG
#include <rom/ets_sys.h>
#endif

#ifdef MYCILA_LOGGER_SUPPORT
#include <MycilaLogger.h>
extern Mycila::Logger logger;
Expand Down Expand Up @@ -33,23 +52,14 @@ 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)

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;
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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
}
26 changes: 16 additions & 10 deletions lib/MycilaDimmer/MycilaDimmer.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,24 @@
*/
#pragma once

#include <esp32-hal-gpio.h>
#include <thyristor.h>

#ifdef MYCILA_JSON_SUPPORT
#include <ArduinoJson.h>
#endif

#include <esp32-hal-gpio.h>
#include <thyristor.h>

/**
* Optional resolution, 15bits max
*/
#ifndef MYCILA_DIMMER_RESOLUTION
#define MYCILA_DIMMER_RESOLUTION 12
#endif

#ifndef MYCILA_DIMMER_MAX_COUNT
#define MYCILA_DIMMER_MAX_COUNT 1
#endif

namespace Mycila {
class Dimmer {
public:
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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]
Expand All @@ -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
1 change: 1 addition & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit cb07fbf

Please sign in to comment.