🤖 Build Your Own Webcam Hand-Gesture Controlled RGB LED Strip Using Arduino Uno
🤖 Build Your Own Webcam Hand-Gesture Controlled RGB LED Strip Using Arduino Uno
📅 By Dinesh | LearnWithDTrend Blog | 2026
🚀 Introduction
Have you ever wanted to control an RGB LED strip just by showing hand gestures in front of a laptop webcam?
In this project, I built a simple and fun gesture-controlled lighting system using:
✅ Arduino Uno
✅ 12V RGB LED strip
✅ BC547 transistor driver stage
✅ Laptop webcam
✅ HTML-based hand gesture detection
The idea is simple: when you show 5 fingers, the strip glows red. When you show 2 fingers, it glows green. When you show 1 finger, it glows blue.
This project is a great example of combining computer vision, web technology, and embedded systems in one compact build.
🧠 Project Concept
Here’s how the system works:
The webcam captures your hand.
The HTML page detects how many fingers are visible.
Based on the gesture, the webpage sends a serial command to Arduino.
Arduino reads the command and switches the RGB LED strip.
The strip lights up in the selected color.
That means your hand becomes the controller.
🧰 Components Used
| Component | Quantity |
|---|---|
| Arduino Uno | 1 |
| 12V RGB LED Strip | 1 |
| BC547 Transistor | 3 |
| 1kΩ Resistor | 3 |
| Webcam Laptop / PC | 1 |
| 12V Battery or Adapter | 1 |
| Jumper Wires | As needed |
| Breadboard / Perfboard | As needed |
🔌 Connections
Arduino Pin Configuration
| Arduino Pin | RGB Function |
|---|---|
| D3 | Red channel |
| D5 | Green channel |
| D6 | Blue channel |
BC547 Transistor Wiring
Each RGB channel uses one BC547 transistor.
Arduino pin (D3 / D5 / D6) → 1kΩ resistor → BC547 base
BC547 emitter → GND
BC547 collector → corresponding RGB strip color wire
12V strip positive → +12V battery/adapter positive
Battery negative → Arduino GND
Common ground must be shared between Arduino and power supply
Important Note
BC547 is suitable only for low-current lighting sections. If your RGB strip is long or draws more current, a MOSFET driver is a better option.
📟 Arduino Code
The Arduino listens for serial commands from the browser and controls the RGB strip.
#define RED_PIN 3
#define GREEN_PIN 5
#define BLUE_PIN 6
void setColor(byte red, byte green, byte blue) {
analogWrite(RED_PIN, red);
analogWrite(GREEN_PIN, green);
analogWrite(BLUE_PIN, blue);
}
void setup() {
pinMode(RED_PIN, OUTPUT);
pinMode(GREEN_PIN, OUTPUT);
pinMode(BLUE_PIN, OUTPUT);
Serial.begin(9600);
setColor(0, 0, 0);
}
void loop() {
if (Serial.available()) {
char cmd = Serial.read();
if (cmd == '5') {
setColor(255, 0, 0); // Red
}
else if (cmd == '2') {
setColor(0, 255, 0); // Green
}
else if (cmd == '1') {
setColor(0, 0, 255); // Blue
}
else if (cmd == '0') {
setColor(0, 0, 0); // Off
}
}
}
🌐 HTML Web Interface
This HTML page does two jobs:
Uses the webcam to detect hand gestures
Sends the gesture result to Arduino through Web Serial
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Hand Gesture RGB Control</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
background: #111;
color: #fff;
margin: 0;
padding: 20px;
}
video, canvas {
width: 640px;
max-width: 95vw;
border: 2px solid #444;
border-radius: 10px;
margin-top: 12px;
}
button {
padding: 12px 18px;
font-size: 16px;
border: none;
border-radius: 8px;
margin: 8px;
cursor: pointer;
}
#status {
margin-top: 12px;
font-size: 18px;
}
</style>
</head>
<body>
<h2>Gesture Control for RGB Strip</h2>
<button id="connectBtn">Connect Arduino</button>
<div id="status">Status: Not connected</div>
<video id="video" autoplay playsinline muted></video>
<canvas id="canvas" width="640" height="480"></canvas>
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/hands/hands.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/camera_utils/camera_utils.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/drawing_utils/drawing_utils.js"></script>
<script>
const video = document.getElementById("video");
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const statusText = document.getElementById("status");
const connectBtn = document.getElementById("connectBtn");
let port = null;
let writer = null;
let lastSent = "";
let stableCount = 0;
let lastGesture = "";
async function connectArduino() {
try {
port = await navigator.serial.requestPort();
await port.open({ baudRate: 9600 });
writer = port.writable.getWriter();
statusText.textContent = "Status: Arduino connected";
} catch (err) {
console.error(err);
statusText.textContent = "Status: Connection failed";
}
}
async function sendCommand(cmd) {
if (!writer) return;
const data = new TextEncoder().encode(cmd);
await writer.write(data);
}
connectBtn.addEventListener("click", connectArduino);
function countFingers(landmarks, handednessLabel) {
const tips = [8, 12, 16, 20];
const pips = [6, 10, 14, 18];
let count = 0;
if (handednessLabel === "Right") {
if (landmarks[4].x < landmarks[3].x) count++;
} else {
if (landmarks[4].x > landmarks[3].x) count++;
}
for (let i = 0; i < 4; i++) {
if (landmarks[tips[i]].y < landmarks[pips[i]].y) count++;
}
return count;
}
function gestureToCommand(fingers) {
if (fingers === 5) return "5";
if (fingers === 2) return "2";
if (fingers === 1) return "1";
return "0";
}
const hands = new Hands({
locateFile: (file) => `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`
});
hands.setOptions({
maxNumHands: 1,
modelComplexity: 1,
minDetectionConfidence: 0.7,
minTrackingConfidence: 0.7
});
hands.onResults((results) => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(results.image, 0, 0, canvas.width, canvas.height);
if (results.multiHandLandmarks && results.multiHandLandmarks.length > 0) {
const landmarks = results.multiHandLandmarks[0];
const handednessLabel = results.multiHandedness[0].label;
drawConnectors(ctx, landmarks, HAND_CONNECTIONS, { color: "#00FF00", lineWidth: 2 });
drawLandmarks(ctx, landmarks, { color: "#FF0000", lineWidth: 1 });
const fingers = countFingers(landmarks, handednessLabel);
const command = gestureToCommand(fingers);
if (command === lastGesture) {
stableCount++;
} else {
stableCount = 0;
lastGesture = command;
}
if (stableCount > 4 && command !== lastSent) {
sendCommand(command);
lastSent = command;
statusText.textContent = `Detected: ${fingers} fingers → Sent ${command}`;
} else {
statusText.textContent = `Detected: ${fingers} fingers`;
}
} else {
statusText.textContent = "No hand detected";
}
});
async function startCamera() {
const stream = await navigator.mediaDevices.getUserMedia({
video: { width: 640, height: 480 }
});
video.srcObject = stream;
const camera = new Camera(video, {
onFrame: async () => {
await hands.send({ image: video });
},
width: 640,
height: 480
});
camera.start();
}
startCamera().catch(err => {
console.error(err);
statusText.textContent = "Camera access failed";
});
</script>
</body>
</html>
🧠 How the System Works
Here is the working flow of the project:
The webcam detects your hand.
The HTML page counts the number of raised fingers.
The command is sent to Arduino through USB serial communication.
Arduino reads the command and drives the RGB strip.
The BC547 transistors act as switching devices for the LED channels.
Gesture to Color Mapping
| Gesture | Command | Color |
|---|---|---|
| 5 fingers | 5 | Red |
| 2 fingers | 2 | Green |
| 1 finger | 1 | Blue |
| No valid gesture | 0 | Off |
🛠️ Build Process
First, I connected the RGB strip to the BC547 transistor driver stage and shared the ground between the Arduino and the 12V supply.
Next, I uploaded the Arduino code and checked whether the strip responded properly to serial commands.
Then, I opened the HTML page in the browser, allowed webcam access, and connected the Arduino using Web Serial.
Finally, I tested the gestures:
Showing 5 fingers turned the strip red
Showing 2 fingers turned the strip green
Showing 1 finger turned the strip blue
🎮 Control Features
Webcam-based hand detection
Finger count recognition
Browser-to-Arduino serial communication
Automatic RGB color switching
Simple and interactive gesture control
📌 Important Notes
Open the HTML file in Chrome or Edge.
Run it from a local server because Web Serial and camera access need browser permissions.
BC547 is fine for small loads, but for a higher-power RGB strip, use a MOSFET.
Make sure the Arduino GND and 12V power GND are connected together.
🎉 Final Result
✅ Webcam gesture detection working
✅ Arduino serial communication working
✅ RGB LED strip switching properly
✅ Red / Green / Blue colors mapped to hand gestures
✅ A clean mini-project that mixes hardware and web technology
This project is a simple but impressive way to show how AI-style hand detection, HTML, and Arduino electronics can work together.
❤️ Let’s Connect
You can use this project for your blog, mini project submission, or portfolio demo.
It also makes a nice beginner-friendly project for students who want to learn:
Arduino programming
Webcam-based gesture detection
HTML and JavaScript control
Serial communication
Transistor switching for LED strips
LearnWithDTrend Blog Draft — ready for publishing
Comments
Post a Comment