Passa al contenuto

Multi-Channel AC Dimmer Control: 2CH and 4CH Guide

Need to control two or four AC loads independently from one board? Multi-channel dimmer modules share a single zero-cross input but give each load its own DIM pin — here is the wiring and code.

TL;DR: 2CH 8A and 4CH 10A modules share one ZC pin across all channels. Each channel has its own DIM pin. One interrupt call in code covers all channels; brightness is set independently per channel handle. Use rbdimmerESP32 on dual-core ESP32, RBDdimmer on Arduino/ESP8266.



What Multi-Channel Modules Provide

Module Channels Max per channel Shared
2CH 8A 2 8A / ~1 300W at 220V ZC pin, AC-N
4CH 10A 4 10A / ~1 700W at 220V ZC pin, AC-N

Each channel controls one AC load independently. The zero-cross detector is shared — one MCU interrupt services all channels.



Wiring


2CH 8A — pin assignments

text
Module   →   MCU (ESP32 example)
────────────────────────────────
ZC-OUT   →   GPIO 4   (interrupt, any GPIO on ESP32)
DIM1     →   GPIO 16  (channel 1)
DIM2     →   GPIO 17  (channel 2)
VCC      →   3.3V
GND      →   GND

AC side: both channels share the neutral (AC-N). Each channel has its own AC L-IN and AC L-OUT connected in series with its load.

Full wiring diagrams: Hardware Connection Guide


4CH 10A — pin assignments

text
Module   →   MCU (ESP32 example)
────────────────────────────────
ZC-OUT   →   GPIO 4
DIM1     →   GPIO 16
DIM2     →   GPIO 17
DIM3     →   GPIO 18
DIM4     →   GPIO 19
VCC      →   3.3V
GND      →   GND

⚠️ One ZC pin for all channels. Connect ZC-OUT to a single MCU interrupt pin. In code, register the zero-cross once — it applies to every channel on the module.




Code: ESP32 (rbdimmerESP32)

Use rbdimmerESP32 on dual-core ESP32 and ESP32-S3. It handles IRAM_ATTR and core pinning automatically — the ISR runs on Core 0 while WiFi runs on Core 1, preventing crashes.


2-channel example

cpp
// rbdimmerESP32 — 2 independent channels, shared zero-cross
// Docs: rbdimmer.com/docs/universal-library-for-esp32
#include "rbdimmerESP32.h"
#define ZC_PIN    4
#define DIM1_PIN  16
#define DIM2_PIN  17
rbdimmer_channel_t ch1, ch2;
void setup() {
    rbdimmer_init();
    rbdimmer_register_zero_cross(ZC_PIN, RBDIMMER_PHASE_DEFAULT);
    rbdimmer_config_t cfg1 = {
        .gpio_pin     = DIM1_PIN,
        .phase        = RBDIMMER_PHASE_DEFAULT,
        .initial_level = 0,
        .curve_type   = RBDIMMER_CURVE_RMS
    };
    rbdimmer_config_t cfg2 = {
        .gpio_pin     = DIM2_PIN,
        .phase        = RBDIMMER_PHASE_DEFAULT,
        .initial_level = 0,
        .curve_type   = RBDIMMER_CURVE_RMS
    };
    rbdimmer_create_channel(&cfg1, &ch1);
    rbdimmer_create_channel(&cfg2, &ch2);
    // Set each channel independently
    rbdimmer_set_level(ch1, 80);  // Channel 1 → 80%
    rbdimmer_set_level(ch2, 40);  // Channel 2 → 40%
}
void loop() {
    // Change levels at runtime as needed
    // rbdimmer_set_level(ch1, newLevel);
}


4-channel example

cpp
#include "rbdimmerESP32.h"
#define ZC_PIN    4
const uint8_t DIM_PINS[4] = {16, 17, 18, 19};
rbdimmer_channel_t channels[4];
void setup() {
    rbdimmer_init();
    rbdimmer_register_zero_cross(ZC_PIN, RBDIMMER_PHASE_DEFAULT);
    for (int i = 0; i < 4; i++) {
        rbdimmer_config_t cfg = {
            .gpio_pin      = DIM_PINS[i],
            .phase         = RBDIMMER_PHASE_DEFAULT,
            .initial_level = 0,
            .curve_type    = RBDIMMER_CURVE_RMS
        };
        rbdimmer_create_channel(&cfg, &channels[i]);
    }
    // Example: staggered brightness
    rbdimmer_set_level(channels[0], 100);
    rbdimmer_set_level(channels[1], 75);
    rbdimmer_set_level(channels[2], 50);
    rbdimmer_set_level(channels[3], 25);
}


