Node.js Raspberry Pi RGB LED met WebSocket


Pulsbreedtemodulatie gebruiken

In de vorige hoofdstukken hebben we geleerd hoe we WebSocket moeten gebruiken en hoe we GPIO kunnen gebruiken om LED's aan en uit te zetten.

In dit hoofdstuk gebruiken we een RGB LED, met PWM (Pulsbreedtemodulatie) om verschillende kleuren weer te geven op basis van gebruikersinvoer via WebSocket.

Een RGB LED is een LED met 3 verschillende kleuren. Het heeft een RODE, GROENE en BLAUWE LED (RGB LED).

En met behulp van PWM kunnen we de individuele sterkte van de 3 LED's instellen. Dit stelt ons in staat om ze te mengen, om een ​​kleur in te stellen.


Wat hebben we nodig?

In dit hoofdstuk maken we een voorbeeld waarbij we een RGB LED met een webpagina aansturen via WebSocket.

Hiervoor heb je nodig:

Klik op de links in de bovenstaande lijst voor beschrijvingen van de verschillende componenten.

Opmerking: de weerstand die u nodig heeft, kan verschillen van wat wij gebruiken, afhankelijk van het type LED dat u gebruikt. De meeste kleine LED's hebben slechts een kleine weerstand nodig, ongeveer 200-500 ohm. Het is over het algemeen niet kritisch welke waarde u precies gebruikt, maar hoe kleiner de waarde van de weerstand, hoe helderder de LED zal schijnen.


Installeer de pigpio-module

Eerder hebben we de "aan-uit"-module gebruikt, die prima werkt om gewoon aan en uit te zetten. Nu willen we de sterkte van de LED's instellen, dus we hebben een GPIO-module nodig met wat meer functionaliteit.

We zullen de "pigpio" Node.js-module gebruiken, omdat dit PWM mogelijk maakt.

Met PWM kunnen we de sterkte van een LED instellen van 0 tot 255.

De module "pigpio" Node.js is gebaseerd op de pigpio C-bibliotheek.

Als u de "Lite"-versie van Raspbian gebruikt, is deze waarschijnlijk niet inbegrepen en moet deze handmatig worden geïnstalleerd.

Werk uw systeempakketlijst bij:

pi@w3demopi:~ $ sudo apt-get update

Installeer de pigpio C-bibliotheek:

pi@w3demopi:~ $ sudo apt-get install pigpio

Nu kunnen we de "pigpio" Node.js-module installeren met npm:

pi@w3demopi:~ $ npm install pigpio

Nu moet de "pigpio" -module worden geïnstalleerd en kunnen we deze gebruiken om te communiceren met de GPIO van de Raspberry Pi.

Opmerking: aangezien de "pigpio"-module de pigpio C-bibliotheek gebruikt, zijn root/sudo-rechten vereist om toegang te krijgen tot hardware-randapparatuur (zoals de GPIO).


Het circuit bouwen

Nu is het tijd om het circuit op ons Breadboard te bouwen.

Als elektronica nieuw voor u is, raden we u aan de stroom voor de Raspberry Pi uit te schakelen. En gebruik een antistatische mat of een aardingsband om beschadiging te voorkomen.

Sluit de Raspberry Pi correct af met het commando:

pi@w3demopi:~ $ sudo shutdown -h now

Nadat de LED's op de Raspberry Pi niet meer knipperen, trekt u de stekker uit de Raspberry Pi (of draait u de stekkerdoos waarop deze is aangesloten uit).

Gewoon aan de stekker trekken zonder goed af te sluiten, kan de geheugenkaart beschadigen.

Bij het bouwen van dit circuit is het belangrijk om te weten of u een gemeenschappelijke anode of gemeenschappelijke kathode, RGB-led hebt:

U kunt dit navragen bij uw provider of het zelf testen:

Sluit kabels aan op GND en 3.3V pin. Sluit GND aan op de langste poot van de RGB-led en de 3,3 V op een andere poot. Als het oplicht, heeft uw RGB-led een gemeenschappelijke kathode. Zo niet, dan heeft het een gemeenschappelijke anode.

