ESP32 S3 UNO - PC817 Optocoupler: Monitor 12V/24V DC Input Signal
This ESP32 S3 Uno PC817 optocoupler tutorial shows you how to read a 12V or 24V DC signal without letting that voltage touch the board. The ESP32 S3 Uno form board runs on 3.3V, so an opto-isolator (photocoupler) is the safe bridge between it and a gate controller, a power supply or a PLC output. At the end, your sketch will tell you if a device is really running right now.
In this tutorial, you will:
- Pick the right PC817 optocoupler module for a 3.3V, 5V, 12V or 24V signal
- Wire the module to the ESP32 S3 Uno and find out if its output is active LOW or active HIGH
- Tap the module across a device in parallel, so the reading follows the device itself
- Read the isolated digital input with digitalRead() in the Arduino IDE
- Build the same input from a bare PC817 chip if you prefer to solder

Hardware Preparation
Or you can buy the following kits:
| 1 | × | DIYables Sensor Kit (18 sensors/displays) |
Additionally, some of these links are for products from our own brand, DIYables .
You only need one module variant: the one that matches the signal you want to watch. The table further down helps you choose.
Overview of PC817 Optocoupler
The PC817 is a small 4-pin part that people also call a photocoupler or an opto-isolator. It is the reason this project is safe, so it helps to know how it works.
How It Works
Inside the plastic body, an infrared LED faces a phototransistor across an insulating gap. When current flows through the LED, its light turns the transistor on. The signal crosses the gap as light, not as electricity, so the two sides never share a wire.
Why the ESP32 S3 Uno Needs It
ESP32 S3 Uno pins work at 3.3V and are NOT 5V tolerant. A 12V or 24V line on a GPIO pin kills that pin at once. With a PC817 in between, the ESP32 S3 Uno only sees its own 3.3V, and the high voltage stays on the other side of the gap.
Typical Jobs
You can watch the 12V output of a garage-door or gate controller, so your sketch knows when the gate is moving. You can check if a 12V car accessory line is live before your project draws power from it. You can also follow the 24V enable line of a bench power supply.
In every case, the real question is not "is this wire live?" but "is the device at the end of this wire on or off right now?". That is the answer the PC817 gives to your sketch.
A Note on Logic Level
The ESP32 S3 Uno uses 3.3V logic. So the output side of the optocoupler is pulled up to 3.3V on this board, and the pin reads either 3.3V or 0V.
Specifications
| Parameter | Value |
|---|---|
| Package | 4-pin DIP |
| Input LED forward voltage (Vf) | about 1.2V typical, 1.4V max |
| Input LED forward current (If) | 5-20 mA normal range, 20 mA continuous max |
| Output collector-emitter voltage (VCEO) | 35V max |
| Output collector current (IC) | 50 mA max |
| Collector power dissipation | 150 mW |
| Isolation voltage | 5000 Vrms for 1 minute |
| Current Transfer Ratio (CTR) | 50% to 600% by rank (A 80-160%, B 130-260%, C 200-400%, D 300-600%) |
| Switching speed | rise time about 4 us, fall time about 3 us |
| Operating temperature | -30 C to +100 C |
The PC817 Optocoupler Module
The easiest way to use a PC817 with the ESP32 S3 Uno is a ready-made isolation module, and this guide wires that up. You can buy it with 1, 2, 4 or 8 channels. Each channel already has a PC817, its series resistor and usually a status LED, and the outside wires go into screw terminals instead of bare pins.
Input Side
A + (or IN+) and a - (or IN-) screw terminal take the external signal.
Output Side
VCC, GND and OUT (or DO / OUT1..OUTn) header pins go to the ESP32 S3 Uno. On this board, power the output side from the 3.3V pin, never from 5V. Many modules pull OUT up to VCC, so a 5V VCC would put 5V on a 3.3V pin. This choice is separate from the input-side choice below, and it is the same for every module variant.
One Resistor, One Voltage
This is the part that surprises people. The series resistor is already on the board, and it is sized for one input voltage only. No module handles every voltage. The modules come in three variants, and you buy the one that fits the signal you want to watch.
Which PC817 Optocoupler Module Do I Need?
Measure or read the voltage of the signal you plan to tap, then find its row:
| Signal you want to watch | Module variant to buy | Typical source |
|---|---|---|
| 3.3V or 5V logic | 3-5V module | another board's output pin, a 5V control board, a separately powered sensor |
| 12V DC | 12V module | gate and garage-door controllers, automotive accessory lines, alarm panels |
| 24V DC | 24V module | bench power supply enable lines, PLC outputs, industrial sensors |
Picking the variant is like picking a resistor value. It is the one buying choice on this page that really matters, and there are two ways to get it wrong.
A 12V Module on a 24V Line
The internal LED gets about twice the current its resistor was chosen for, and it is damaged within seconds. This is the costly mistake.
A 24V Module on a 12V Line
The LED does not get enough current. Nothing burns, but the output may switch late, switch only sometimes, or never switch. It looks like a wiring fault, but it is really a buying fault.
If your signal is between two labels, pick the nearest variant without going over. Then test it on the bench with the status LED before you trust the reading.
Why Isolate a 5V or 3.3V Signal?
The 3-5V module can look strange next to a 3.3V board. If the other signal is already at logic level, why isolate it? The answer is that isolation is not about voltage. It is about not sharing a ground.
Two circuits with their own power supplies, or at the two ends of a long cable, do not agree on where 0V is. If you join their grounds, return current, noise and faults can travel between them. A PC817 lets the information cross while the grounds stay apart.
There is one more reason on the ESP32 S3 Uno: a 5V logic signal cannot go straight into a 3.3V pin. The 3-5V module solves both problems at once. Use it for a separately powered control board, a long cable across a tutorial, a noisy motor driver nearby, or the 5V logic board inside a mains-powered appliance.
Also remember that the PC817 input reacts to current, not voltage. A 5V supply that can give 20 A is no harder on the optocoupler than one that gives 20 mA, because the module's resistor sets the LED current. The big supply only changes how much damage a wiring mistake elsewhere can do, which is one more reason to keep it on the other side of the gap.
Active LOW or Active HIGH: Which Way Does Your Module Read?
Before you trust any reading, you need to know which logic level means "signal present". This takes less than a minute, and it saves a lot of confusion later.
The Bare Chip
With the bare chip wired as this guide shows, the answer is fixed. The collector goes to a digital input pin that a pull-up holds HIGH. The internal pull-up of the ESP32 S3 Uno is the easiest choice, and it pulls the pin to 3.3V. A 10 kohm resistor from the pin to 3.3V does the same job. The result feels upside down at first:
| External signal | LED | Transistor | Pin reads |
|---|---|---|---|
| PRESENT | on | conducts | LOW |
| ABSENT | off | off | HIGH |
The Module
Modules are not always the same. Most of them pass the chip's behaviour straight through, so a present signal still reads LOW. Some makers invert it on the board, so OUT follows the input. Both kinds are sold, sometimes with nearly the same printing, so test yours:
- Wire the module as shown below, upload the sketch from this guide and open the Serial Monitor at 9600 baud.
- Leave the input terminals without power and note what the board prints.
- Power the external line and note what it prints now.
- The state printed while the line is live is your module's active level. If it prints LIVE with nothing on the input and IDLE while the line has power, you have the inverting kind.
- Compare with the module's own status LED, which lights whenever the input side has power. If the LED is on but the printed state does not change, you are reading the wrong level. The tap itself is fine.
To see the raw pin value instead of LIVE/IDLE, add this line to loop() while you test:
When you know the answer, change one constant at the top of the sketch: MODULE_ACTIVE_LOW. Keep it true for the usual active-LOW module, or set it to false for a module whose output follows the input. Nothing else in the code changes. Active LOW is common on relay modules too, and the internal pull-up is the same one used in the ESP32 S3 Uno - Button tutorial.
WARNING
Never connect the ground of the 12V or 24V circuit to the GND of the ESP32 S3 Uno. The two grounds must stay apart, because that separation is the whole point of the optocoupler. If you join them, the PC817 still switches, but the isolation is gone, and a fault on the 12V/24V side can reach your board.
ESP32 S3 Uno Pinout
The image below shows the pinout of the ESP32 S3 Uno form board. Use it to find the Uno header pins (D2, 3.3V, GND…) and their GPIO numbers when you wire this circuit.

