ESP32 UNO - Color Sensor via Web
Hold a red cup in front of a sensor and see a cartoon turn red on your phone. That is the ESP32 Uno color sensor via web project. A TCS3200D/TCS230 color recognition module measures red, green and blue, and the ESP32 Uno form board pushes the result as a HEX code to a browser over WebSocket. The DIYables ESP32 WebApps library serves the page and keeps the link open.
By the end, you can:
- Connect a TCS3200/TCS230 RGB sensor to the Uno headers with five signal wires
- Turn three filter readings into one #RRGGBB code with map() and sprintf()
- Stream that code to a phone or PC browser with DIYables ESP32 WebApps
- Paint an animated Minion in the color your sensor sees, about once per second

The demo video sits further down, right after the upload steps.
Components You Need
| 1 | × | ESP32 Uno-form Board | |
| 1 | × | USB Cable Type-A to Type-C (for USB-A PC) | |
| 1 | × | USB Cable Type-C to Type-C (for USB-C PC) | |
| 1 | × | TCS3200D/TCS230 Color Recognition Sensor Module | |
| 1 | × | Jumper Wires |
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 .
Before You Start
After this part, you know which two guides fill the gaps if the sensor or the web framework is new to you.
| Topic | Guide |
|---|---|
| Sensor basics and calibration | ESP32 Uno - TCS3200D/TCS230 Color Sensor |
| Custom web page framework | ESP32 Uno - DIYables ESP32 WebApps Custom WebApp |
Good to know: the calibration guide gives you six numbers (min and max for each color). You type them into this sketch later.
ESP32 Uno Pinout
On the ESP32 Uno form board, every header label like D4 or D7 belongs to one GPIO number. The sketch talks to the GPIO number, so compare the labels with the diagram before you plug in the sensor.

How to Connect the Color Sensor
When this part is done, the TCS3200 sits on five digital pins of the ESP32 Uno and gets 3.3V power.

This image is created using Fritzing. Click to enlarge image
※ NOTE THAT:
The wiring diagram may not show the correct wiring for the ESP32 Uno. On the ESP32 Uno, connect VCC to 3.3V, not 5V. We will update the diagram soon. Until then, follow the wiring table and the text on this page, not the picture.
| TCS3200 Color Sensor | ESP32 Uno Pin |
|---|---|
| VCC | 3.3V |
| GND | GND |
| S0 | D4 (GPIO17) |
| S1 | D3 (GPIO25) |
| S2 | D6 (GPIO27) |
| S3 | D5 (GPIO16) |
| OUT | D7 (GPIO14) |
WARNING
The ESP32 Uno runs on 3.3V logic, and its pins cannot take 5V. Feed the module VCC from the 3.3V pin. The TCS3200 is fine from 2.7V to 5.5V, and its OUT pulses then stay at a safe 3.3V. If the drawing shows VCC on 5V, move only that wire. If you really need 5V on VCC, add a resistor divider (2.2kΩ from OUT to D7, 3.3kΩ from D7 to GND) so D7 (GPIO14) never sees more than about 3V.
Good to know: none of these five pins is a boot strapping pin, so the board starts and uploads with the sensor plugged in.
From Color to Web Page: the Data Flow
After this part, you can follow one color sample from the sensor chip to the screen.
Step 1 — Measure
Every 1000 ms, the sketch switches S2/S3 to the red, then the green, then the blue filter. For each filter, pulseIn() times one LOW pulse on OUT.
Step 2 — Scale
map() turns each pulse time into 0–255, using your numbers from the calibration guide. A short pulse means a strong color, so the scale runs backward (min time gives 255).
Step 3 — Pack
sprintf() writes the three values as one HEX text, for example #E63C1E for a tomato red.
Step 4 — Send
DIYables ESP32 WebApps adds the tag Color sensor: and broadcasts the text to every open browser over WebSocket (port 81).
Step 5 — Paint
JavaScript on the page drops the tag and sets the color on the Minion's body, arms and eyelids.
ESP32 Uno Code - Minion Color Web App
This part gives you four files. Together they read the sensor, join your WiFi and serve the Minion page.
| File | Job |
|---|---|
| ColorSensorESP32.ino | The heart of the build. It sets the sensor pins, connects to WiFi, samples the color each second and sends it |
| CustomWebApp.h | Declares the custom page class |
| CustomWebApp.cpp | Sends and receives WebSocket text tagged Color sensor |
| custom_page_html.h | The Minion page itself, with its styles and script |
ColorSensorESP32.ino
CustomWebApp.h
CustomWebApp.cpp
custom_page_html.h
Upload and Test
When you finish this list, the Minion on your screen copies the color of whatever you hold in front of the sensor.
- First time with this board? Set it up with ESP32 Uno - Getting Started before you continue.
- Calibrate first. Run the TCS3200D/TCS230 guide and note redMin, redMax, greenMin, greenMax, blueMin and blueMax.
- Build the circuit by following the wiring table above.
- Plug in the USB Type-C cable between the ESP32 Uno and your computer.
- Select the board in Arduino IDE: pick ESP32 Dev Module and the COM port of the board (CH340).
- Open the Library Manager with the Libraries icon on the left side of Arduino IDE.
- Find the library: type "DIYables ESP32 WebApps" and choose the entry by DIYables.
- Install it: press Install, then Install All so the helper libraries come too.
- Search for DIYables ESP32 WebApps created by DIYables and click the Install button.
- Make the project: save a new sketch as ColorSensorESP32, then add three new tabs and paste the other files into them. You should end up with four tabs:

