Arduino UNO Q - 2-Channel Relay Module

Do you have a pump and a lamp that should run on their own schedules, and you would like to switch them from your phone? One small board with two relays can do it. On the Arduino UNO Q, the STM32 MCU drives both relays, and the Linux side adds Python control and a Telegram bot on top.

In this tutorial, you will learn:

Arduino UNO Q 2-Channel Relay Module

WARNING

A relay can switch mains voltage, and mains voltage can kill. If you have never worked with it, ask a person with electrical training to help you. For your first tests, use a low-voltage DC load (24V or less) instead.

Hardware Preparation

1×Arduino UNO Q
1×USB Cable for Arduino Uno Q
1×2-channel Relay Module
1×Optionally, 5V Power Adapter
1×Jumper Wires
1×Recommended: Screw Terminal Block Shield for Arduino Uno
1×Recommended: Sensors/Servo Expansion Shield for Arduino Uno
1×Recommended: Breadboard Shield for Arduino Uno
1×Recommended: Enclosure for Arduino Uno
1×Recommended: Prototyping Base Plate & Breadboard Kit for Arduino UNO

Or you can buy the following kits:

1×DIYables Sensor Kit (18 sensors/displays)
Disclosure: Some of the links provided in this section are Amazon affiliate links. We may receive a commission for any purchases made through these links at no additional cost to you.
Additionally, some of these links are for products from our own brand, DIYables .

Overview of 2-Channel Relay Module

Think of this module as two separate switches on one board. They share the power pins, but each relay has its own control input and its own set of output screws. Two single relay modules would do the same job, yet one 2-channel board needs fewer wires, fits in a smaller box and is cheaper. The code does not change: one pin per relay, just like with single modules.

Pinout

2-channel Relay Module Pinout
Group Pin What it does
Power DC+ 5V supply for the relay coils
Power DC- Ground of that supply. Join it to a GND pin of the Arduino UNO Q too
Control IN1 Signal from the MCU that switches relay 1
Control IN2 Signal from the MCU that switches relay 2
Output COM1, NO1, NC1 Screw terminals of relay 1 for the first load
Output COM2, NO2, NC2 Screw terminals of relay 2 for the second load

Output Terminals

Every relay has three screws. COM is the common contact. NO stands for normally open: it connects to COM only while the relay is active. NC stands for normally closed: it connects to COM while the relay is idle. For a load that should be off by default (a pump, a lamp), wire it through COM and NO.

Trigger Jumpers

Near the inputs you find two jumpers, one per relay. A jumper picks how its relay reacts:

  • High-level trigger: the relay turns on when its IN pin is HIGH
  • Low-level trigger: the relay turns on when its IN pin is LOW

Each channel can use a different setting. The code in this tutorial expects high-level trigger on both. If one relay works "upside down", check its jumper first.

※ NOTE THAT:

The MCU pins of the Arduino UNO Q give 3.3V for HIGH, not 5V. Most 5V relay modules switch fine at 3.3V, because the IN pin only feeds a transistor or an optocoupler. If a relay does not click, check that its jumper is on high-level trigger and that DC- shares ground with the board.

To learn the basics of a single relay and how to hook up a high-voltage device, see the Arduino UNO Q - Relay tutorial.

Wiring Diagram

Only two signal wires go to the MCU: IN1 to D2 and IN2 to D3. For a quick test on your desk, the module takes its power from the 5V pin of the board.

The wiring diagram between Arduino UNO Q 2-channel relay module

This image is created using Fritzing. Click to enlarge image

Relay Module Pin Arduino UNO Q
DC+ 5V
DC- GND
IN1 Pin 2
IN2 Pin 3

Two relay coils that are on at once draw a fair amount of current. If the 5V pin also feeds sensors or a display, the voltage may drop and the board may reset when the relays switch. For a real project, power the module from its own 5V adapter, and join its GND to a GND pin of the Arduino UNO Q.

※ NOTE THAT:

DC- must always be joined to a GND pin of the Arduino UNO Q. Without a common ground, the IN signals have no reference and the relays act at random.

