Community project

Arduino Mage Npn 12v/24v 5v Io I2c Led

ESP32
Photo of Arduino Mage Npn 12v/24v 5v Io I2c Led
Generated with AI

wen symbol

Published August 25, 2026

This industrial I/O expansion board transforms an ESP32 into a robust 24 V control interface for factory automation, machinery, and process control applications. Built around an MCP23017 I2C GPIO expander with optocoupler-isolated inputs, MOSFET-driven outputs, and dual-voltage support (5 V logic, 12–24 V switching), the board safely bridges low-power microcontroller signals to high-power industrial loads while protecting against voltage spikes and noise.

The guide provides a complete wiring diagram, detailed parts list, and step-by-step assembly instructions covering power distribution, input conditioning, output switching stages, and I2C communication setup. Included firmware demonstrates debounced input sampling, safe output sequencing, and diagnostic LED feedback, enabling makers and technicians to deploy reliable automation logic without custom PCB design.

Wiring diagram

Wiring diagram for Arduino Mage Npn 12v/24v 5v Io I2c Led

Gather all the parts

QtyComponent
1

External 24 V 10 A DIN-rail DC power supply

24 V DC, 10 A, external DIN-rail supply

An external enclosed supply that provides the board and field devices with 24 V DC.

1

RECOM R-78E5.0-1.0 switching regulator

5 V, 1 A, SIP3

A board-mounted switching regulator that converts the 12–24 V field supply to a regulated 5 V rail.

1

MCP23017 I2C GPIO expander IC

TSSOP-28

A 16-pin digital I/O chip that reads eight isolated inputs and controls eight output drivers over I2C.

8

PC817C optocoupler

DIP-4, CTR grade C

An isolating light-coupler that safely transfers one 12–24 V NPN sensor signal to the 3.3 V logic side.

1

74AHCT541 octal buffer

TSSOP-20

An eight-channel 5 V buffer that converts the MCP23017 3.3 V output signals into strong 5 V MOSFET gate-drive signals.

8

NVRGS055N06CL 60 V N-channel MOSFET

SOT-23, 60 V, 70 mΩ max at VGS=4.5 V

A low-side power switch that connects one 24 V load to 0 V when its control signal is on.

8

2.2 kΩ 0.5 W input resistor

2.2 kΩ, 0.5 W, 1206

A resistor that limits 12–24 V NPN sensor current before each optocoupler LED.

8

Red 0805 input status LED

Red, 0805

A red light that shows when its NPN sensor input is being pulled to 0 V.

8

SS36 Schottky flyback diode

SS36, 3 A, 60 V, SMA

A diode that safely absorbs the voltage spike from one 24 V relay coil or solenoid when its output turns off.

8

Red 0805 output status LED

Red, 0805

A red light that shows when its low-side MOSFET output is pulling the load terminal to 0 V.

8

100 Ω MOSFET gate resistor

100 Ω, 0603

A resistor that limits each MOSFET gate charging pulse and reduces electrical noise.

8

100 kΩ MOSFET gate pull-down resistor

100 kΩ, 0603

A resistor that keeps each output MOSFET safely off while the controller starts or is unplugged.

1

Logic pull-up and decoupling passive set

2×4.7 kΩ 0603; 5×100 nF 0603; 2×10 µF 0805

The I2C pull-up resistors and local ceramic capacitors that keep the logic supply and data signals stable.

1

24 V input protection set

10 A fuse, SS54 reverse diode, SMBJ33A TVS

A fuse, reverse-polarity diode and surge suppressor that protect the board from a miswired or noisy 24 V field supply.

1

Two-position 5.08 mm power terminal block

2-position, 5.08 mm pitch, ≥10 A

The screw terminal where the 12–24 V field supply enters the circuit board.

1

Nine-position NPN sensor terminal block

9-position, 5.08 mm pitch

The screw terminal block for eight NPN sensor signal wires and their shared 0 V return.

1

Nine-position output terminal block

9-position, 5.08 mm pitch, ≥10 A

The screw terminal block for eight switched low-side load terminals and the shared protected +24 V feed.

1

Six-position 5 V GPIO terminal block

6-position, 3.5 mm pitch

A screw terminal for four protected 5 V logic signals plus 5 V and ground.

1

Four-pin 3.3 V I2C header

1×4, 2.54 mm

A keyed header for a low-voltage I2C device using 3.3 V logic.