Raspberry Pi 3 met Breadboard.  RGB LED gemeenschappelijke kathode

Kijk naar de bovenstaande afbeelding van het circuit.

  1. On the Breadboard, connect the RGB LED to the right ground bus column, and make sure that each leg connects to a different row. The longest leg is the common cathode leg. In this example we have connected the LED to rows 1-4, with the common cathode leg connected to row 2 column I. The RED leg is connected to row 1 column J, the GREEN leg is connected to row 3 column J, and the BLUE leg is connected to row 4 column J
  2. On the Raspberry Pi, connect the female leg of the first jumper wire to Ground. You can use any GND pin. In this example we used Physical Pin 9 (GND, row 5, left column)
  3. On the Breadboard, connect the male leg of the first jumper wire to the same row of the right ground bus column that you connected the common cathode to. In this example we connected it to row 2 column F
  4. On the Raspberry Pi, connect the female leg of the second jumper cable to a GPIO pin. We will use this for the RED leg, In this example we used Physical Pin 7 (GPIO 4, row 4, left column)
  5. On the Breadboard, connect the male leg of the second jumper wire to the left ground bus, same row as the RED leg of the LED is connected. In this example we connected it to row 1, column A
  6. On the Breadboard, connect a resistor between the left and right ground bus columns for the row with the RED leg of the LED. In this example we have attached it to row 1, column E and F
  7. On the Raspberry Pi, connect the female leg of the third jumper cable to a GPIO pin. We will use this for the GREEN leg, In this example we used Physical Pin 11 (GPIO 17, row 6, left column)
  8. On the Breadboard, connect the male leg of the third jumper wire to the left ground bus, same row as the GREEN leg of the LED is connected. In this example we connected it to row 3, column A
  9. On the Breadboard, connect a resistor between the left and right ground bus columns for the row with the GREEN leg of the LED. In this example we have attached it to row 3, column E and F
  10. On the Raspberry Pi, connect the female leg of the forth jumper cable to a GPIO pin. We will use this for the BLUE leg, In this example we used Physical Pin 13 (GPIO 27, row 7, left column)
  11. On the Breadboard, connect the male leg of the forth jumper wire to the left ground bus, same row as the BLUE leg of the LED is connected. In this example we connected it to row 4, column A
  12. Sluit op het Breadboard een weerstand aan tussen de linker en rechter massabuskolommen voor de rij met de BLAUWE poot van de LED. In dit voorbeeld hebben we het gekoppeld aan rij 4, kolom E en F

Je circuit zou nu compleet moeten zijn en je verbindingen zouden er ongeveer hetzelfde uit moeten zien als in de bovenstaande afbeelding.

Nu is het tijd om de Raspberry Pi op te starten en het Node.js-script te schrijven om ermee te communiceren.

Raspberry Pi 3 met Breadboard.  RGB LED gemeenschappelijke anode

Kijk naar de bovenstaande afbeelding van het circuit.

  1. On the Breadboard, connect the RGB LED to the right ground bus column, and make sure that each leg connects to a different row. The longest leg is the common anode leg. In this example we have connected the LED to rows 1-4, with the common cathode leg connected to row 2 column I. The RED leg is connected to row 1 column J, the GREEN leg is connected to row 3 column J, and the BLUE leg is connected to row 4 column J
  2. On the Raspberry Pi, connect the female leg of the first jumper cable to a GPIO pin. We will use this for the RED leg, In this example we used Physical Pin 7 (GPIO 4, row 4, left column)
  3. On the Breadboard, connect the male leg of the first jumper wire to the left ground bus, same row as the RED leg of the LED is connected. In this example we connected it to row 1, column A
  4. On the Breadboard, connect a resistor between the left and right ground bus columns for the row with the RED leg of the LED. In this example we have attached it to row 1, column E and F
  5. On the Raspberry Pi, connect the female leg of the second jumper cable to a GPIO pin. We will use this for the GREEN leg, In this example we used Physical Pin 11 (GPIO 17, row 6, left column)
  6. On the Breadboard, connect the male leg of the second jumper wire to the left ground bus, same row as the GREEN leg of the LED is connected. In this example we connected it to row 3, column A
  7. On the Breadboard, connect a resistor between the left and right ground bus columns for the row with the GREEN leg of the LED. In this example we have attached it to row 3, column E and F
  8. On the Raspberry Pi, connect the female leg of the third jumper cable to a GPIO pin. We will use this for the BLUE leg, In this example we used Physical Pin 13 (GPIO 27, row 7, left column)
  9. On the Breadboard, connect the male leg of the third jumper wire to the left ground bus, same row as the BLUE leg of the LED is connected. In this example we connected it to row 4, column A
  10. On the Breadboard, connect a resistor between the left and right ground bus columns for the row with the BLUE leg of the LED. In this example we have attached it to row 4, column E and F
  11. On the Raspberry Pi, connect the female leg of the forth jumper wire to 3.3V. In this example we used Physical Pin 1 (3.3V, row 1, left column)
  12. Sluit op de Breadboard het mannelijke been van de vierde jumperdraad aan op dezelfde rij van de rechter grondbuskolom waarop u de gemeenschappelijke anode hebt aangesloten. In dit voorbeeld hebben we het verbonden met rij 2 kolom F