The two loads can share one high-voltage supply if they need the same voltage. A 12V pump and a 220V lamp need two separate supplies.

How To Program For 2-Channel Relay Module

Each relay is just one digital output, so two built-in functions are all you need.

  • In setup(), make both control pins outputs with pinMode():
pinMode(PIN_RELAY_1, OUTPUT); pinMode(PIN_RELAY_2, OUTPUT);
  • Turn a relay on or off with digitalWrite(). Each relay has its own pin, which lets them change state independently:
digitalWrite(PIN_RELAY_1, HIGH); // relay 1 on digitalWrite(PIN_RELAY_2, LOW); // relay 2 off

Arduino UNO Q Code

The Arduino UNO Q has two processors:

  • The STM32 MCU runs the Arduino sketch and sets the IN1 and IN2 pins
  • The Qualcomm MPU runs Debian Linux with Wi-Fi and Python
  • In this part, only the MCU gets code. The Linux side joins in the Bridge section below

The test sketch below switches both relays on together, waits two seconds, switches them off, waits two more seconds, and starts again. A line goes to the console at every change.

/* * This Arduino UNO Q code was developed by newbiely.com * * This Arduino UNO Q code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/arduino-uno-q/arduino-uno-q-2-channel-relay-module */ // Arduino UNO Q - 2-Channel Relay Module: switch both relays on and off every 2 seconds // Wiring: IN1 -> D2, IN2 -> D3, DC+ -> 5V (or a separate 5V supply), DC- -> GND // The MCU pins give 3.3V HIGH. Set both trigger jumpers to high-level trigger. #define PIN_RELAY_1 2 // The Arduino UNO Q pin connected to the IN1 pin of relay module #define PIN_RELAY_2 3 // The Arduino UNO Q pin connected to the IN2 pin of relay module // The setup function runs once on reset or power-up void setup() { Serial.begin(115200); delay(1500); // initialize digital pin as an output. pinMode(PIN_RELAY_1, OUTPUT); pinMode(PIN_RELAY_2, OUTPUT); } // The loop function repeats indefinitely void loop() { Serial.println("Turned on both relays"); digitalWrite(PIN_RELAY_1, HIGH); digitalWrite(PIN_RELAY_2, HIGH); delay(2000); Serial.println("Turned off both relays"); digitalWrite(PIN_RELAY_1, LOW); digitalWrite(PIN_RELAY_2, LOW); delay(2000); }

Detailed Instructions

First time with Arduino UNO Q? Read Getting Started with Arduino UNO Q first.

  • Wire: Connect the module as in the wiring diagram. Leave the output screws empty for now.
  • Connect: Plug the Arduino UNO Q into your computer with the USB-C cable.
  • Open Arduino App Lab: Wait until it finds your board.
  • Create a new App: Click the Create New App button.
Create New App in Arduino App Lab on Arduino UNO Q
  • Name it, for example TwoRelayTest, and click Create.
Arduino App Lab App folders and files on Arduino UNO Q
  • Paste the sketch: Copy the code above into sketch/sketch.ino. Keep the other files as they are. No library is needed.
  • Run: Click the Run button.
Click Run button in Arduino App Lab on Arduino UNO Q
  • Test it: You hear a double click every two seconds, and both relay LEDs go on and off together. Once that works, remove all power, wire your loads to COM and NO, and power up again.

App Lab Console Output

DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
Message (Enter to send a message to "Newbiely" on usb(2820070321))
New Line
9600 baud
[2026-10-20 09:00:01] Turned on both relays [2026-10-20 09:00:03] Turned off both relays [2026-10-20 09:00:05] Turned on both relays [2026-10-20 09:00:07] Turned off both relays [2026-10-20 09:00:09] Turned on both relays [2026-10-20 09:00:11] Turned off both relays

The time between lines is two seconds, the same as the delay(2000) in the sketch. If the console shows the lines but nothing clicks, the problem is in the power or ground wiring, not in the code.

Bridge: Linux + MCU