- Enter your WiFi details in ColorSensorESP32.ino:
- Enter your calibration numbers in the three map() lines of loop(). Say your test gave redMin = 27, redMax = 164, greenMin = 33, greenMax = 196, blueMin = 25, blueMax = 141. Then the lines read:
- Flash the board: click Upload and wait for "Done uploading".
- Open the Serial Monitor and set it to 9600 baud. The output looks similar to this:
- No output? Press the EN (reset) button once and watch again.
- Open the page: type the IP address from the Serial Monitor into a browser on a phone or PC on the same WiFi, for example http://192.168.1.47.
- Pick the app: tap Color sensor WebApp on the home page, or go straight to http://192.168.1.47/custom.
- Test it: show the sensor a green leaf, a blue pen cap, a yellow sticky note. The Minion follows each one within a second.
- Pro tip: use matte paper cards for testing. Shiny plastic reflects the sensor's own white LEDs, and the Minion then looks pale and washed out.
Watch It Work
See the ESP32 Uno build in action in the video below.
Inside the Code
After this part, you know which file does what, and where to edit when you want changes.
The Sketch (ColorSensorESP32.ino)
| Code Part | What It Does |
|---|---|
| digitalWrite(S0, HIGH) and digitalWrite(S1, LOW) | Sets the output frequency to 20%, a good speed for pulseIn() |
| webAppsServer.begin(WIFI_SSID, WIFI_PASSWORD) | Joins the WiFi and starts HTTP on port 80 and WebSocket on port 81 |
| millis() check with 1000 | Takes a new sample once per second without blocking the server |
| S2/S3 pairs + pulseIn() + map() | Reads red (LOW LOW), green (HIGH HIGH) and blue (LOW HIGH) and scales each to 0–255 |
| constrain() + sprintf() | Clamps the values and builds the #RRGGBB text |
| customPage.sendToWeb() | Broadcasts the color to all open browsers |
The result is one short text message per second, light enough for any phone.
The Web Page (custom_page_html.h)
| Page Part | What It Does |
|---|---|
| CSS Minion | Draws the character with blinking eyes, a laughing mouth and roaming pupils |
| WebSocket client | Connects to the board on port 81 and listens for tagged messages |
| Color handler | Applies the HEX code to body, arms and eyelids with a smooth CSS transition |
| Reconnect timer | Tries again every 2 seconds if the link drops |
| Resize logic | Scales the Minion to fit phones, tablets and desktops |
The Message Format
Each message starts with a tag, so this page only reacts to its own data.
- ESP32 Uno sends: Color sensor:#2DB45A
- Page keeps: #2DB45A after it cuts off the tag
To build a page of your own on the same pattern, read ESP32 Uno - DIYables ESP32 WebApps Custom WebApp.
ESP32 Uno vs UNO R4 for This Project
This table lists what changes when the Minion project moves from the UNO R4 WiFi to the ESP32 Uno.
| Item | Arduino UNO R4 | ESP32 Uno |
|---|---|---|
| Logic voltage | 5V | 3.3V |
| Sensor VCC | 5V | 3.3V (pins are not 5V tolerant) |
| S0, S1, S2, S3, OUT | D4, D3, D6, D5, D7 | GPIO17, GPIO25, GPIO27, GPIO16, GPIO14 |
| Library | DIYables WebApps | DIYables ESP32 WebApps |
| Server factory | UnoR4ServerFactory | ESP32ServerFactory |
| WiFi setup | WiFi.begin() loop in setup() | webAppsServer.begin(ssid, password) |
| Arduino IDE board | Arduino UNO R4 WiFi | ESP32 Dev Module |
The sensor wires go to the same Uno header spots as before. Only the VCC wire changes, from 5V to 3.3V, so the OUT signal stays safe for the ESP32 Uno.
Try These Next
- Show the HEX code as large text under the Minion, so you can copy it.
- Add a "Freeze" button on the page that stops the updates, and handle it with onCustomMessageReceived().
- Name the color too: send "RED", "GREEN" or "BLUE" when one value is far above the other two.
- Save the last 10 colors and draw them as a strip of swatches on the page.
Troubleshooting
| Problem | Possible Cause | Solution |
|---|---|---|
| No COM port in Arduino IDE | CH340 driver missing or a charge-only USB cable | Install the CH340 driver and use a USB cable that carries data |
| Upload stops at Failed to connect or Waiting for download | Board did not enter download mode | Hold the BOOT button while the upload starts, release it when the percent count begins |
| Failed to connect to WiFi! repeats | Wrong SSID or password, or the router offers only 5 GHz | Check the two lines and join a 2.4 GHz network |
| Browser says the site cannot be reached | Phone is on mobile data or a guest network | Put the phone on the same WiFi as the board and use the printed IP |
| Minion never changes color | WebSocket on port 81 blocked or page opened before the board was ready | Reload the page and look for Sent to Minion lines in the Serial Monitor |
| Every color shows as #000000 or #FFFFFF | OUT not on D7 or calibration numbers too narrow | Check the OUT and S0 to S3 wires, then redo the calibration |
| Colors flicker between samples | Room light changes or the object moves | Hold the object 1 to 2 cm away and cover the sensor with a small tube |
| Sensor LEDs are on but values are random | VCC or GND loose | Press the jumpers in firmly and check 3.3V on VCC with a meter |
| Board restarts right after Network connected | USB port gives too little current when the WiFi radio starts | Plug into another USB port or a powered hub |
FAQ
Does the TCS3200 module run on 3.3V?
Yes. It works from 2.7V to 5.5V, and 3.3V is the best choice here. The OUT pulses then match the 3.3V input level of the ESP32 Uno.
What happens if I power the sensor from 5V by mistake?
OUT then sends 5V pulses into D7 (GPIO14). ESP32 Uno pins are rated for 3.3V, so this can damage the pin over time. Move VCC to 3.3V, or add a resistor divider on the OUT wire.
Why do I write 17 and 14 in code and not D4 and D7?
The ESP32 Uno core knows only GPIO numbers. D4 maps to GPIO17, D3 to GPIO25, D6 to GPIO27, D5 to GPIO16 and D7 to GPIO14. The D labels just show where the pins sit on the Uno-shaped board.
Can I run the UNO R4 version of this sketch on the ESP32 Uno?
No. The UNO R4 sketch uses UnoR4ServerFactory and the UNO R4 WiFi firmware checks. The ESP32 Uno needs the DIYables ESP32 WebApps library and ESP32ServerFactory. The color reading part is the same.
How accurate is the color the Minion shows?
It is a fair match, not a lab result. The TCS3200 has simple photodiode filters, and light, distance and surface gloss change the readings. Calibrate in the same light you test in.
How do I make the Minion update faster?
Change 1000 in the millis() check to a smaller value, like 300. Each sample still needs three pulseIn() calls, so going much below 100 ms gives little gain.
Can two phones watch the same Minion at once?
Yes. sendToWeb() broadcasts to every connected client, so each open browser gets the same color at the same time.
Can I put an Uno shield on the ESP32 Uno for this project?
Often yes, if the shield works with 3.3V logic and does not use D3 to D7. Check that the shield does not drive any of the five sensor pins.
What if this build needs more pins than the Uno headers offer?
The ESP32 Uno has extra holes near the power header: GPIO32 and GPIO33 (I/O, PWM, analog on ADC1, so they still read analog while WiFi is on) and GPIO15 (I/O, PWM, analog on ADC2). Solder pin headers and use the GPIO number in code. For this project, GPIO32/33 are a good spot for a light sensor or a second module next to the color sensor. Two warnings: GPIO15 and GPIO0 (the IO0 pin at the unused Uno NC spot) are boot strapping pins, so a wrong connection can stop booting or uploading; use GPIO32/33 first. Never use the six holes under the digital header (SD0 to SD3, CMD, CLK = GPIO6 to GPIO11); they go to the flash chip and using them crashes the board.
Can I view the colors from outside my home WiFi?
Not with this sketch alone. The server only lives on your local network. For remote access, you need port forwarding, a VPN, or a cloud service such as MQTT.