Dimming curves

Curve Constant Best for
Linear RBDIMMER_CURVE_LINEAR Heating elements
RMS RBDIMMER_CURVE_RMS Incandescent bulbs
Logarithmic RBDIMMER_CURVE_LOGARITHMIC Dimmable LED bulbs



Code: Arduino / ESP8266 (RBDdimmer)

Use RBDdimmer for ATmega-based Arduino boards and ESP8266.

⚠️ Do not use RBDdimmer on ESP32 with WiFi active — the ISR lacks IRAM_ATTR and causes crashes. Use rbdimmerESP32 instead. See: Wrong Library: RBDdimmer vs rbdimmerESP32


Arduino Uno/Nano — 2 channels

cpp
// RBDdimmer — 2 channels on Arduino Uno/Nano
// ZC pin MUST be pin 2 or pin 3 on Uno/Nano (INT0/INT1)
#include <RBDdimmer.h>
#define ZC_PIN    2   // Hardware interrupt pin
#define DIM1_PIN  5
#define DIM2_PIN  6
// First dimmer registers the zero-cross pin
dimmerLamp dimmer1(DIM1_PIN, ZC_PIN);
// Subsequent dimmers share the ZC signal from dimmer1
dimmerLamp dimmer2(DIM2_PIN);
void setup() {
    dimmer1.begin(NORMAL_MODE, ON);
    dimmer2.begin(NORMAL_MODE, ON);
    dimmer1.setPower(80);  // Channel 1 → 80%
    dimmer2.setPower(40);  // Channel 2 → 40%
}
void loop() {
    // No special call needed in NORMAL_MODE
}


Arduino Mega — ZC pin options

On the Mega, ZC can be pins 2, 3, 18, 19, 20, or 21. The 4CH module works the same way — declare each channel after the first:

cpp
dimmerLamp dimmer1(DIM1_PIN, ZC_PIN);  // ZC set here
dimmerLamp dimmer2(DIM2_PIN);
dimmerLamp dimmer3(DIM3_PIN);
dimmerLamp dimmer4(DIM4_PIN);


ESP8266 — multi-channel

ESP8266 uses RBDdimmer with the same pattern: the first dimmerLamp sets the ZC pin; subsequent ones share it automatically.

cpp
// RBDdimmer — 2 channels on ESP8266 (NodeMCU)
#include <RBDdimmer.h>
#define ZC_PIN   5   // D1
#define DIM1_PIN 4   // D2
#define DIM2_PIN 14  // D5
dimmerLamp dimmer1(DIM1_PIN, ZC_PIN);
dimmerLamp dimmer2(DIM2_PIN);  // shares ZC from dimmer1
void setup() {
    dimmer1.begin(NORMAL_MODE, ON);
    dimmer2.begin(NORMAL_MODE, ON);
    dimmer1.setPower(80);
    dimmer2.setPower(40);
}
void loop() {}



Runtime Control

Both libraries allow runtime brightness changes:

cpp
// rbdimmerESP32
rbdimmer_set_level(ch1, 60);
// With smooth transition (rbdimmerESP32)
// signature: (channel, target_level_pct, duration_ms)
rbdimmer_set_level_transition(ch1, 60, 2000); // → 60% over 2 000 ms
// RBDdimmer
dimmer1.setPower(60);



Common Mistakes

Mistake Soluzione
Separate ZC pins per channel Use one ZC pin, one registration
Using RBDdimmer on ESP32+WiFi Use rbdimmerESP32
ZC on non-interrupt pin (Uno) Use pin 2 or 3 on Uno/Nano
Overloading a channel Check module rating: 8A or 10A per ch
DIM pins wired in wrong order Loads swap channels; re-map GPIO



Related Articles



Still have questions?

Ask on forum.rbdimmer.com or open a GitHub Issue.

Condividi articolo
Accedi per lasciare un commento