Je circuit zou nu compleet moeten zijn en je verbindingen zouden er ongeveer hetzelfde uit moeten zien als in de bovenstaande afbeelding.

Nu is het tijd om de Raspberry Pi op te starten en het Node.js-script te schrijven om ermee te communiceren.



Raspberry Pi en Node.js RGB LED en WebSocket-script

Ga naar de map "nodetest" en maak een nieuw bestand aan met de naam " rgbws.js":

pi@w3demopi:~ $ nano rgbws.js

Het bestand is nu geopend en kan worden bewerkt met de ingebouwde Nano Editor.

Schrijf of plak het volgende:

rgbws.js

var http = require('http').createServer(handler); //require http server, and create server with function handler()
var fs = require('fs'); //require filesystem module
var io = require('socket.io')(http) //require socket.io module and pass the http object (server)
var Gpio = require('pigpio').Gpio, //include pigpio to interact with the GPIO
ledRed = new Gpio(4, {mode: Gpio.OUTPUT}), //use GPIO pin 4 as output for RED
ledGreen = new Gpio(17, {mode: Gpio.OUTPUT}), //use GPIO pin 17 as output for GREEN
ledBlue = new Gpio(27, {mode: Gpio.OUTPUT}), //use GPIO pin 27 as output for BLUE
redRGB = 0, //set starting value of RED variable to off (0 for common cathode)
greenRGB = 0, //set starting value of GREEN variable to off (0 for common cathode)
blueRGB = 0; //set starting value of BLUE variable to off (0 for common cathode)

//RESET RGB LED
ledRed.digitalWrite(0); // Turn RED LED off
ledGreen.digitalWrite(0); // Turn GREEN LED off
ledBlue.digitalWrite(0); // Turn BLUE LED off

http.listen(8080); //listen to port 8080

function handler (req, res) { //what to do on requests to port 8080
  fs.readFile(__dirname + '/public/rgb.html', function(err, data) { //read file rgb.html in public folder
    if (err) {
      res.writeHead(404, {'Content-Type': 'text/html'}); //display 404 on error
      return res.end("404 Not Found");
    }
    res.writeHead(200, {'Content-Type': 'text/html'}); //write HTML
    res.write(data); //write data from rgb.html
    return res.end();
  });
}

io.sockets.on('connection', function (socket) {// Web Socket Connection
  socket.on('rgbLed', function(data) { //get light switch status from client
    console.log(data); //output data from WebSocket connection to console

    //for common cathode RGB LED 0 is fully off, and 255 is fully on
    redRGB=parseInt(data.red);
    greenRGB=parseInt(data.green);
    blueRGB=parseInt(data.blue);

    ledRed.pwmWrite(redRGB); //set RED LED to specified value
    ledGreen.pwmWrite(greenRGB); //set GREEN LED to specified value
    ledBlue.pwmWrite(blueRGB); //set BLUE LED to specified value
  });
});