Now let Linux decide when each relay switches:

  • Both relays are wired to the MCU — IN1 on pin 2 and IN2 on pin 3
  • The MPU cannot touch those pins — it has to ask the MCU to switch them
  • The MCU offers six actions with Bridge.provide_safe(): relay1_on, relay1_off, relay2_on, relay2_off, all_on, all_off. It also offers get_relays with Bridge.provide(), which returns the state as text like 1,0
  • Python calls them with Bridge.call() and prints the state after each step
  • ⚠️ /dev/ttyHS1 (Linux) and Serial1 (MCU) are RESERVED by the router — never open them in your code

In short: Python calls an action → MCU sets pin 2 or 3 → the matching relay clicks.

MCU Code (Bridge)

/* * This Arduino UNO Q code was developed by newbiely.com * * This Arduino UNO Q code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/arduino-uno-q/arduino-uno-q-2-channel-relay-module */ // Arduino UNO Q - 2-Channel Relay Module, controlled from Linux via Bridge // Wiring: IN1 -> D2, IN2 -> D3, DC+ -> 5V, DC- -> GND (high-level trigger) // The MCU owns the relay pins. Linux (Python) only calls the functions below. #include "Arduino_RouterBridge.h" #define PIN_RELAY_1 2 // D2 -> IN1 (relay 1) #define PIN_RELAY_2 3 // D3 -> IN2 (relay 2) bool relay1_on = false; bool relay2_on = false; void setRelay(int channel, bool on) { if (channel == 1) { digitalWrite(PIN_RELAY_1, on ? HIGH : LOW); relay1_on = on; } else { digitalWrite(PIN_RELAY_2, on ? HIGH : LOW); relay2_on = on; } Monitor.println("Relay " + String(channel) + ": " + (on ? "ON" : "OFF")); } void relay1_on_fn() { setRelay(1, true); } void relay1_off_fn() { setRelay(1, false); } void relay2_on_fn() { setRelay(2, true); } void relay2_off_fn() { setRelay(2, false); } void all_on() { setRelay(1, true); setRelay(2, true); } void all_off() { setRelay(1, false); setRelay(2, false); } // Returns the state of both relays, for example "1,0" (relay 1 ON, relay 2 OFF) String get_relays(String arg) { return String(relay1_on ? 1 : 0) + "," + String(relay2_on ? 1 : 0); } void setup() { Bridge.begin(); Monitor.begin(); pinMode(PIN_RELAY_1, OUTPUT); pinMode(PIN_RELAY_2, OUTPUT); digitalWrite(PIN_RELAY_1, LOW); // start with both relays off digitalWrite(PIN_RELAY_2, LOW); // These functions touch hardware pins, so they are registered with provide_safe Bridge.provide_safe("relay1_on", relay1_on_fn); Bridge.provide_safe("relay1_off", relay1_off_fn); Bridge.provide_safe("relay2_on", relay2_on_fn); Bridge.provide_safe("relay2_off", relay2_off_fn); Bridge.provide_safe("all_on", all_on); Bridge.provide_safe("all_off", all_off); Bridge.provide("get_relays", get_relays); Monitor.println("Arduino UNO Q 2-Channel Relay Bridge ready"); } void loop() {}

Python Code (Bridge)

The Python script plays a small routine: relay 1 on, relay 2 on, relay 1 off, relay 2 off, then both on and both off together. After each step it reads the state back from the MCU.

""" This Arduino UNO Q script was developed by newbiely.com This Arduino UNO Q script is made available for public use without any restriction For comprehensive instructions and wiring diagrams, please visit: https://newbiely.com/tutorials/arduino-uno-q/arduino-uno-q-2-channel-relay-module """ from arduino.app_utils import * import time # Linux side: run a short demo on the two relays by calling the MCU over Bridge def step(action, seconds): Bridge.call(action) state = Bridge.call("get_relays") # for example "1,0" print(f"{action} -> relays: {state}") time.sleep(seconds) def loop(): step("relay1_on", 2) # pump on step("relay2_on", 2) # light on too step("relay1_off", 2) # pump off, light stays on step("relay2_off", 2) # light off step("all_on", 2) # both on together step("all_off", 3) # both off together App.run(user_loop=loop)