Wiring Diagram
The external signal goes to the IN+ and IN- screw terminals of the matching module variant. On the other end, VCC, GND and OUT go to 3.3V, GND and D2 (GPIO18) of the ESP32 S3 Uno. The series resistor is already on the module, so you do not add one.

This image is created using Fritzing. Click to enlarge image
| PC817 Module Pin | ESP32 S3 Uno Pin |
|---|---|
| VCC | 3.3V |
| GND | GND |
| OUT | D2 (GPIO18) |
| IN+ | switched positive of the 12V or 24V device (not the board) |
| IN- | return of the 12V or 24V device (not the board) |
WARNING
Power the module output side from 3.3V, not 5V. On many modules OUT is pulled up to VCC, and ESP32 S3 Uno pins are NOT 5V tolerant. A 5V VCC can damage GPIO18.
For the optional bare-chip build at the end of this guide, the 12V signal goes to pin 1 through a 1 kohm resistor (2.2 kohm for 24V). Pin 2 goes back to the ground of the 12V circuit. Pin 4 goes to D2 (GPIO18), and pin 3 goes to GND on the ESP32 S3 Uno.
Connecting the PC817 in Parallel With the Device You Want to Monitor
Where you place the input wires decides if the project works or burns the chip. Let's use a gate opener as the example. Its controller sends 12V down two wires to the gate motor relay whenever the gate moves, and the ESP32 S3 Uno must notice that.
The module input goes across those two wires, in parallel with the device, just where a voltmeter would go. It never goes into the wire.
WARNING
Never put the PC817 input in series with the device. In series, the full load current of the gate motor, relay coil or lamp would flow through an LED rated for 20 mA, and the PC817 would die the moment the device turns on. Always connect across the device, in parallel.
You do not cut or move any of the existing gate wiring. You only add three connections:
- The switched positive terminal of the device goes to the IN+ screw terminal. Do not add your own resistor, because the module already has the one its variant needs.
- The negative or return terminal of the same device goes to the IN- screw terminal.
- The output side stays as it is: OUT to D2 (GPIO18), VCC to 3.3V and GND to GND.
The tap uses only the small LED current the module is designed for. Next to the amps a gate motor, relay coil, valve or lamp draws, that is nothing, so the device works exactly as before. The measurement is read-only.
Polarity Matters
The input side is an LED, and an LED conducts in one direction only. If you swap IN+ and IN-, nothing breaks, but the module never turns on, the status LED stays dark and the sketch prints IDLE forever. Measure the tap with a multimeter and find the positive side before you wire it.
Inductive Loads Need a Clamp Diode
A gate motor, relay coil, contactor, solenoid or valve makes a big reverse-voltage spike when its power is cut. The PC817 input LED can only take 6V in reverse. Fit a normal diode in reverse-parallel right across the IN+ and IN- terminals: cathode to IN+, anode to IN-. In normal use the diode does nothing. On a spike, it conducts and clamps the reverse voltage to well under one volt. A 1N4148 is fine for a small tap, and a 1N4007 for a heavier one.
Leaky Solid-State Outputs
Some PLC transistor outputs, triac outputs and LED lamp drivers let a small current through even when they are off. That leakage can light the module's input LED a little, and the sketch then says the device is on while it is clearly off. The sign is a reading that never goes back to IDLE and a status LED that glows weakly. Put a bleeder resistor of about 4.7 kohm to 10 kohm across IN+ and IN-, so the leakage flows through the resistor and not through the LED.
DC Only
The module input is a single LED, so it works with one polarity and with DC only. To sense an AC line, you need an optocoupler with two back-to-back LEDs in its input stage.
Knowing Whether the Device Is Actually Running
Because the tap sits in parallel with the device, the reading is honest. The pin does not follow one button or one controller output. It follows the power that really reaches the device. A gate opened by the remote, the wall switch or a key switch looks the same to the sketch, because the sketch watches the motor, not the trigger. And if the gate got a command but no power, the pin stays IDLE, and that silence is your fault report.
This turns a simple digital read into data worth logging. You can count run hours for the gate motor, send an alert when an opening takes longer than its normal twenty seconds, record idle time for a machine, or check "did it really start?" a few seconds after you send a command.
There is one honest limit: the PC817 tells you the device has power, not that it works. A stuck motor or a burnt heater element still draws power on that line, and it still reads LIVE.
Optional: Building the Same Input From the Bare PC817 Chip
If you like to solder, you can skip the module and use the bare chip. Then choosing a variant becomes choosing a resistor: you fit the resistor the module would have had.

