Node.js Raspberry Pi RGB LED with WebSocket

Welcome to The Coding College! In this tutorial, you’ll learn how to control an RGB LED connected to a Raspberry Pi using Node.js and WebSocket. This project allows real-time color changes directly from a web browser, making it a perfect starting point for IoT enthusiasts.

What You’ll Learn

  1. How to control an RGB LED using Raspberry Pi GPIO pins.
  2. How to use WebSocket for real-time communication between the browser and Node.js.
  3. How to combine hardware and software for interactive projects.

Prerequisites

  1. A Raspberry Pi with Node.js installed.
  2. Basic understanding of RGB LEDs and GPIO pins.
  3. A computer or mobile device connected to the same network as the Raspberry Pi.

Hardware Requirements

  • Raspberry Pi (any model with GPIO pins).
  • 1 x RGB LED.
  • 3 x Resistors (330Ω recommended).
  • Jumper wires.
  • Breadboard.

Circuit Setup

  1. Connect the common cathode (negative pin) of the RGB LED to a ground pin (GND) on the Raspberry Pi.
  2. Connect the red, green, and blue pins of the RGB LED to GPIO pins through resistors.

Example GPIO Pin Assignment

LED ColorGPIO PinPhysical Pin
RedGPIO17Pin 11
GreenGPIO22Pin 15
BlueGPIO24Pin 18

Installing Required Libraries

Install the following libraries for this project:

npm install express ws onoff

Project Structure

rgb-websocket/
│
├── server.js  # Node.js server code
├── public/
│   └── index.html  # Frontend code

Writing the Code

Step 1: Node.js WebSocket Server

  1. Create a file named server.js:
const express = require('express');
const WebSocket = require('ws');
const Gpio = require('onoff').Gpio;

const app = express();
const server = require('http').createServer(app);
const wss = new WebSocket.Server({ server });

// Serve static files
app.use(express.static('public'));

// Configure GPIO pins for RGB LED
const red = new Gpio(17, 'out');
const green = new Gpio(22, 'out');
const blue = new Gpio(24, 'out');

// Helper function to set RGB values
const setRGB = (r, g, b) => {
    red.writeSync(r);
    green.writeSync(g);
    blue.writeSync(b);
};

// Handle WebSocket connections
wss.on('connection', (ws) => {
    console.log('WebSocket connection established.');

    ws.on('message', (message) => {
        console.log('Received:', message);

        try {
            const { red, green, blue } = JSON.parse(message);
            setRGB(red, green, blue);
        } catch (error) {
            console.error('Invalid message format:', error);
        }
    });

    ws.on('close', () => {
        console.log('WebSocket connection closed.');
        setRGB(0, 0, 0); // Turn off the LED
    });
});

// Graceful shutdown
process.on('SIGINT', () => {
    setRGB(0, 0, 0);
    red.unexport();
    green.unexport();
    blue.unexport();
    console.log('Exiting...');
    process.exit();
});

// Start the server
const PORT = 3000;
server.listen(PORT, () => {
    console.log(`Server running at http://localhost:${PORT}`);
});

Step 2: Frontend Code

  1. Create a file named index.html in the public folder:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>RGB LED Control</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            text-align: center;
            margin-top: 50px;
        }
        input[type="range"] {
            width: 300px;
            margin: 10px;
        }
        .color-label {
            display: block;
            margin-top: 10px;
        }
    </style>
</head>
<body>
    <h1>Control RGB LED</h1>
    <div>
        <label class="color-label">Red</label>
        <input id="red" type="range" min="0" max="1" step="1" />
    </div>
    <div>
        <label class="color-label">Green</label>
        <input id="green" type="range" min="0" max="1" step="1" />
    </div>
    <div>
        <label class="color-label">Blue</label>
        <input id="blue" type="range" min="0" max="1" step="1" />
    </div>
    <script>
        const socket = new WebSocket(`ws://${location.hostname}:3000`);

        const sendRGB = () => {
            const red = parseInt(document.getElementById('red').value);
            const green = parseInt(document.getElementById('green').value);
            const blue = parseInt(document.getElementById('blue').value);

            socket.send(JSON.stringify({ red, green, blue }));
        };

        document.getElementById('red').addEventListener('input', sendRGB);
        document.getElementById('green').addEventListener('input', sendRGB);
        document.getElementById('blue').addEventListener('input', sendRGB);

        socket.onopen = () => console.log('WebSocket connected.');
        socket.onclose = () => console.log('WebSocket disconnected.');
    </script>
</body>
</html>

Running the Project

  1. Start the server:
node server.js
  1. Open a web browser and navigate to:
http://<your-raspberry-pi-ip>:3000

Testing the RGB LED

  1. Use the sliders in the web interface to adjust the red, green, and blue components of the LED.
  2. Observe the LED changing colors in real-time.

Enhancements

  1. Save Presets: Add buttons to save and load color presets.
  2. Gradient Animation: Add a script to cycle through colors automatically.
  3. Mobile Control: Optimize the interface for mobile devices.

Conclusion

This project demonstrates how to integrate Node.js, WebSocket, and Raspberry Pi GPIO for real-time RGB LED control. By combining hardware and software, you can build interactive and dynamic IoT applications.

For more coding and IoT tutorials, visit The Coding College.

Leave a Comment