Detailed Instructions

  • Create a new App: In Arduino App Lab click Create New App, name it TwoRelayBridge, and click Create.
  • Paste the MCU sketch into sketch/sketch.ino and add the library:
  • Install the library: Click the Add sketch library button (the open book icon with a + sign) in the left sidebar.
Add sketch library in Arduino App Lab on Arduino UNO Q
  • Search for Arduino_RouterBridge created by Arduino and click the Install button.
My Apps / DIYables Apps
Run
Bricks
No bricks added...
Sketch Libraries
No sketch libra...
Files
python
sketch
.gitignore
README.md
app.yaml
sketch.ino
Add sketch library
Arduino_RouterBridge Arduino

This library provides a simple RPC bridge for Arduino UNO Q boards, allowing communication between the board and other devices using MsgPack serialization.

0.4.1
Install
More Info
  • Paste the Python code into the Python file of the same App.
  • Run: Click the Run button. The relays follow the routine and then repeat it.
  • Check both consoles: The MCU Monitor shows each pin change; the Python console shows what Linux asked for and the state it got back.

App Lab Console Output

DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
Message (Enter to send a message to "Newbiely" on usb(2820070321))
New Line
9600 baud
[2026-10-20 10:15:00] Arduino UNO Q 2-Channel Relay Bridge ready [2026-10-20 10:15:02] Relay 1: ON [2026-10-20 10:15:04] Relay 2: ON [2026-10-20 10:15:06] Relay 1: OFF [2026-10-20 10:15:08] Relay 2: OFF [2026-10-20 10:15:10] Relay 1: ON [2026-10-20 10:15:10] Relay 2: ON [2026-10-20 10:15:12] Relay 1: OFF [2026-10-20 10:15:12] Relay 2: OFF
DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
[2026-10-20 10:15:02] relay1_on -> relays: 1,0 [2026-10-20 10:15:04] relay2_on -> relays: 1,1 [2026-10-20 10:15:06] relay1_off -> relays: 0,1 [2026-10-20 10:15:08] relay2_off -> relays: 0,0 [2026-10-20 10:15:10] all_on -> relays: 1,1 [2026-10-20 10:15:12] all_off -> relays: 0,0

Telegram

With two relays, a phone remote makes a lot of sense: start the water pump from the garden, switch off the lamp you forgot at home, and check what is still running. The bot below has a command for each relay, two commands for both at once, and /status. Because the relays switch real loads, it only obeys messages from your own chat ID.

MCU sketch: Keep the same MCU sketch from the Bridge section.

Python Code (Telegram)

""" This Arduino UNO Q script was developed by newbiely.com This Arduino UNO Q script is made available for public use without any restriction For comprehensive instructions and wiring diagrams, please visit: https://newbiely.com/tutorials/arduino-uno-q/arduino-uno-q-2-channel-relay-module """ from arduino.app_utils import * import requests import time TELEGRAM_BOT_TOKEN = "YOUR_TELEGRAM_BOT_TOKEN" CHAT_ID = "YOUR_CHAT_ID" API_URL = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}" last_update_id = 0 # Telegram command -> (Bridge function, reply text) COMMANDS = { "/on1": ("relay1_on", "Relay 1 is ON."), "/off1": ("relay1_off", "Relay 1 is OFF."), "/on2": ("relay2_on", "Relay 2 is ON."), "/off2": ("relay2_off", "Relay 2 is OFF."), "/allon": ("all_on", "Both relays are ON."), "/alloff": ("all_off", "Both relays are OFF."), } HELP_TEXT = ( "Arduino UNO Q 2-Channel Relay Bot\n" "/on1 /off1 - relay 1 on / off\n" "/on2 /off2 - relay 2 on / off\n" "/allon /alloff - both relays on / off\n" "/status - show both relays" ) def get_updates(): try: resp = requests.get(f"{API_URL}/getUpdates", params={"offset": last_update_id + 1, "timeout": 5}, timeout=10) data = resp.json() if data.get("ok"): return data["result"] except Exception as e: print(f"Error getting updates: {e}") return [] def send_message(chat_id, text): try: requests.post(f"{API_URL}/sendMessage", data={"chat_id": chat_id, "text": text}, timeout=10) except Exception as e: print(f"Error sending message: {e}") def status_text(): state = str(Bridge.call("get_relays")).split(",") # for example ["1", "0"] if len(state) != 2: return "Relay state is not ready yet." r1 = "ON" if state[0] == "1" else "OFF" r2 = "ON" if state[1] == "1" else "OFF" return f"Relay 1: {r1}, Relay 2: {r2}" def loop(): global last_update_id for update in get_updates(): last_update_id = update["update_id"] if "message" not in update: continue chat_id = update["message"]["chat"]["id"] text = update["message"].get("text", "").strip().lower() print(f"Received: {text}") # Relays switch real loads: only accept commands from your own chat if str(chat_id) != CHAT_ID: send_message(chat_id, "Sorry, this bot only takes commands from its owner.") continue if text in COMMANDS: action, reply = COMMANDS[text] Bridge.call(action) send_message(chat_id, reply) elif text == "/status": send_message(chat_id, status_text()) else: send_message(chat_id, HELP_TEXT) time.sleep(1) App.run(user_loop=loop)

