
A comprehensive ESP32/Arduino library for controlling AC power devices including TRIACs, SSRs, and voltage regulators through multiple dimming methods.

Table of Contents
- Table of Contents
- Overview
- Features
- Hardware Support
- Supported Platforms
- Supported Hardware
- Installation
- Quick Start
- Dimmer Types
- Zero-Cross Dimmer
- PWM Dimmer
- DFRobot DAC Dimmer
- Understanding AC Dimming Methods
- Dimming Method Comparison
- Phase Control
- Burst Fire on Full Period
- Burst Fire on Semi-Period
- Stochastic Burst Fire (Coming Soon)
- Recommendations for Harmonic Mitigation (Phase Control)
- Current MycilaDimmer Support
- Choosing the Right Method
- API Reference
- Common API (All Dimmer Types)
- Zero-Cross Dimmer Specific
- PWM Dimmer Specific
- DFRobot DAC Dimmer Specific
- Advanced Features
- Configuration
- Examples
- Build Configuration
- PlatformIO Configuration
- Dependencies
- Troubleshooting
- Contributing
- License
- Disclaimer
Overview
MycilaDimmer provides a unified interface for controlling AC power devices through different hardware implementations. The library uses a polymorphic architecture that allows you to switch between different dimming methods without changing your application code.
Key Benefits:
- Unified API - Same interface for all dimmer types
- IRAM Safe - Interrupt handlers work during flash operations
- Hardware Agnostic - Supports multiple hardware approaches
- Production Ready - Used in YaSolR Solar Router
Features
- ✨ Flicker-Free Dimming: Progressive dimming without flickering using precise DAC control or zero-cross detection with quality ZCD circuits
- 🎛️ Multiple Control Methods: Zero-cross detection, PWM, and I2C DAC
- ⚡ High Performance: IRAM-safe interrupt handlers with lookup table optimization
- 💡 Selectable Dimming Curves: Choose between linear dimming or Power LUT for perceptual brightness matching - switch at runtime based on your needs
- � Flexible Configuration: Duty cycle remapping, calibration, and user-selectable dimming modes
- 📊 Rich Telemetry: Duty cycle measurements, firing ratios, and online status
- 🛡️ Safety Features: Duty cycle limits and grid connection detection
- 📱 JSON Integration: Optional ArduinoJson support for telemetry
- 🔄 Real-time Control: Microsecond-precision timing control
Hardware Support
Supported Platforms
- ESP32 (all variants: ESP32, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6, ESP32-H2)
- Arduino Framework via PlatformIO or Arduino IDE
Supported Hardware
- TRIACs with zero-cross detection circuits
- Random Solid State Relays (SSRs)
- Voltage Regulators with 0-10V control (LSA, LCTC, etc)
- DFRobot DAC Modules (GP8211S, GP8413, GP8403)
Installation
PlatformIO
[env:myproject]
lib_deps =
mathieucarbou/MycilaDimmer
Arduino IDE
- Go to Sketch → Include Library → Manage Libraries
- Search for "MycilaDimmer"
- Install the library by Mathieu Carbou
Quick Start
#include <MycilaDimmer.h>
void setup() {
}
void loop() {
for (float power = 0.0; power <= 1.0; power += 0.1) {
delay(1000);
}
}
bool setDutyCycle(float dutyCycle)
Set the power duty.
void setPin(gpio_num_t pin)
Set the GPIO pin to use for the dimmer.
virtual void begin()
Enable a dimmer on a specific GPIO pin.
Dimmer Types
Zero-Cross Dimmer
Perfect for TRIAC and Random SSR control with flicker-free progressive dimming. Achieves smooth, continuous power control through precise phase angle control when paired with quality zero-cross detection circuits.
#include <MycilaDimmer.h>
void setup() {
}
virtual void begin()
Enable a dimmer on a specific GPIO pin.
static void onZeroCross(int16_t delayUntilZero, void *args)
void setPin(gpio_num_t pin)
Set the GPIO pin to use for the dimmer.
void setSemiPeriod(uint16_t semiPeriod)
Set the semi-period of the grid frequency in us. It cannot be zero and it is required for proper dimm...
Features:
- Flicker-free dimming: Smooth progressive control without visible flickering
- Microsecond-precision phase angle control
- Lookup table with linear interpolation for seamless transitions
- IRAM-safe interrupt handlers
- Supports several zero-cross detection circuits:
The Zero-Cross Detector mounted on DIN Rail mount from Daniel is is very good and reliable. I sometimes buy it in bulk from PCBWay. If you want one, you can have a look at the YaSolR Pro page for the stock status.
PWM Dimmer
Standard PWM output for SSRs and other PWM-controlled devices.
#include <MycilaDimmer.h>
void setup() {
}
void setResolution(uint8_t resolution)
Set the PWM resolution in bits.
void setFrequency(uint32_t frequency)
Set the PWM frequency in Hz.
Features:
- Configurable frequency (default: 1kHz)
- Configurable resolution (default: 12-bit)
- Automatic PWM channel management
For example, this dimmer can be used with a 3.3V to 0-5V/0-10V signal converter
DFRobot DAC Dimmer
Flicker-free progressive dimming using precision I2C DAC modules. Perfect for voltage regulator controlled devices (LSA, LCTC, etc) with 0-10V input, providing ultra-smooth dimming without any visible flickering thanks to high-resolution DAC output.
#include <MycilaDimmer.h>
void setup() {
dimmer.setSKU(Mycila::DFRobotDimmer::SKU::DFR1071_GP8211S);
dimmer.
setOutput(Mycila::DFRobotDimmer::Output::RANGE_0_10V);
}
void setDeviceAddress(uint8_t deviceAddress)
I2C address of the device.
void setOutput(Output output)
Set output mode of the device: 0-5V or 0-10V.
virtual void begin()
Enable a dimmer on a specific GPIO pin.
Supported Models:
- DFR0971 (GP8403): 12-bit, dual channel, 0-5V/10V
- DFR1071 (GP8211S): 15-bit, single channel, 0-5V/10V
- DFR1073 (GP8413): 15-bit, dual channel, 0-5V/10V
Here is a comparison table of the different DFRobot DAC modules.
Understanding AC Dimming Methods
When controlling AC power devices like TRIACs, SSRs, and voltage regulators, there are several dimming approaches available. Each method has specific characteristics, advantages, and limitations that affect precision, grid compatibility, and regulatory compliance.
Dimming Method Comparison
Phase Control
How it works: Controls power by delaying the firing angle within each AC semi-period (twice per cycle). The TRIAC/SSR activates at a specific point in the sine wave, "chopping" the waveform to deliver partial power.
Advantages:
- ✅ High Precision: Can adjust power at each semi-period (every 10ms for 50Hz), enabling watt-level control
- ✅ Fast Response: Instant power adjustment with no delay
- ✅ Accurate Power Control: With Power LUT, achieves predictable power output matching the desired level
- ✅ Regulatory Compliant: Keeps grid balanced (no DC component) when properly implemented
- ✅ Widely Used: Standard method in commercial dimmers and variable speed drives
Limitations:
- ⚠️ Harmonics: Generates harmonic distortion, especially at 50% power (90° phase angle)
- Harmonics are regulated by CEI 61000-3-2 (Class A devices)
- H3 (3rd harmonic) is the most significant, exceeds limits at 50% dimming with ~1700W nominal load
- H15 (15th harmonic) first to exceed limits at ~760W nominal load (but less significant than H3)
- Maximum compliant load: ~800W without mitigation
- Maximum significant load: ~1700W
- ⚠️ Mitigation may be required: May need RC snubbers, proper wiring, load management, or limiter settings
MycilaDimmer Implementation:
- All three implementations (ZeroCrossDimmer, PWMDimmer, DFRobotDimmer) use phase control
- ZeroCrossDimmer: Direct TRIAC/Random SSR control with zero-cross detection
- PWMDimmer: Generates PWM signal for converter for voltage regulators (LSA, LCTC) which perform internal phase control
- DFRobotDimmer: Outputs 0-10V analog signal to voltage regulators (LSA, LCTC) which perform internal phase control
Burst Fire on Full Period
How it works: Rapidly switches complete AC cycles on/off (20ms periods for 50Hz). For example, to achieve 50% power, alternates full power for 1 second, then off for 1 second.
Advantages:
- ✅ No Harmonics: Preserves complete sine waves, generates minimal harmonic distortion
- ✅ Simple Implementation: Basic on/off switching logic
- ✅ Compatible with Zero-Cross SSRs: Can use simpler, cheaper SSRs
Limitations:
- ❌ Flickering: Visible light flicker and voltage fluctuations affecting nearby devices
- Caused by sudden high current draw creating voltage drops
- Impacts micro-inverters and other sensitive electronics
- ❌ Slow Response: Limited precision due to coarse time slots
- 50 slots in 1-second window for 50Hz = 60W resolution for 3000W load
- Longer windows reduce precision; shorter windows worsen flickering
- ❌ Heat Dissipation: Rapid switching generates more heat in SSR
- ❌ Poor Accuracy: Cannot achieve watt-level control precision
- ❌ Delayed Corrections: By the time adjustment is applied, conditions may have changed
Burst Fire on Semi-Period
How it works: Switches at semi-period level (every 10ms for 50Hz) to double the control slots and improve response time.
Advantages:
- ✅ Better Resolution: Twice as many control slots compared to full-period burst fire
- ✅ Faster Response: 2x quicker than full-period burst fire
Limitations:
- ❌ All Full-Period Limitations: Still suffers from flickering, heat, and inaccuracy
- ❌ DC Component - FORBIDDEN: Critical regulatory violation
- At 50% power, may turn off negative semi-periods (1 second), then positive semi-periods (1 second)
- Creates dangerous DC components on AC grid (current asymmetry drawn only one side of the waveform for a short time)
- Unbalances grid network by drawing current asymmetrically
- Violates electrical regulations - this method should not be used
- ❌ Grid Instability: Causes phase imbalance and potential equipment damage
Regulatory Note: Creating DC components on AC power grids is explicitly forbidden by electrical regulations. Many routers implement this method unknowingly, creating compliance and safety issues.
Stochastic Burst Fire (Coming Soon)
How it works: Probabilistic full-wave switching at each zero-cross. At each AC cycle, generates a random number (0-100) and compares it to the desired power level percentage. If the random number is lower, the full wave is allowed through; otherwise, it's blocked.
Advantages:
- ✅ No DC Component: Always switches at zero-cross on full waves, maintains grid balance
- ✅ Eliminates Periodic Flickering: Random distribution prevents visible periodic patterns
- ✅ Minimal EMF Interference: Zero-cross switching reduces electromagnetic interference
- ✅ Multi-Channel Safe: Random switching prevents simultaneous current spikes across channels
- ✅ Even Distribution: Over time, produces statistically accurate power output
- ✅ No Harmonics: Preserves complete sine waves like traditional burst fire
Limitations:
- ⚠️ Less Precise: Statistical accuracy over time, not instant watt-level precision
- ⚠️ Requires More Cycles: Needs multiple AC cycles to reach target power level
- ⚠️ Not for Fast-Response Systems: Better suited for thermal/heating applications with slower dynamics
Use Cases:
- Multi-channel heating systems
- Temperature control with PID regulation
- Applications where eliminating flicker is more important than instant precision
- Systems sensitive to EMF interference
Regulatory Note: Creating DC components on AC power grids is explicitly forbidden by electrical regulations. Many routers implement this method unknowingly, creating compliance and safety issues.
Recommendations for Harmonic Mitigation (Phase Control)
When using phase control, harmonics can be reduced through several approaches:
- Power Limiter: Limit dimmer (in example to 40% of nominal load)
- Reduced Load: Use lower wattage resistance (e.g., 1000W @ 53Ω instead of 3000W @ 18Ω)
- Proper Wiring: Minimize cable length, use appropriate wire gauge
- Strategic Placement: Position router close to grid entry/exit point
- Stepped Loads: Use multiple resistances with relays (e.g., 3x 800W elements)
- RC Snubbers: 100Ω 100nF snubbers can help with sensitive equipment
- Power LUT: Use perceptual power curve to reduce time spent at problematic phase angles
Current MycilaDimmer Support
Currently Supported (Phase Control):
- ✅ ZeroCrossDimmer - TRIAC/Random SSR with zero-cross detection
- ✅ PWMDimmer - PWM output for voltage regulators (LSA, LCTC)
- ✅ DFRobotDimmer - I2C DAC for voltage regulators (LSA, LCTC)
Coming Soon:
- 🚧 Stochastic Burst Fire (Full Period) - For Zero-Cross SSR compatibility
- Novel probabilistic approach: At each zero-cross, generates random number (0-100) and compares to desired power level
- Smart distribution: If random number < desired power, relay switches on; otherwise switches off
- Key advantages over traditional burst fire:
- Eliminates periodic flickering through randomized switching pattern
- Prevents simultaneous high current draw across multiple channels
- Evenly distributed full-wave switching over time
- No DC component - maintains grid balance
- Reduces EMF interference by switching only at zero-cross
- Trade-offs: Less precise than phase control but safer and more grid-friendly
- Ideal for: Multi-channel heating applications, temperature control systems
- Based on proven StochasticHeatController implementation
Choosing the Right Method
For Solar Routers & High-Precision Applications:
- Use Phase Control with appropriate harmonic mitigation
- Provides best accuracy and response time
- Essential for PV routing where precise power matching is critical
For Simple On/Off Control:
- Consider Zero-Cross SSR with simple relay control
- Suitable when precise dimming is not required
- No harmonics, but no variable power control
Resources:
API Reference
Common API (All Dimmer Types)
void begin();
void end();
const char* type() const;
void on();
void off();
bool setDutyCycle(float dutyCycle);
bool isEnabled() const;
bool isOnline() const;
void setOnline(bool online);
bool isOn() const;
bool isOff() const;
bool isOnAtFullPower() const;
void setDutyCycleMin(float min);
void setDutyCycleMax(float max);
void setDutyCycleLimit(float limit);
float getDutyCycle() const;
float getDutyCycleMapped() const;
float getDutyCycleLimit() const;
float getDutyCycleMin() const;
float getDutyCycleMax() const;
void enablePowerLUT(bool enable, uint16_t semiPeriod = 0);
bool isPowerLUTEnabled() const;
uint16_t getPowerLUTSemiPeriod() const;
float getDutyCycleFire() const;
#ifdef MYCILA_JSON_SUPPORT
void toJson(const JsonObject& root) const;
#endif
Zero-Cross Dimmer Specific
void setPin(gpio_num_t pin);
void setSemiPeriod(uint16_t semiPeriod);
static void onZeroCross(int16_t delayUntilZero, void* arg);
PWM Dimmer Specific
void setPin(gpio_num_t pin);
void setFrequency(uint32_t frequency);
void setResolution(uint8_t resolution);
DFRobot DAC Dimmer Specific
void setWire(TwoWire& wire);
void setSKU(SKU sku);
void setOutput(Output output);
void setDeviceAddress(uint8_t addr);
void setChannel(uint8_t channel);
Advanced Features
#ifdef MYCILA_JSON_SUPPORT
JsonDocument doc;
dimmer.toJson(doc.to<JsonObject>());
serializeJson(doc, Serial);
#endif
void setDutyCycleMin(float min)
Duty remapping (equivalent to Shelly Dimmer remapping feature). Useful to calibrate the dimmer when u...
void setOnline(bool online)
Set the online status of the dimmer.
bool isPowerLUTEnabled() const
Check if the power LUT is enabled.
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...
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.
Configuration
Build Flags
For Zero-Cross Dimmer (IRAM safety):
build_flags =
-D CONFIG_ARDUINO_ISR_IRAM=1
-D CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=1
-D CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM=1
-D CONFIG_GPTIMER_ISR_IRAM_SAFE=1
-D CONFIG_GPIO_CTRL_FUNC_IN_IRAM=1
lib_deps =
mathieucarbou/MycilaPulseAnalyzer
For JSON Support:
build_flags =
-D MYCILA_JSON_SUPPORT
lib_deps =
bblanchon/ArduinoJson
Examples
The library includes comprehensive examples:
Build Configuration
PlatformIO Configuration
[platformio]
lib_dir = .
src_dir = examples/ZeroCross ; or DAC, PWM, etc.
[env]
framework = arduino
board = esp32dev
build_flags =
-D CONFIG_ARDUHAL_LOG_COLORS
-D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
-Wall -Wextra
; Zero-Cross specific flags
-D CONFIG_ARDUINO_ISR_IRAM=1
-D CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=1
-D CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM=1
-D CONFIG_GPTIMER_ISR_IRAM_SAFE=1
-D CONFIG_GPIO_CTRL_FUNC_IN_IRAM=1
lib_deps =
bblanchon/ArduinoJson
mathieucarbou/MycilaPulseAnalyzer
Dependencies
Troubleshooting
Common Issues
Zero-Cross Dimmer Not Working
- Ensure IRAM build flags are set
- Check semi-period is configured (setSemiPeriod())
- Verify zero-cross signal is connected and working
PWM Output Not Visible
- Check GPIO pin configuration
- Verify PWM frequency and resolution settings
- Use oscilloscope or LED to test output
DFRobot Module Not Responding
- Verify I2C wiring (SDA, SCL, power, ground)
- Check device address with I2C scanner
- Ensure correct SKU is configured
Contributing
- Fork the repository
- Create a feature branch (git checkout -b feature/amazing-feature)
- Commit your changes (‘git commit -m 'Add amazing feature’)
- Push to the branch (git push origin feature/amazing-feature`)
- Open a Pull Request
Development Setup
git clone https://github.com/mathieucarbou/MycilaDimmer.git
cd MycilaDimmer
pio run
License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
Disclaimer
This website is provided for informational purposes only. By accessing this site and using the information contained herein, you accept the terms set forth in this disclaimer.
- Accuracy of Information: We strive to provide accurate and up-to-date information on this site, but we cannot guarantee the completeness or accuracy of this information. The information provided is subject to change without notice.
- Use of Information: Use of the information provided on this site is at your own risk. *We decline all responsibility for the consequences arising from the use of this information. It is recommended that you consult a competent professional for advice specific to your situation.
- External Links: This site may contain links to external websites which are provided for your reference and convenience. We have no control over the content of these external sites and we accept no responsibility for their content and their use.
- Limitation of Liability: To the fullest extent permitted by applicable law, we disclaim all liability for any direct, indirect, incidental, consequential or special damages arising out of the use of, or inability to use, this website, even if we have been advised of the possibility of such damage.
By using this site, you agree to hold harmless the owners, administrators and authors of this site from any claims arising from your use of this website. If you do not agree to these terms, please do not use this site.
Author: Mathieu Carbou
Used in: YaSolR Solar Router