8

4.7 kΩ input LED resistor

4.7 kΩ, 0.25 W, 1206

A resistor that limits current through one 24 V input status LED.

8

4.7 kΩ output LED resistor

4.7 kΩ, 0.25 W, 1206

A resistor that limits current through one 24 V output status LED.

8

10 kΩ optocoupler pull-up resistor

10 kΩ, 0603

A resistor that makes one MCP23017 input read high when its optocoupler is off.

1

PCB mechanical hardware set

2×7 XIAO female headers; 4×M3 mounting holes

Four mounting holes and the XIAO socket headers used to secure and plug in the controller.

8

Resettable output fuse

MF-R110, 1.10 A hold PTC, radial

A protective fuse that limits fault current in one 24 V output channel.

8

100 kΩ output-command pull-down resistor

100 kΩ, 0603

A resistor that keeps one output-command input low while the controller starts.

1

MCP23017 address and reset network

3×0 Ω, 10 kΩ, 100 nF 0603

Straps that set the expander to address 0x20 and keep its reset pin high.

4

5 V GPIO direction-selection jumper

1×3, 2.54 mm header plus shunt

A three-pin jumper that selects whether one translated 5 V signal is an input or an output.

1

SN74LVC1T45 5 V GPIO channel 1 translator

SN74LVC1T45, SC70-6

A direction-controlled chip that safely translates the first XIAO signal between 3.3 V and 5 V.

1

SN74LVC1T45 5 V GPIO channel 2 translator

SN74LVC1T45, SC70-6

A direction-controlled chip that safely translates the second XIAO signal between 3.3 V and 5 V.

1

SN74LVC1T45 5 V GPIO channel 3 translator

SN74LVC1T45, SC70-6

A direction-controlled chip that safely translates the third XIAO signal between 3.3 V and 5 V.

1

SN74LVC1T45 5 V GPIO channel 4 translator

SN74LVC1T45, SC70-6

A direction-controlled chip that safely translates the fourth XIAO signal between 3.3 V and 5 V.

Assemble it in 8 steps

1. 准备外部 24 V 电源

把符合当地安全规范的封闭式 24 V 直流 DIN 导轨电源安装在机箱或导轨上。它的 +24V 线接到扩展板 J1 的 +24V,0V 线接到 J1 的 0V;这两根线为现场设备和扩展板供电。

  • 先用万用表量 J1 两端,确认极性正确且电压在 12–24 V 范围内。
  • 交流市电只接外置、封闭且合规的 DIN 导轨电源;绝不能引入这块低压 PCB。
  • 把 +24V 与 0V 接反会使保护器件发热或损坏。

2. 安装 XIAO 控制器

将 Seeed Studio XIAO ESP32S3 插入两排 1×7 母座,USB-C 接口朝向 PCB 外缘。确认每一排针脚都进入对应孔位,不要错位一列。

  • 先只焊两个对角针脚,确认 USB-C 位置和板边方向正确后,再焊完其余针脚。
  • 焊接时不要让 5 V、3.3 V 或 GPIO 针脚之间产生焊锡桥接,否则可能损坏 XIAO。

3. 装配输入区域

在 PCB 的 IN1–IN8 区域装入八颗 PC817C 光耦、每路 2.2 kΩ/0.5 W 输入电阻、4.7 kΩ LED 电阻和红色输入 LED。光耦缺口和 PCB 丝印缺口必须同向;LED 的短脚或外壳色带一侧是负端,按丝印方向安装。

  • 每装完一路,用万用表检查该路没有把 +24V 短接到 0V。
  • 光耦和 LED 装反会导致该输入无指示或始终不工作。
  • 输入电阻必须使用 0.5 W、1206 或更大封装;普通小电阻可能在 24 V 现场侧过热。

4. 装配输出区域

在 OUT1–OUT8 区域依照丝印安装八颗 MOSFET、每路 100 Ω 栅极电阻、100 kΩ 下拉电阻、MF-R110 自恢复保险丝、SS36 续流二极管、红色输出 LED 及其 4.7 kΩ 电阻。SS36 带条纹的一端必须朝向 +24V 丝印,另一端朝向对应 OUTn。

  • 先检查每个 MOSFET 的封装方向,再焊接;SOT-23 的引脚很小,建议使用细焊锡和助焊剂。
  • 把续流二极管装反会在输出开启时直接短接 24 V,可能损坏保险丝、走线或电源。
  • 每路负载不得超过 1 A;八路同时工作时,外置电源、端子和铜箔必须承受总电流。