Detailed Instructions

  • Get a bot token: Create a bot with @BotFather. See How to Create a Telegram Bot if you need help. Put the token in TELEGRAM_BOT_TOKEN.
  • Get your chat ID: Put your own chat ID in CHAT_ID. Messages from any other chat are refused.
  • Paste the code into the Python file of your Bridge App. The MCU sketch stays the same.
  • Run: Click the Run button.
  • Test it: Open your bot in Telegram and send /on1, then /status.

App Lab Console Output

DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
[2026-10-20 18:42:10] Received: /on1 [2026-10-20 18:42:25] Received: /status [2026-10-20 18:43:02] Received: /allon [2026-10-20 18:47:40] Received: /off2 [2026-10-20 18:50:11] Received: /alloff
Telegram
Telegram 12:45
Welcome to Telegram!
ArduinoBot 10:19
Chatting with Arduino...
telegram-botfather
BotFather Yesterday
Your bot has been created.

ArduinoBot

bot
Today
/on1
10:15 AM ✓✓
Relay 1 is ON.
10:16 AM
/status
10:17 AM ✓✓
Relay 1: ON, Relay 2: OFF
10:18 AM
/allon
10:19 AM ✓✓
Both relays are ON.
10:20 AM
/off2
10:21 AM ✓✓
Relay 2 is OFF.
10:22 AM
/alloff
10:23 AM ✓✓
Both relays are OFF.
10:24 AM

OpenClaw

You can adapt the OpenClaw to this tutorial by refering the instruction on Arduino Uno Q - OpenClaw Tutorial

Project Ideas

Two relays plus a Linux computer on the same board open up many builds:

  • Balcony Garden Keeper: The MCU reads a soil sensor and runs a pump on relay 1, while Python turns a grow light on relay 2 on and off by the clock.
  • Room Climate Switch: A DHT22 on the MCU decides between a fan (relay 1) and a heater (relay 2); Telegram tells you which one is running.
  • Two-Gang Wall Switch: Two push buttons toggle the relays locally, and the Linux side keeps a log file of every change.
  • Aquarium Helper: Relay 1 runs the filter all day, relay 2 runs the light on a Python schedule, and /status shows both from your phone.
  • Garage Door and Light: Relay 1 pulses the door opener, relay 2 turns on the garage light for five minutes after each opening.

Challenge Yourself

Try these with your two relays and the Arduino UNO Q:

  • Easy: Change the test sketch so the relays take turns: relay 1 on while relay 2 is off, then swap every second.
  • Medium: Add a /toggle1 and /toggle2 command to the Telegram bot that flips a relay to the opposite state, using get_relays to read the current state first.
  • Advanced: Add a timer command like /on1 10 that turns relay 1 on and makes Python switch it off again after 10 minutes, even if no other message arrives.

Function References

※ OUR MESSAGES

  • As freelancers, We are AVAILABLE for HIRE. See how to outsource your project to us
  • Please feel free to share the link of this tutorial. However, Please do not use our content on any other websites. We invested a lot of effort and time to create the content, please respect our work!