Node.js Raspberry Pi RGB-LED mit WebSocket


Verwendung von Pulsweitenmodulation

In den vorherigen Kapiteln haben wir gelernt, wie man WebSocket verwendet und wie man GPIO verwendet, um LEDs ein- und auszuschalten.

In diesem Kapitel verwenden wir eine RGB-LED mit PWM (Pulsweitenmodulation), um verschiedene Farben basierend auf Benutzereingaben über WebSocket anzuzeigen.

Eine RGB-LED ist eine LED mit 3 verschiedenen Farben. Es verfügt über eine ROTE, GRÜNE und BLAUE LED (RGB-LED).

Und per PWM können wir die individuelle Stärke der 3 LEDs einstellen. Dies ermöglicht es uns, sie zu mischen, um eine Farbe festzulegen.


Was brauchen wir?

In diesem Kapitel erstellen wir ein Beispiel, in dem wir eine RGB-LED mit einer Webseite über WebSocket steuern.

Dazu benötigen Sie:

Klicken Sie auf die Links in der obigen Liste, um Beschreibungen der verschiedenen Komponenten zu erhalten.

Hinweis: Der benötigte Widerstand kann je nach verwendetem LED-Typ von dem abweichen, was wir verwenden. Die meisten kleinen LEDs benötigen nur einen kleinen Widerstand, etwa 200-500 Ohm. Es ist im Allgemeinen nicht entscheidend, welchen genauen Wert Sie verwenden, aber je kleiner der Wert des Widerstands ist, desto heller leuchtet die LED.


Installieren Sie das Pigpio-Modul

Früher haben wir das "onoff"-Modul verwendet, das sich hervorragend zum einfachen Ein- und Ausschalten eignet. Jetzt wollen wir die Stärke der LEDs einstellen, also brauchen wir ein GPIO-Modul mit etwas mehr Funktionalität.

Wir werden das Node.js-Modul "pigpio" verwenden, da dies PWM ermöglicht.

Mit PWM können wir die Stärke einer LED von 0 bis 255 einstellen.

Das Node.js-Modul „pigpio“ basiert auf der C-Bibliothek pigpio.

Wenn Sie die „Lite“-Version von Raspbian verwenden, ist diese höchstwahrscheinlich nicht enthalten und muss manuell installiert werden.

Aktualisieren Sie Ihre Systempaketliste:

pi@w3demopi:~ $ sudo apt-get update

Installieren Sie die pigpio C-Bibliothek:

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

Jetzt können wir das Node.js-Modul "pigpio" mit npm installieren:

pi@w3demopi:~ $ npm install pigpio

Nun sollte das Modul „pigpio“ installiert sein und wir können damit mit dem GPIO des Raspberry Pi interagieren.

Hinweis: Da das „pigpio“-Modul die pigpio-C-Bibliothek verwendet, benötigt es root/sudo-Rechte, um auf Hardware-Peripheriegeräte (wie GPIO) zuzugreifen.


Aufbau der Schaltung

Jetzt ist es Zeit, die Schaltung auf unserem Breadboard zu bauen.

Wenn Sie neu in der Elektronik sind, empfehlen wir Ihnen, den Strom für den Raspberry Pi auszuschalten. Und verwenden Sie eine antistatische Matte oder ein Erdungsband, um Beschädigungen zu vermeiden.

Fahren Sie den Raspberry Pi ordnungsgemäß herunter mit dem Befehl:

pi@w3demopi:~ $ sudo shutdown -h now

Nachdem die LEDs auf dem Raspberry Pi aufgehört haben zu blinken, ziehen Sie den Netzstecker aus dem Raspberry Pi (oder schalten Sie die Steckdosenleiste aus, an die er angeschlossen ist).

Das Ziehen des Steckers ohne ordnungsgemäßes Herunterfahren kann zu einer Beschädigung der Speicherkarte führen.

Beim Aufbau dieser Schaltung ist es wichtig zu wissen, ob Sie eine gemeinsame Anode oder gemeinsame Kathode, RGB-LED, haben:

Sie können bei Ihrem Anbieter nachfragen oder es selbst testen:

Schließen Sie die Kabel an GND und 3,3 V Pin an. Verbinden Sie GND mit dem längsten Bein der RGB-LED und die 3,3 V mit jedem anderen Bein. Wenn es aufleuchtet, hat Ihre RGB-LED eine gemeinsame Kathode. Wenn nicht, hat es eine gemeinsame Anode.

Raspberry Pi 3 mit Steckbrett.  Gemeinsame RGB-LED-Kathode

Sehen Sie sich die obige Abbildung der Schaltung an.

  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. Verbinden Sie auf dem Steckbrett einen Widerstand zwischen der linken und rechten Erdungsbussäule für die Reihe mit dem BLAUEN Bein der LED. In diesem Beispiel haben wir es an Zeile 4, Spalte E und F angehängt

Ihre Schaltung sollte jetzt vollständig sein und Ihre Verbindungen sollten der obigen Abbildung ziemlich ähnlich aussehen.

Jetzt ist es an der Zeit, den Raspberry Pi hochzufahren und das Node.js-Skript zu schreiben, um damit zu interagieren.

Raspberry Pi 3 mit Steckbrett.  Gemeinsame Anode für RGB-LEDs

Sehen Sie sich die obige Abbildung der Schaltung an.

  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. Verbinden Sie auf dem Breadboard das männliche Bein des vierten Überbrückungskabels mit derselben Reihe der rechten Massebusspalte, mit der Sie die gemeinsame Anode verbunden haben. In diesem Beispiel haben wir es mit Zeile 2 Spalte F verbunden

Ihre Schaltung sollte jetzt vollständig sein und Ihre Verbindungen sollten der obigen Abbildung ziemlich ähnlich aussehen.

Jetzt ist es an der Zeit, den Raspberry Pi hochzufahren und das Node.js-Skript zu schreiben, um damit zu interagieren.



Raspberry Pi und Node.js RGB-LED und WebSocket-Skript

Gehen Sie in das Verzeichnis „nodetest“ und erstellen Sie eine neue Datei mit dem Namen „ rgbws.js“:

pi@w3demopi:~ $ nano rgbws.js

Die Datei ist nun geöffnet und kann mit dem eingebauten Nano Editor bearbeitet werden.

Schreiben oder fügen Sie Folgendes ein:

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
});

Drücken Sie „ Ctrl+x“, um den Code zu speichern. Bestätigen Sie mit „ y“ und bestätigen Sie den Namen mit „ Enter“.

Schreiben oder fügen Sie Folgendes ein:

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
});

Drücken Sie „ Ctrl+x“, um den Code zu speichern. Bestätigen Sie mit „ y“ und bestätigen Sie den Namen mit „ Enter“.


Raspberry Pi und Node.js WebSocket-Benutzeroberfläche

Jetzt ist es an der Zeit, den HTML-Code hinzuzufügen, der Benutzereingaben über WebSocket ermöglicht.

Dafür wollen wir:

  • 3 Farbregler, einer für jede Farbe (RGB)
  • Ein Farbwähler
  • Ein div, das die aktuelle Farbe anzeigt

Gehen Sie in den Ordner "öffentlich":

pi@w3demopi:~/nodetest $ cd public

Und erstellen Sie eine HTML-Datei, 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>

Kehren Sie zum Ordner "nodetest" zurück:

pi@w3demopi:~/nodetest $ cd ..

Führen Sie den Code aus:

pi@w3demopi:~ $ sudo node rgbws.js

Hinweis: Da das „pigpio“-Modul die pigpio-C-Bibliothek verwendet, benötigt es root/sudo-Rechte, um auf Hardware-Peripheriegeräte (wie GPIO) zuzugreifen.

Öffnen Sie die Website in einem Browser mit http://[RaspberryPi_IP]:8080/

Jetzt sollte die RGB-LED je nach Benutzereingabe die Farbe ändern.

Beenden Sie das Programm mit Ctrl+c.