ESP8266 Multi-relay boards: Sonoff Dual and Electrodragon


November was a busy month and the Sonoff Dual that IteadStudio kindly sent me to review was bored in a box waiting for some free time. But it was just fair that another board that has been waiting in the boards-to-review box for longer had it’s chance to have some fresh air too. So here we have the Itead Studio Sonoff Dual and the Electrodragon ESP Relay Board face to face.

Face to face

They are both two relay boards with an Espressif ESP8266 controller. They are both powered from mains and programmable. The both have a similar size. They might look alike but they are actually quite different from the inside.

The Sonoff Dual (left) and the Electrodragon (right) face to face in the nude

The Sonoff Dual (left) and the Electrodragon (right) face to face in the nude

IteadStudio Sonoff Dual Electrodragon ESP Relay Board
Controller Bare ESP8266EX ESP8266 as a ESP12e module
Memory 8Mbit 32Mbit
Antenna PCB PCB in module
Relays 2x HKE HRS3FNH-S-DC5V-A 250V 10A 2x SONGLE SRD-05VDC-SL-C 125-250VAC 10A* (GPIO12 and GPIO13)
LEDs Blue 3mm LED attached to GPIO13 and RG 3mm LED attached to relays (all of them visible from outside the shell) SMD LEDs attached to the relays and to GPIO16 in inverse logic (none of them visible from outside the shell)
Buttons 1 available from the outside + 2 more in a header 2 surface buttons not accesible from the outside but also in the header
AC/DC On board As a module
Accessible ESP8266 GPIO RX TX 3V3 GND RX TX ADC GPIO4 GPIO15 3V3 5V GND and GPIO14 in the DHT22 footprint

* Please note that even thou the Electrodragon has 10A relays the board itself is no way able to handle such currents. The manufacturer recommends a maximum of 1A per line or 2A on a single line.

The relays in the Sonoff Dual

The relays in the Sonoff Dual

The Electrodragon header... the silkscreen quality is not the best

The Electrodragon header… the silkscreen quality is not the best

Those traces in the Electrodragon board are too thing for 10A

Those traces in the Electrodragon board are too thing for 10A

The Sonoff Dual is a more sturdy and end-user friendly device, it comes with a default firmware that connects to the eWeLink app for Android and iPhone and lets you manage the relays, configure schedules and much more. The Electrodragon on the other side is a hacker’s board, with a demo-firmware loaded which does very little.

Anyway I wanted to load my ESPurna firmware on both of them. It might look easy and for the Electrodragon is just a matter of adding support for multiple GPIO driven relays, but not for the Sonoff Dual.

IteadStudio Sonoff Dual

The Dual has 2 LEDs and one button meant to be used/checked from outside the enclosure. But the button is not connected to the ESP8266 (so you cannot use it to set the IC in flash mode, more about this later). The approach IteadStudio have used is pretty much the same they have in their PSB-04 modules: encapsulate the button and relay functionality in a helper microcontroller, a Silicon Labs F330. When a button is pressed the F330 reports the new status of the relays to the ESP8266 through serial. The ESP8266 can also change the relays statuses sending the proper commands to the F330.

The on-board button in the Sonoff Dual reports being button 2. Buttons 0 and 1 are available in a header properly labelled. The protocol has been reverse engineered by Markus Maeder and published in Itead’s support pages here. The messages have 4 bytes: starting byte, number of relays, status mask and stop byte.

Byte Contents Values
1 Start byte 0xA0
2 Number of relays 0x04
3 Status binary mask of the relays 0x00 to 0x0F
4 Stop byte 0xA1

So if the user presses the on board button (BUTTON2) the F330 will send 0xA00404A1 to the ESP8266 (provided everything was off). Bad news is that the communication is done through the hardware UART interface of the ESP8266 at 19230,8,N,1, so we cannot use it for debugging purposes.

Sonoff Dual support in ESPurna

The ESPurna firmware is released as free open software and can be checked out at my Espurna repository on GitHub.

I have added support for the Sonoff Dual to my ESPurna firmware. You can check it out in the repo but I’d like to highlight here the two chunks of code responsible for the communication between the ESP8266 and the F330.

    dualRelayStatus ^= (1 << id);

The code above toggles the “id” relay (where “id” can be 0 or 1 for the Sonoff Dual) by xor-ing (what?) it in the “dualRelayStatus”, that is the variable that holds the status of the relays as a bit mask. This is from the ESP8266 to the F330. For the other way round we should check for the start and stop bytes:

void buttonLoop() {

    if (Serial.available() >= 4) {

        unsigned char value;
        if ( == 0xA0) {
            if ( == 0x04) {
                value =;
                if ( == 0xA1) {

                    // RELAYs and BUTTONs are synchonized in the SIL F330
                    // The on-board BUTTON2 should toggle RELAY0 value
                    // Since we are not passing back RELAY2 value
                    // (in the relayStatus method) it will only be present
                    // here if it has actually been pressed
                    if ((value & 4) == 4) value = value ^ 1;

                    // Otherwise check if any of the other two BUTTONs
                    // (in the header) has been pressent, but we should
                    // ensure that we only toggle one of them to avoid
                    // the synchronization going mad
                    // This loop is generic for any PSB-04 module
                    for (unsigned int i=0; i<relayCount(); i++) {

                        bool status = (value & (1 << i)) > 0;

                        // relayStatus returns true if the status has changed
                        if (relayStatus(i, status)) break;





Note some things in the code above. First we check for the message format (lines 23 to 26). Second we expect just one button to be pressed at a time so we break after a relay has changed it status (line 45). And third we intercept button2 presses and map them to button0 (line 33). So the external button toggles relay 0. Right now this is hardcoded, change it to “value = value ^ 2” to toggle relay 1 instead.

The relayStatus method does quite a few things: checks if the status has changed (returns true if so), sends the message back to the F330, synchronises other devices (more about it in a minute) and sends notifications to MQTT and websocket clients.

Flash the Sonoff Dual

Since the button is not connected to the ESP8266 GPIO0 flashing the Sonoff Dual is a bit trickier than doing the same on the TH or POW. My recommendation is to shortcut an exposed pad connected to GPIO for the first flash and then use OTA to upload the filesystem or update the firmware.

In the picture below you have a line pointing a resistor pad connected to GPIO0. Use a jumper cable to short it to ground while powering the board to get into flash mode.

GPIO0 exposed in the Sonoff Dual

GPIO0 exposed in the Sonoff Dual

Electrodragon ESP Relay Board

The Electrodragon board is relatively simple to use. It’s a board meant for developers, not for end-users. The relays are directly connected to GPIO12 and GPIO13 so it’s just a matter of handling different GPIOs in the code. I use a vector to store all defined relay pins and then directly drive them with digitalWrite method.

std::vector<unsigned char> _relays;
        #ifdef RELAY1_PIN
        #ifdef RELAY2_PIN
        #ifdef RELAY3_PIN
        #ifdef RELAY4_PIN
digitalWrite(_relays[id], status);

To flash the Electrodragon note the pinout in the picture bellow. Power the device through the 5V pin. The RX marked pin should go to your programmer TX pin and the TX to the RX. Use the button labelled BTN2 to get into flashing mode. I’ve have better results holding it down while powering the board and until the firmware has started flashing.

Right pinout in the Electrodragon

Right pinout in the Electrodragon

Synchronising relays

If you have 2 relays you can control 2 appliances. Easy. But you can also do some other things like synchronising them. The ESPurna firmware supports 4 options:

  • No synchronisation
  • All off or at most one on (so if you turn one on all the other will go off)
  • One and only one on (so if you turn one on all the other will go off, but if you turn that one off again the next in the line will go on)
  • All the same (turn one on and all will go on, turn one off and all will go off)

Let me stop in the “one and only one on” since this this allows for multi-way switching, which is something I’ve been after since the first Sonoff.

3-way switch from the Wikipedia, by Cburnet

3-way switch from the Wikipedia, by Cburnet

This is a quite common way of switch where yo can toggle your lights from different switches in the room. A 3-way switch (like the one in the graphic) is usually implemented with a SPDT relay with exposed NO and NC terminals. But you can also use two relays with inverse sinchonisation, like the “one and only one on” mode does.

ESPurna 1.1.0

The ESPurna firmware is released as free open software and can be checked out at my Espurna repository on GitHub.

The firmware has been updated to support the Sonoff Dual and all the GPIO-based multi-relay boards out there, in particular the Electrodragon ESP Relay Board. This means a lot of changes:

  • MQTT topics for each relay (i.e. /test/dual/relay/0)
  • API entry points for each relay (i.e. PUT or GET /api/relay/0)
  • API entry point to get all relays (GET /relay)
  • Each relay is exposed as a different WeMo device
  • Different relay synchronisation options

I have also removed deprecated API entry points so all API requests go trough the /api namespace and require and API key.

I plan to add more API entry points to retrieve sensor values and a “pulse” mode for the relays so they can auto off after a second.

CC BY-SA 4.0 ESP8266 Multi-relay boards: Sonoff Dual and Electrodragon by Tinkerman is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

30 thoughts on “ESP8266 Multi-relay boards: Sonoff Dual and Electrodragon

  1. Peter Scargill

    Very interesting – I agree with comments about both boards – I don’t like the quality of the Electrodragon – Itead stuff is WAY better. I use the original SONOFF to control 2 small heaters and have done for months without any issue.

    Also of interest, your software – I was not even aware of it – am now – will test it and blog about it at where there is LOTS of ESP8266/Alexa/Sonoff stuff.

    So – anyone wanting to blow software for these can look at my own software for ESP8266 which has support for these boards – but not Alexa support – as I’m starting to use very similar software to yours by the look of it – are you aware of this one which now has dual access point support (my suggestion though I’m sure others suggested it too) and of course MQTT and Alexa support.

    I’ve just noticed yours has up to 3 access points – good idea – right – I’m off to try it out on one of my Sonoffs.

  2. Xose

    Hi Pete
    Yes I follow your blog. Great stuff there. I’m aware of your work and Theo’s too. His firmware is very much like mine albeit more evolved and with a lot of options. He has been working hard lately adding support for POW, DUAL and Alexa too.
    ESPurna has become the synthesis of different ESP8266 projects I’m working on. Whenever I improve something on any of them (like Wifi connectivity or using Hristo’s async libraries) ESPurna gets an update too.

    1. Xose Pérez Post author

      In 2016, I can already do that with my firmware for Sonoff 🙂
      And there are a number of other open source firmwares that can do that as well…

      1. freezing

        In 2016 we are still woking on the NEST support and linkage : ) Using the NEST temperature, humidity and light intensity information to automatic control the sonoff should be a good application.

        And LAN control is another feature should be done before 2017.. Many users want to control the sonoff without Internet and server : (

        1. Xose Pérez Post author

          So, are you part of the eWeLink/Sonoff developer team? If so, great to know what’s in your roadmap. I’m one of those user that prefer to go cloud-less if possible. I think that you don’t really own the device if you don’t own the data. Open sourcing the code would be great. Open sourcing the API could be a first step.

      2. freezing

        And for the Echo support, the idea should be somewhat different ; p

        ESPurna by emulating a Belkin WeMo switch.

        But for sonoff we will try to connect the cloud server to Alexa, Echo command to the server then our server send the action command to sonoff (sonoff don’t care this command is from app or Echo, it just do what sever tell it to do) – in this way we don’t need to modify the firmware but just need to upgrade the server code.

    1. Xose Pérez Post author

      Hi Adrian
      That’s the Electrodragon board I use in the example, but version 1.5. Mine is version 1.0. It should work with the current Espurna firmware selecting the Electrodragon hardware.

  3. Rajeev

    Hi Xose,

    This is regarding the other module, you made mention of – PSB-04 – the 4 channel wifi module ( Does that one also follow the same protocol as SonoffDual? I mean to ask if the ESPurna works for that module? Anyone tested the protocol? Although that is a standalone module w/o relays and other peripheral sub systems.

    1. Xose Pérez Post author

      I have not tested the PSB-04 yet. My guess is that it works just like the Dual, so the firmware should work with maybe a few modifications. If anyone has access to one such module please contact me by email to do some tests…

  4. Rajeev

    Hell Xose,

    Thanks for your comments. Now, regarding Sonoff Dual vs PSB-94. I have some questions about the protocol for sonoff dual which is used between esp and other MCU in sonoff dual .

    You have mentioned about the reverse engineering done by Markus at and yo have also written about the message structure. I have doubt about the byte 2 and byte 3 of the message

    a) Byte 2 as you say is number of relay. Then how come 0x04 is the value for this. Markus does not say anything about number of relays. He simply mentioned that byte no 2 is 0x04 and sonoff dual obviously has two relays and people (perhaps Markus and your code as well is working with byte no2 as 0x04) so I do not get the logic that Byte#2 corresponds to number of relays. If it does then for dual it ought to be 0x02 and for 4 ch modules, it could be 0x04? Or is it max no. of relays this code / firmware works for?

    b) This is regarding byte#3, Assuming, it is like all bits (4 LSBs) correspond to indivudual relays (as evident from message) then do you think that for relay number 3 and 4 the values ought to be 0x04 and 0x08 , logically OR’ed with other relays ?

    I tried to order the psb-04: The itead site says it is in stock whereas upon ordering I was told it is on backorder. I wrote to itead but still awaiting the reply.

    1. Xose Pérez Post author

      OK, this is mostly guess-work. As you say relays #3 and #4 are OR’ed in byte 3 as 0x04 and 0x08. Since the Dual is a two-relay board you should never see those values. But you do. When you click the button on board you get a 0x04 there. My guess is that the Dual works just like the PSB-04, a 4-relay 4-key board. Relays #1 and #2 are wired, but the physical button in the Dual is wired to key #3, whilst keys #1 and #2 are brought up in a header.

      Those messages we are seeing are the protocol between the ESP8266Ex and the F330. They are symmetric. Whenever you press a button the F330 toggles the corresponding relay and notifies the ESP with a full status (byte 3 with all active relays to 1). And when the ESP wants to change a relay status it sends a message with the same format to the F330.

      It’s state-full. Both sides must know the current status to toggle on/off a certain relay while keeping the rest as is (if you want to toggle relay #2 you have to send a current_status ^= 0x02). My guess is that byte 2 is the number of significant bits to take into account.

    1. Xose Pérez Post author

      This is almost 100% sure due to bad connections. Double check your connections (RX and TX) and remember to set the board in flash mode prior to uploading the code. Check the section “Flash the Sonoff Dual” for the Dual or “Electrodragon ESP Relay Board” for Electrodragon’s board. You can also check the documentation in the ESPurna wiki here:

    1. Xose Pérez Post author

      Hi, I’m working on improving the documentation, in the meantime, here you have an example on how to use the API to toggle a relay:

      # Toggle first relay (status 0 to switch off, 1 to switch on and 2 to toggle)
      $ curl -X PUT -H "Accept: application/json" http://192.1681.1.34/api/relay/0 --data "apikey=C62ED7BE7594B658&value=2"
      { "relay0": 0 }
  5. scruffr

    Hi Xose, nice writeup! Thanks!
    I’m currently stuck with a project incorporating a Sonoff Dual as an electric blinds control. For that I need the two channels to be mutually exclusive on at any time. When doing this wirelessly, that’s no issue as I can make sure of that in the relay control code, but a problem arises when also using the buttons 0 & 1.
    I can successfully read the buttons and control the relays accordingly, BUT since the F330 has it’s own idea about controlling the relays when a button press is detected things get a bit messy especially in case of race conditions which makes it rather hard to ensure the mutual exclusivity of channels.
    Have you got an idea how to prevent the F330 to control the relays on button press but only obey to control commands issued by the ESP8266?

    1. Xose Pérez Post author

      You can try to flash the F330. I have not tried it myself.

      My firmware has the option to force the relays to be in different states but it takes a dime longer to enforce since it’s the ESP8266 commanding the F330 to do so.

  6. Dylano

    dear… Find this with google..
    I flashed espeasy on the dual. Is there some one that give me a example to switch the two relais?
    I did try:,14,1
    And different GPIO … not working.

    And to set a idx in the espaeasy software and control it with Domoticz
    Only i not get the relais switching..

    Hope there is some one that can help me.

  7. Kira

    Please can you show sonoff connections for multiway. I really didnt understand with pictures of 3 way switching?
    Asli is it possible 4way switching?


    1. Xose Pérez Post author

      You can do three-way with two SPST relays like the ones in the Dual. Just connect each of the two lines that go to the other 3-way switch in your system to each relay and select “ONE AND JUST ONE” option in the synchronisation parameter in the web UI (SWITCHES tab). 4-way is not possible with these devices.

  8. Vijay

    Hi there! First of all a very big thank you for such a wonderful piece of code. I just discovered it and am looking for ways to use ESPurna instead of my own firmware code.
    One thing which is coming my way in adopting this is that I currently have my own code on ESP switch and I have integrated it with the normal ON/OFF switches in my home. So instead of the momentarily push button to manually control the switch , I use the regular ON/OFF switch. Seeing your code , you don’t have that mode built in. I tried understanding the code but I think it will be a tough job for me to try modifying it. that’s when I discovered this page where you talk about the “one and only one on” . I am not sure if I understand this. Can you tell me more if what I am looking for can be addressed by this mode OR a way to modify and support the ON/OFF switch instead of momentarily push to ON switch.

    1. Xose Pérez Post author

      You can change the button type from BUTTON_PUSHBUTTON to BUTTON_SWITCH that will trigger a toggle event on both edges, just connect one of them to ground and use a pullup in the GPIO. That will do (edit your board in hardware.h):


      The “one and only one” sync type is specially suited for 3-way switches when using a 2 relay board. Many of these relays boards use simple SPST relays (or sometimes SPDT but only the NO connection is brought out). You can then use the board as a 3-way switch by forcing the firmware to always have one of the relays on, and only one. So if you turn relay A on, relay B will go off, and if you turn A off, B will go on again.


Leave a Reply (all comments are moderated, be patient)

This site uses Akismet to reduce spam. Learn how your comment data is processed.