process.on('SIGINT', function () { //on ctrl+c
  ledRed.digitalWrite(0); // Turn RED LED off
  ledGreen.digitalWrite(0); // Turn GREEN LED off
  ledBlue.digitalWrite(0); // Turn BLUE LED off
  process.exit(); //exit completely
});

Druk op " Ctrl+x" om de code op te slaan. Bevestig met " y" en bevestig de naam met " Enter".

Schrijf of plak het volgende:

rgbws.js

var http = require('http').createServer(handler); //require http server, and create server with function handler()
var fs = require('fs'); //require filesystem module
var io = require('socket.io')(http) //require socket.io module and pass the http object (server)
var Gpio = require('pigpio').Gpio, //include pigpio to interact with the GPIO
ledRed = new Gpio(4, {mode: Gpio.OUTPUT}), //use GPIO pin 4 as output for RED
ledGreen = new Gpio(17, {mode: Gpio.OUTPUT}), //use GPIO pin 17 as output for GREEN
ledBlue = new Gpio(27, {mode: Gpio.OUTPUT}), //use GPIO pin 27 as output for BLUE
redRGB = 255, //set starting value of RED variable to off (255 for common anode)
greenRGB = 255, //set starting value of GREEN variable to off (255 for common anode)
blueRGB = 255; //set starting value of BLUE variable to off (255 for common anode)

//RESET RGB LED
ledRed.digitalWrite(1); // Turn RED LED off
ledGreen.digitalWrite(1); // Turn GREEN LED off
ledBlue.digitalWrite(1); // Turn BLUE LED off

http.listen(8080); //listen to port 8080

function handler (req, res) { //what to do on requests to port 8080
  fs.readFile(__dirname + '/public/rgb.html', function(err, data) { //read file rgb.html in public folder
    if (err) {
      res.writeHead(404, {'Content-Type': 'text/html'}); //display 404 on error
      return res.end("404 Not Found");
    }
    res.writeHead(200, {'Content-Type': 'text/html'}); //write HTML
    res.write(data); //write data from rgb.html
    return res.end();
  });
}

io.sockets.on('connection', function (socket) {// Web Socket Connection
  socket.on('rgbLed', function(data) { //get light switch status from client
    console.log(data); //output data from WebSocket connection to console

    //for common anode RGB LED  255 is fully off, and 0 is fully on, so we have to change the value from the client
    redRGB=255-parseInt(data.red);
    greenRGB=255-parseInt(data.green);
    blueRGB=255-parseInt(data.blue);

    console.log("rbg: " + redRGB + ", " + greenRGB + ", " + blueRGB); //output converted to console

    ledRed.pwmWrite(redRGB); //set RED LED to specified value
    ledGreen.pwmWrite(greenRGB); //set GREEN LED to specified value
    ledBlue.pwmWrite(blueRGB); //set BLUE LED to specified value
  });
});

process.on('SIGINT', function () { //on ctrl+c
  ledRed.digitalWrite(1); // Turn RED LED off
  ledGreen.digitalWrite(1); // Turn GREEN LED off
  ledBlue.digitalWrite(1); // Turn BLUE LED off
  process.exit(); //exit completely
});

Druk op " Ctrl+x" om de code op te slaan. Bevestig met " y" en bevestig de naam met " Enter".


Raspberry Pi en Node.js WebSocket-gebruikersinterface

Nu is het tijd om de HTML toe te voegen die gebruikersinvoer via WebSocket mogelijk maakt.

Hiervoor willen we:

  • 3 kleurschuifregelaars, één voor elke kleur (RGB)
  • Een kleurenkiezer
  • Een div met de huidige kleur

Ga naar de map "openbaar":

pi@w3demopi:~/nodetest $ cd public

En maak een HTML-bestand, rgb.html:

pi@w3demopi:~/nodetest/public $ nano rgb.html

rgb.html:

<!DOCTYPE html>
<html>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<style>
.slider {
  -webkit-appearance: none;
  width: 100%;
  height: 15px;
  border-radius: 5px;
  background: #d3d3d3;
  outline: none;
  opacity: 0.7;
  -webkit-transition: .2s;
  transition: opacity .2s;
}

.slider:hover {opacity: 1;}