The chip is a 4-pin DIP, and pin 1 is marked with a dot or a notch.
| PC817 Pin | Name | Connects to |
|---|---|---|
| 1 | Anode (A) | the external signal, through the series resistor |
| 2 | Cathode (K) | the ground of the external circuit, NOT the ESP32 S3 Uno GND |
| 3 | Emitter (E) | GND on the ESP32 S3 Uno |
| 4 | Collector (C) | D2 (GPIO18) on the ESP32 S3 Uno |
Choose the resistor for about 10 mA of LED current with R = (Vin - 1.2) / 0.01:
| Input voltage | Resistor |
|---|---|
| 3.3V | 220 ohm |
| 5V | 390 ohm |
| 12V | 1 kohm |
| 24V | 2.2 kohm, in a 1/2 W part |
Change the resistor whenever the input voltage changes. Everything else on this page still applies: the parallel tap, the clamp diode, the bleeder resistor and the separate grounds. With the internal pull-up, this build really is active LOW, so keep MODULE_ACTIVE_LOW set to true.
How To Program
Reading the PC817 is just reading a digital pin. The steps below show the four small pieces of code you need.
- Give a name to the pin that the module OUT line goes to. D2 on the ESP32 S3 Uno is GPIO18.
- Make that pin an input with the internal pull-up, using pinMode().
- Read the pin with digitalRead().
- Turn the raw level into a yes/no answer with the one constant that describes your module.
- Print the result, or use it to trigger an action.
ESP32 S3 Uno Code - PC817 Optocoupler
This sketch reads D2 (GPIO18) every half second and prints LIVE when the 12V line has power and IDLE when it does not. You do not need any library, because reading a PC817 is plain digital input.
Detailed Instructions
Follow these steps in order:
- New to the ESP32 S3 Uno? Follow ESP32 S3 Uno - Getting Started first.
- Check the module variant on your bench. It must match the voltage of the line you will tap.
- Wire it up as shown in the diagram. Power the module from 3.3V, and keep the 12V ground away from the board GND.
- Connect the board to your computer with a USB Type-C cable.
- Open Arduino IDE, choose the ESP32S3 Dev Module board and the correct COM port.
- Copy the code above and open it in the Arduino IDE.
- Upload the code by clicking the Upload button.
- Open the Serial Monitor and set it to 9600 baud.
- Switch the 12V line on and off a few times.
- Check the result on the Serial Monitor.
- Tip: If the result is exactly backwards (LIVE at rest and IDLE while the line has power), your module inverts on the board. Set MODULE_ACTIVE_LOW to false and upload again. If it says LIVE with nothing connected to the input, check that GND really reaches the module and that the pin uses INPUT_PULLUP. If it never says LIVE, check the input polarity and that the module variant matches the line voltage.
Video Tutorial
Watch the video below to see this ESP32 S3 Uno project step by step.
Function References
FAQ
Can I connect a 12V signal directly to an ESP32 S3 Uno pin?
No. ESP32 S3 Uno pins work at 3.3V and are not 5V tolerant, so 12V destroys the pin right away and can damage the whole chip. Always put a PC817 optocoupler module, or another isolation or level-shifting circuit, between the 12V line and the board. If you want to measure the voltage of that line instead of only detecting it, see the ESP32 S3 Uno - Measure Voltage tutorial.
Should I power the PC817 module from 3.3V or 5V on the ESP32 S3 Uno?
Use 3.3V. On many modules the OUT pin is pulled up to VCC, so a 5V VCC would put 5V on a GPIO pin. The PC817 transistor works fine at 3.3V, and the internal pull-up of the ESP32 S3 Uno holds the pin at 3.3V too.
Is this code different from the UNO R4 version?
Only the pin number changes. The UNO R4 sketch uses pin 2, and on the ESP32 S3 Uno the D2 header is GPIO18, so the code says #define PC817_PIN 18. pinMode(), INPUT_PULLUP and digitalRead() work the same way, and no library is needed.
Why does my sketch show LIVE when nothing is connected?
Your module is probably the inverting type, so its OUT follows the input. Set MODULE_ACTIVE_LOW to false. If that does not help, check that the module GND is connected to the ESP32 S3 Uno GND and that the pin uses INPUT_PULLUP.
Can one ESP32 S3 Uno monitor several 12V or 24V devices?
Yes. Use a 2, 4 or 8 channel module, or several single modules, and connect each OUT to its own digital pin. Each channel needs its own pin in the code, and every input pair goes across its own device.
What if my project needs more pins than the Uno headers give?
The ESP32 S3 Uno has two extra rows of holes with more GPIOs: GPIO15 and GPIO16 (I/O, PWM, analog), GPIO45 and GPIO35 to GPIO42 (I/O, PWM), and GPIO47/GPIO48 (output only, PWM). Solder pin headers to them and write the GPIO number in your code. For extra optocoupler channels, GPIO35 to GPIO42, GPIO15 and GPIO16 are good choices. Do not use GPIO47/GPIO48, because they are output only, and they may also run at 1.8V instead of 3.3V on some modules (especially names with "V", like R8V or R16V), so 3.3V devices can be damaged or act strangely. Also be careful with GPIO0, GPIO3 (D6), GPIO45 and GPIO46 (D9): they are boot strapping pins, and a wrong connection can stop the board from booting or uploading code. Use the other extra pins first.
Troubleshooting
| Problem | Possible Cause | Solution |
|---|---|---|
| No COM port in the Arduino IDE | USB driver missing or board not in upload mode | Install the CP210x or CH340 driver, try another USB Type-C data cable, or hold BOOT while you press RESET |
| Upload fails with a timeout | Wrong board selected or board busy | Choose ESP32S3 Dev Module and the right COM port, then hold BOOT while you press RESET and upload again |
| Always prints IDLE | IN+ and IN- swapped, or a 24V module on a 12V line | Check polarity with a multimeter, and use the module variant that matches the line voltage |
| Always prints LIVE, even with no input | Inverting module, or module GND not connected | Set MODULE_ACTIVE_LOW to false, and check the GND wire between the module and the board |
| Reading stays LIVE and the status LED glows weakly | Leakage current from a PLC, triac or LED driver output | Add a 4.7 kohm to 10 kohm bleeder resistor across IN+ and IN- |
| Module stops working after the device switches off | Reverse spike from an inductive load damaged the input LED | Replace the module and fit a 1N4148 or 1N4007 diode across IN+ and IN- (cathode to IN+) |
| Board resets or GPIO18 behaves strangely | Module VCC on 5V, or 12V ground joined to the board GND | Power the module from 3.3V and keep the two grounds separate |
| Serial Monitor shows strange characters | Wrong baud rate | Set the Serial Monitor to 9600 baud |