5. 装配逻辑与电源区域

装入 MCP23017、74AHCT541、5 V 降压稳压器、逻辑上拉电阻、去耦电容和 24 V 保护器件。MCP23017 的 A0、A1、A2 接地,I²C 地址固定为 0x20;RESET 由上拉电阻接到 3.3 V。每颗 IC 的 100 nF 电容要紧贴其电源脚。

  • 使用放大镜检查 TSSOP 引脚;相邻引脚间不应有焊锡连桥。
  • MCP23017 和 XIAO 只能使用 3.3 V 逻辑;不要把 5 V 接到 SDA、SCL 或 XIAO 的 GPIO。

6. 连接传感器与执行器

每个三线 NPN 传感器:棕线接 +24V 公共端,蓝线接 0V 公共端,黑线接 IN1–IN8 中对应的一路。每个直流负载:正端接输出端子的 +24V_COM,负端接对应 OUT1–OUT8;该输出会把负端接到 0V 来启动负载。

  • 先只接一个小型 24 V 指示灯或继电器线圈测试 OUT1,再逐路接入其余设备。
  • 感性负载必须使用本板对应通道的续流二极管;否则关断瞬间的尖峰可能损坏 MOSFET。
  • 不要把 NPN 传感器的黑色输出线直接接到 +24V。

7. 选择并连接 5 V GPIO 与 I2C

J4 的 IO1–IO4 经过单通道电平转换器连接到 XIAO GPIO1–GPIO4;按每路 DIR 焊盘或跳线选择方向,输出模式把 DIR 接 3.3V,输入模式把 DIR 接 GND。J5 的四针顺序为 3V3、GND、SDA、SCL,SDA 接 GPIO5,SCL 接 GPIO6。

  • 第一次使用 5 V GPIO 时,先选择输入模式并用万用表确认外部设备没有把电压送入错误端。
  • 不要把超过 5 V 的信号接到 J4;也不要把 24 V 现场信号接到 J4 或 J5。

8. 第一次低风险上电

先不接执行器,仅连接 XIAO 的 USB-C 与外部 24 V。确认 5 V 稳压输出为约 5.0 V、XIAO 的 3.3 V 为约 3.3 V,并确认所有 OUT 灯在上电时熄灭。随后一次连接一个传感器和一个小负载验证 INn 动作时 OUTn 与两颗状态灯一起变化。

  • 若某一路上电即导通,立即断开 24 V,检查该路 100 kΩ 栅极下拉、MOSFET 朝向和 74AHCT541 的 OE 接地。
  • 进行接线或更换负载前先断开 24 V 电源;带电插拔可能产生火花并损坏端子或输出器件。

Review all connections

1. Connections between "field_psu_24v" and "ESP32"

Functionfield_psu_24vESP32
power+24VTwo-position 5.08 mm power terminal block +VEXT
ground0VTwo-position 5.08 mm power terminal block 0VEXT

2. Connections between "tb_power" and "ESP32"

Functiontb_powerESP32
power+V24 V input protection set FIELD_INEXT
ground0VGND

3. Connections between "field_protection" and "ESP32"

Functionfield_protectionESP32
powerFIELD_PROTECTEDRECOM R-78E5.0-1.0 switching regulator VINEXT
ground0VGND

4. Connections between "pcb_reg_5v" and "ESP32"

Functionpcb_reg_5vESP32
powerVINVIN
groundGNDGND
powerVOUT5V

5. Connections between "mcp23017_ic" and "ESP32"

Functionmcp23017_icESP32
powerVDD3V3
groundVSSGND
i2cSDAGPIO 5
i2cSCLGPIO 6
digitalGPA0-GPA7PC817C optocoupler COLLECTOREXT
digitalGPB0-GPB774AHCT541 octal buffer A0-A7EXT

6. Connections between "opto_pc817c" and "ESP32"

Functionopto_pc817cESP32
digitalANODE2.2 kΩ 0.5 W input resistor END2EXT
groundCATHODENine-position NPN sensor terminal block IN1-IN8EXT
digitalCOLLECTORMCP23017 I2C GPIO expander IC GPA0-GPA7EXT
groundEMITTERGND

7. Connections between "input_series_resistor" and "ESP32"