.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 25px;
  height: 25px;
  border-radius: 50%;
  cursor: pointer;
}

.slider::-moz-range-thumb {
  width: 25px;
  height: 25px;
  border-radius: 50%;
  background: #4CAF50;
  cursor: pointer;
}
#redSlider::-webkit-slider-thumb {background: red;}
#redSlider::-moz-range-thumb {background: red;}
#greenSlider::-webkit-slider-thumb {background: green;}
#greenSlider::-moz-range-thumb {background: green;}
#blueSlider::-webkit-slider-thumb {background: blue;}
#blueSlider::-moz-range-thumb {background: blue;}
</style>
<body>

<div class="w3-container">
<h1>RGB Color</h1>
<div class="w3-cell-row">
<div class="w3-container w3-cell w3-mobile">
<p><input type="range" min="0" max="255" value="0" class="slider" id="redSlider"></p>
<p><input type="range" min="0" max="255" value="0" class="slider" id="greenSlider"></p>
<p><input type="range" min="0" max="255" value="0" class="slider" id="blueSlider"></p>
</div>
<div class="w3-container w3-cell w3-mobile" style="background-color:black" id="colorShow">
<div></div>
</div>
</div>
<p>Or pick a color: <input type="color" id="pickColor"></p>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>
<script src="https://www.w3schools.com/lib/w3color.js"></script>
<script>
var socket = io(); //load socket.io-client and connect to the host that serves the page
var rgb = w3color("rgb(0,0,0)"); //we use the w3color.js library to keep the color as an object
window.addEventListener("load", function(){ //when page loads
  var rSlider = document.getElementById("redSlider");
  var gSlider = document.getElementById("greenSlider");
  var bSlider = document.getElementById("blueSlider");
  var picker = document.getElementById("pickColor");

  rSlider.addEventListener("change", function() { //add event listener for when red slider changes
    rgb.red = this.value; //update the RED color according to the slider
    colorShow.style.backgroundColor = rgb.toRgbString(); //update the "Current color"
    socket.emit("rgbLed", rgb); //send the updated color to RGB LED via WebSocket
  });
  gSlider.addEventListener("change", function() { //add event listener for when green slider changes
    rgb.green = this.value; //update the GREEN color according to the slider
    colorShow.style.backgroundColor = rgb.toRgbString(); //update the "Current color"
    socket.emit("rgbLed", rgb); //send the updated color to RGB LED via WebSocket
  });
  bSlider.addEventListener("change", function() { //add event listener for when blue slider changes
    rgb.blue = this.value;  //update the BLUE color according to the slider
    colorShow.style.backgroundColor = rgb.toRgbString(); //update the "Current color"
    socket.emit("rgbLed", rgb); //send the updated color to RGB LED via WebSocket
  });
  picker.addEventListener("input", function() { //add event listener for when colorpicker changes
    rgb.red = w3color(this.value).red; //Update the RED color according to the picker
    rgb.green = w3color(this.value).green; //Update the GREEN color according to the picker
    rgb.blue = w3color(this.value).blue; //Update the BLUE color according to the picker
    colorShow.style.backgroundColor = rgb.toRgbString();  //update the "Current color"
    rSlider.value = rgb.red;  //Update the RED slider position according to the picker
    gSlider.value = rgb.green;  //Update the GREEN slider position according to the picker
    bSlider.value = rgb.blue;  //Update the BLUE slider position according to the picker
   socket.emit("rgbLed", rgb);  //send the updated color to RGB LED via WebSocket
  });
});
</script>

</body>
</html>

Keer terug naar de map "nodetest":

pi@w3demopi:~/nodetest $ cd ..

Voer de code uit:

pi@w3demopi:~ $ sudo node rgbws.js

Opmerking: aangezien de "pigpio"-module de pigpio C-bibliotheek gebruikt, zijn root/sudo-rechten vereist om toegang te krijgen tot hardware-randapparatuur (zoals de GPIO).

Open de website in een browser met behulp van http://[RaspberryPi_IP]:8080/

Nu moet de RGB-led van kleur veranderen, afhankelijk van de gebruikersinvoer.

Sluit het programma af met Ctrl+c.