Skip to content

Commit

Permalink
mathieucarbou/MycilaPulseAnalyzer @ 2.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
mathieucarbou committed Sep 19, 2024
1 parent d30ab6e commit 1c60a96
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 66 deletions.
8 changes: 4 additions & 4 deletions lib/MycilaDimmer/MycilaZCD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ extern Mycila::Logger logger;

// Mycila::ZCD

void Mycila::ZCD::begin(const int8_t pin, const uint16_t semiPeriod) {
void Mycila::ZCD::begin(const int8_t pin, const uint32_t semiPeriod) {
if (_enabled)
return;

if (!semiPeriod) {
LOGE(TAG, "Disable Dimmer on pin %" PRId8 ": Invalid semi-period: %" PRIu16 " us", pin, semiPeriod);
LOGE(TAG, "Disable Dimmer on pin %" PRId8 ": Invalid semi-period: %" PRIu32 " us", pin, semiPeriod);
return;
}

Expand All @@ -48,7 +48,7 @@ void Mycila::ZCD::begin(const int8_t pin, const uint16_t semiPeriod) {
return;
}

LOGI(TAG, "Enable Zero-Cross Detection on pin %" PRId8 " with semi-period %" PRIu16 " us", _pin, semiPeriod);
LOGI(TAG, "Enable Zero-Cross Detection on pin %" PRId8 " with semi-period %" PRIu32 " us", _pin, semiPeriod);

// https://github.com/fabianoriccardi/dimmable-light/wiki/Notes-about-specific-architectures#interrupt-issue
Thyristor::semiPeriodShrinkMargin = 400;
Expand All @@ -69,6 +69,6 @@ void Mycila::ZCD::end() {
}
}

uint16_t Mycila::ZCD::getSemiPeriod() const {
uint32_t Mycila::ZCD::getSemiPeriod() const {
return Thyristor::getSemiPeriod();
}
4 changes: 2 additions & 2 deletions lib/MycilaDimmer/MycilaZCD.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
namespace Mycila {
class ZCD {
public:
void begin(const int8_t pin, const uint16_t semiPeriod);
void begin(const int8_t pin, const uint32_t semiPeriod);
void end();

gpio_num_t getPin() const { return _pin; }
bool isEnabled() const { return _enabled; }

uint16_t getSemiPeriod() const;
uint32_t getSemiPeriod() const;

#ifdef MYCILA_JSON_SUPPORT
void zcdToJson(const JsonObject& root) const {
Expand Down
2 changes: 1 addition & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ lib_deps =
mathieucarbou/MycilaLogger @ 3.2.0
mathieucarbou/MycilaMQTT @ 4.2.2
mathieucarbou/MycilaNTP @ 5.0.0
mathieucarbou/MycilaPulseAnalyzer @ 1.0.2
mathieucarbou/MycilaPulseAnalyzer @ 2.0.0
mathieucarbou/MycilaPZEM004Tv3 @ 4.0.7
mathieucarbou/MycilaRelay @ 4.0.1
mathieucarbou/MycilaSystem @ 3.0.3
Expand Down
2 changes: 1 addition & 1 deletion src/Website.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -800,7 +800,7 @@ void YaSolR::WebsiteClass::updateCards() {
_relay2SwitchCount.set(String(relay2.getSwitchCount()).c_str());
_udpMessageRateBuffer.set((String(udpMessageRateBuffer.rate()) + " msg/s").c_str());
_zcdPulsePeriod.set((String(pulseAnalyzer.getPeriod()) + " us").c_str());
_zcdPulseLength.set((String(pulseAnalyzer.getLength()) + " us").c_str());
_zcdPulseLength.set((String(pulseAnalyzer.getWidth()) + " us").c_str());
_time.set(Mycila::Time::getLocalStr().c_str());
_uptime.set(Mycila::Time::toDHHMMSS(Mycila::System::getUptime()).c_str());
#ifdef APP_MODEL_TRIAL
Expand Down
106 changes: 48 additions & 58 deletions src/tasks/ZCD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,94 +5,84 @@
#include <YaSolR.h>

static uint32_t findBestSemiPeriod() {
uint8_t frequency = 0;

// first get frequency from the measurement tools
float frequency = 0;
uint32_t semiPeriod = 0;

// first get res from the measurement tools
Mycila::Grid::Metrics gridMetrics;
grid.getMeasurements(gridMetrics);

if (!frequency)
frequency = round(gridMetrics.frequency);
if (!frequency)
frequency = round(pzemO1.getFrequency());
if (!frequency)
frequency = round(pzemO2.getFrequency());
if (frequency) {
semiPeriod = 1000000 / 2 / frequency;
logger.info(TAG, "Semi-period detected by a measurement device: %" PRIu32 " us", semiPeriod);
return semiPeriod;
}

// otherwise try get frequency from the configuration

if (!frequency)
frequency = config.get(KEY_GRID_FREQUENCY).toInt();

// if a frequency is found, we return its semi-period

// otherwise try get res from the configuration
frequency = config.get(KEY_GRID_FREQUENCY).toInt();
if (frequency) {
logger.debug(TAG, "Semi-period detected from a measurement device: %" PRIu32 " us", static_cast<uint32_t>(1000000 / 2 / frequency));
return 1000000 / 2 / frequency;
semiPeriod = 1000000 / 2 / frequency;
logger.info(TAG, "Semi-period derived from configured frequency: %" PRIu32 " us", semiPeriod);
return semiPeriod;
}

// otherwise use auto-detection
logger.debug(TAG, "Semi-period detected from pulse analyzer: %" PRIu32 " us", pulseAnalyzer.getPeriod());
return pulseAnalyzer.getPeriod();
frequency = round(pulseAnalyzer.getFrequency());
if (frequency) {
semiPeriod = 1000000 / frequency;
logger.info(TAG, "Semi-period detected by pulse analyzer: %" PRIu32 " us", semiPeriod);
return semiPeriod;
}

return 0;
}

Mycila::Task zcdTask("ZCD", [](void* params) {
const bool zcdSwitchedOn = config.getBool(KEY_ENABLE_ZCD);
const Mycila::PulseAnalyzer::State analyzerState = pulseAnalyzer.getState();
uint32_t semiPeriod = 0;
uint32_t delay = 0;

// if the user is asking to disable ZCD, and it is starting or running, we stop it
if (!zcdSwitchedOn) {
if (zcd.isEnabled() || analyzerState != Mycila::PulseAnalyzer::State::IDLE) {
if (!config.getBool(KEY_ENABLE_ZCD)) {
if (zcd.isEnabled() || pulseAnalyzer.isEnabled()) {
logger.warn(TAG, "ZCD disabled, stopping ZCD and PulseAnalyzer");
zcd.end();
pulseAnalyzer.end();
}
return;
}

switch (analyzerState) {
// ZCD switched on, and no analysis is in progress, we start a new one if ZCD is not enabled yet
// Otherwise if ZCD switch is on and ZCD is enabled, system is running and we do nothing
case Mycila::PulseAnalyzer::State::IDLE:
if (!zcd.isEnabled()) {
logger.info(TAG, "ZCD enabled, starting PulseAnalyzer");
pulseAnalyzer.record(config.get(KEY_PIN_ZCD).toInt());
}
return;
// ZCD switch turned on

// if an analysis is in progress, we wait for it to finish
case Mycila::PulseAnalyzer::State::RECORDING:
logger.warn(TAG, "PulseAnalyzer is waiting for ZCD pulses...");
return;
// if ZCD is already enabled, we do nothing
if (zcd.isEnabled())
return;

case Mycila::PulseAnalyzer::State::RECORDED:
logger.info(TAG, "PulseAnalyzer analysis finished, starting ZCD");
pulseAnalyzer.analyze();
pulseAnalyzer.end();
// => ZCD disabled.

semiPeriod = findBestSemiPeriod();
if (!semiPeriod) {
logger.error(TAG, "Cannot start ZCD and Dimmers: unable to determine semi-period");
return;
}
// try to find the semiPeriod
uint32_t semiPeriod = findBestSemiPeriod();

delay = pulseAnalyzer.getLength();
// Support BM1Z102FJ chip where the pulse length will be detected as the semi-period
if (delay > semiPeriod * 8 / 10 && delay < semiPeriod * 12 / 10) {
delay = 0;
}
// if we have a semiPeriod, we start ZCD
if (semiPeriod) {
pulseAnalyzer.end();
zcd.begin(config.get(KEY_PIN_ZCD).toInt(), semiPeriod);
if (zcd.isEnabled()) {
logger.info(TAG, "ZCD started");
dimmer1Task.resume();
dimmer2Task.resume();
}
return;
}

zcd.begin(config.get(KEY_PIN_ZCD).toInt(), semiPeriod);
if (zcd.isEnabled()) {
logger.info(TAG, "ZCD started");
dimmer1Task.resume();
dimmer2Task.resume();
}
return;
// => ZCD switch turned + ZCD disabled + no semiPeriod => we need start analyser or wait for results

default:
return;
if (!pulseAnalyzer.isEnabled()) {
logger.info(TAG, "Starting PulseAnalyzer");
pulseAnalyzer.begin(config.get(KEY_PIN_ZCD).toInt());
return;
}

logger.warn(TAG, "Waiting for ZCD pulse analysis to complete...");
});

0 comments on commit 1c60a96

Please sign in to comment.