Functioninput_series_resistorESP32
powerEND1VIN
digitalEND2PC817C optocoupler ANODEEXT

8. Connections between "input_indicator_led" and "ESP32"

Functioninput_indicator_ledESP32
powerANODEVIN
groundCATHODENine-position NPN sensor terminal block IN1-IN8EXT

9. Connections between "tb_inputs" and "ESP32"

Functiontb_inputsESP32
groundCOM_0VGND
digitalIN1-IN8PC817C optocoupler CATHODEEXT

10. Connections between "output_buffer" and "ESP32"

Functionoutput_bufferESP32
powerVCC5V
groundGNDGND
digitalA0-A7MCP23017 I2C GPIO expander IC GPB0-GPB7EXT
digitalY0-Y7100 Ω MOSFET gate resistor END1EXT
groundOE1_OE2GND

11. Connections between "gate_resistor" and "ESP32"

Functiongate_resistorESP32
digitalEND174AHCT541 octal buffer Y0-Y7EXT
digitalEND2NVRGS055N06CL 60 V N-channel MOSFET GATEEXT

12. Connections between "mosfet_gate_pulldown" and "ESP32"

Functionmosfet_gate_pulldownESP32
digitalEND1NVRGS055N06CL 60 V N-channel MOSFET GATEEXT
groundEND2GND

13. Connections between "output_mosfet" and "ESP32"

Functionoutput_mosfetESP32
digitalGATE100 Ω MOSFET gate resistor END2EXT
digitalDRAINNine-position output terminal block OUT1-OUT8EXT
groundSOURCEGND

14. Connections between "output_flyback_diode" and "ESP32"

Functionoutput_flyback_diodeESP32
groundANODENine-position output terminal block OUT1-OUT8EXT
powerCATHODEVIN

15. Connections between "output_indicator_led" and "ESP32"

Functionoutput_indicator_ledESP32
powerANODEVIN
digitalCATHODENine-position output terminal block OUT1-OUT8EXT

16. Connections between "tb_outputs" and "ESP32"

Functiontb_outputsESP32
power+24V_COMVIN
digitalOUT1-OUT8NVRGS055N06CL 60 V N-channel MOSFET DRAINEXT

17. Connections between "hdr_i2c" and "ESP32"

Functionhdr_i2cESP32
power3V33V3
groundGNDGND
i2cSDAGPIO 5
i2cSCLGPIO 6

18. Connections between "logic_passives" and "ESP32"

Functionlogic_passivesESP32
power3V33V3
power5V5V
groundGNDGND

19. Connections between "input_led_resistor" and "ESP32"

Functioninput_led_resistorESP32
powerEND1VIN
digitalEND2Red 0805 input status LED ANODEEXT

20. Connections between "output_led_resistor" and "ESP32"

Functionoutput_led_resistorESP32
powerEND1VIN
digitalEND2Red 0805 output status LED ANODEEXT

21. Connections between "opto_pullup_resistor" and "ESP32"

Functionopto_pullup_resistorESP32
powerEND13V3
digitalEND2MCP23017 I2C GPIO expander IC GPA0-GPA7EXT

22. Connections between "board_hardware" and "ESP32"

Functionboard_hardwareESP32
groundGND_REFERENCEGND

23. Connections between "output_fuse" and "ESP32"

Functionoutput_fuseESP32
powerINVIN
powerOUTNine-position output terminal block +24V_COMEXT

24. Connections between "buffer_input_pulldown" and "ESP32"

Functionbuffer_input_pulldownESP32
digitalEND174AHCT541 octal buffer A0-A7EXT
groundEND2GND

25. Connections between "mcp_config" and "ESP32"

Functionmcp_configESP32
groundA0_A1_A2GND
powerRESET_PULLUP3V3
groundDECOUPLING_GNDGND

26. Connections between "gpio_dir_jumper" and "ESP32"

Functiongpio_dir_jumperESP32
powerOUTPUT_SELECT3V3
groundINPUT_SELECTGND
digitalCOMMONSN74LVC1T45 5 V GPIO channel 1 translator DIREXT

27. Connections between "gpio_translator_1" and "ESP32"

Functiongpio_translator_1ESP32
powerVCCA3V3
powerVCCB5V
groundGNDGND
digitalAGPIO 1
digitalBSix-position 5 V GPIO terminal block IO1-IO4EXT
digitalDIR5 V GPIO direction-selection jumper COMMONEXT

28. Connections between "gpio_translator_2" and "ESP32"

Functiongpio_translator_2ESP32
powerVCCA3V3
powerVCCB5V
groundGNDGND
digitalAGPIO 2
digitalBSix-position 5 V GPIO terminal block IO1-IO4EXT
digitalDIR5 V GPIO direction-selection jumper COMMONEXT

29. Connections between "gpio_translator_3" and "ESP32"

Functiongpio_translator_3ESP32
powerVCCA3V3
powerVCCB5V
groundGNDGND
digitalAGPIO 3
digitalBSix-position 5 V GPIO terminal block IO1-IO4EXT
digitalDIR5 V GPIO direction-selection jumper COMMONEXT

30. Connections between "gpio_translator_4" and "ESP32"

Functiongpio_translator_4ESP32
powerVCCA3V3
powerVCCB5V
groundGNDGND
digitalAGPIO 4
digitalBSix-position 5 V GPIO terminal block IO1-IO4EXT
digitalDIR5 V GPIO direction-selection jumper COMMONEXT

31. Connections between "tb_gpio5v" and "ESP32"

Functiontb_gpio5vESP32
power+5V5V
groundGNDGND

Deploy the firmware

#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_MCP23X17.h>


// Forward declarations
void setOutputsOff();

constexpr uint8_t I2C_SDA_PIN = 5;
constexpr uint8_t I2C_SCL_PIN = 6;
constexpr uint8_t GPIO5V_1_PIN = 1;
constexpr uint8_t GPIO5V_2_PIN = 2;
constexpr uint8_t GPIO5V_3_PIN = 3;
constexpr uint8_t GPIO5V_4_PIN = 4;
constexpr uint8_t MCP_ADDRESS = 0x20;
constexpr uint8_t CHANNEL_COUNT = 8;
constexpr uint32_t INPUT_STABLE_MS = 20;

Adafruit_MCP23X17 io;
bool stableInput[CHANNEL_COUNT] = {false};
bool sampledInput[CHANNEL_COUNT] = {false};
uint32_t lastChangeMs[CHANNEL_COUNT] = {0};

void setOutputsOff() {
  for (uint8_t channel = 0; channel < CHANNEL_COUNT; ++channel) {
    io.digitalWrite(channel + 8, LOW);
  }
}

void setup() {
  Serial.begin(115200);
  Wire.begin(I2C_SDA_PIN, I2C_SCL_PIN);

  pinMode(GPIO5V_1_PIN, INPUT);
  pinMode(GPIO5V_2_PIN, INPUT);
  pinMode(GPIO5V_3_PIN, INPUT);
  pinMode(GPIO5V_4_PIN, INPUT);

  if (!io.begin_I2C(MCP_ADDRESS, &Wire)) {
    Serial.println("MCP23017 not found at 0x20; outputs remain unavailable.");
    while (true) delay(1000);
  }

  for (uint8_t channel = 0; channel < CHANNEL_COUNT; ++channel) {
    io.pinMode(channel, INPUT_PULLUP);
    io.pinMode(channel + 8, OUTPUT);
  }
  setOutputsOff();
  Serial.println("Industrial 8-in/8-out board ready.");
}

void loop() {
  const uint32_t now = millis();
  for (uint8_t channel = 0; channel < CHANNEL_COUNT; ++channel) {
    const bool sensorOn = (io.digitalRead(channel) == LOW);
    if (sensorOn != sampledInput[channel]) {
      sampledInput[channel] = sensorOn;
      lastChangeMs[channel] = now;
    }
    if (sampledInput[channel] != stableInput[channel] &&
        now - lastChangeMs[channel] >= INPUT_STABLE_MS) {
      stableInput[channel] = sampledInput[channel];
      io.digitalWrite(channel + 8, stableInput[channel] ? HIGH : LOW);
      Serial.printf("IN%u=%s, OUT%u=%s\n", channel + 1,
                    stableInput[channel] ? "ON" : "OFF", channel + 1,
                    stableInput[channel] ? "ON" : "OFF");
    }
  }
}

Remix this project

Make it yours in one click

Open a full copy of this project in your own Schematik workspace — diagram, code, parts, and assembly steps included. Swap the sensor, add features, or redesign the whole thing with AI. The author's original stays untouched.

Open in Schematik