Node.js Raspberry Pi RGB LED s WebSocket


Použití pulzně-šířkové modulace

V předchozích kapitolách jsme se naučili používat WebSocket a jak používat GPIO k zapínání a vypínání LED.

V této kapitole použijeme RGB LED s PWM (Pulse-width modulation) k zobrazení různých barev na základě vstupu uživatele přes WebSocket.

RGB LED je LED se 3 různými barvami. Má ČERVENOU, ZELENOU a MODROU LED (RGB LED).

A pomocí PWM můžeme nastavit individuální sílu 3 LED. To nám umožní je smíchat, nastavit barvu.


Co potřebujeme?

V této kapitole vytvoříme příklad, kdy ovládáme RGB LED s webovou stránkou přes WebSocket.

K tomu potřebujete:

Kliknutím na odkazy ve výše uvedeném seznamu zobrazíte popisy různých součástí.

Poznámka: Rezistor, který potřebujete, se může lišit od toho, co používáme v závislosti na typu použité LED. Většina malých LED potřebuje pouze malý odpor, kolem 200-500 ohmů. Obecně není rozhodující, jakou přesnou hodnotu použijete, ale čím menší je hodnota odporu, tím jasněji bude LED svítit.


Nainstalujte modul pigpio

Dříve jsme používali modul „onoff“, který funguje skvěle pro pouhé zapnutí a vypnutí. Nyní chceme nastavit sílu LED diod, takže potřebujeme modul GPIO s o něco větší funkčností.

Použijeme modul "pigpio" Node.js, protože to umožňuje PWM.

Pomocí PWM můžeme nastavit sílu LED od 0 do 255.

Modul "pigpio" Node.js je založen na knihovně pigpio C.

Pokud používáte "Lite" verzi Raspbianu, tato s největší pravděpodobností není součástí dodávky a musí být nainstalována ručně.

Aktualizujte svůj seznam systémových balíčků:

pi@w3demopi:~ $ sudo apt-get update

Nainstalujte knihovnu pigpio C:

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

Nyní můžeme nainstalovat modul "pigpio" Node.js pomocí npm:

pi@w3demopi:~ $ npm install pigpio

Nyní by měl být nainstalován modul „pigpio“ a můžeme jej použít k interakci s GPIO Raspberry Pi.

Poznámka: Protože modul "pigpio" používá knihovnu pigpio C, vyžaduje oprávnění root/sudo pro přístup k hardwarovým periferiím (jako je GPIO).


Budování okruhu

Nyní je čas postavit okruh na našem Breadboardu.

Pokud s elektronikou začínáte, doporučujeme Raspberry Pi vypnout. A použijte antistatickou podložku nebo zemnící pásek, abyste jej nepoškodili.

Vypněte správně Raspberry Pi příkazem:

pi@w3demopi:~ $ sudo shutdown -h now

Poté, co LED diody na Raspberry Pi přestanou blikat, vytáhněte zástrčku z Raspberry Pi (nebo otočte prodlužovací kabel, ke kterému je připojen).

Pouhé vytažení zástrčky bez řádného vypnutí může způsobit poškození paměťové karty.

Při stavbě tohoto obvodu je důležité vědět, zda máte společnou anodu nebo společnou katodu, RGB LED:

Můžete si to ověřit u svého poskytovatele nebo si to sami vyzkoušet:

Připojte kabely k GND a 3,3V kolíku. Připojte GND k nejdelší noze RGB LED a 3,3 V k jakékoli jiné noze. Pokud se rozsvítí, vaše RGB LED má společnou katodu. Pokud ne, má společnou anodu.

Raspberry Pi 3 s Breadboard.  RGB LED společná katoda

Podívejte se na výše uvedený obrázek obvodu.

  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. Na Breadboard zapojte odpor mezi levý a pravý sloupec zemní sběrnice pro řadu s MODROU nohou LED. V tomto příkladu jsme jej připojili k řádku 4, sloupci E a F

Váš obvod by nyní měl být kompletní a vaše připojení by měla vypadat velmi podobně jako na obrázku výše.

Nyní je čas nastartovat Raspberry Pi a napsat skript Node.js pro interakci s ním.

Raspberry Pi 3 s Breadboard.  Společná anoda RGB LED

Podívejte se na výše uvedený obrázek obvodu.

  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. Na Breadboardu připojte samčí nohu čtvrtého propojovacího vodiče ke stejné řadě pravého sloupku zemní sběrnice, ke kterému jste připojili společnou anodu. V tomto příkladu jsme jej připojili k řádku 2 sloupci F

Váš obvod by nyní měl být kompletní a vaše připojení by měla vypadat velmi podobně jako na obrázku výše.

Nyní je čas nastartovat Raspberry Pi a napsat skript Node.js pro interakci s ním.



Raspberry Pi a Node.js RGB LED a WebSocket Script

Přejděte do adresáře "nodetest" a vytvořte nový soubor s názvem " rgbws.js":

pi@w3demopi:~ $ nano rgbws.js

Soubor je nyní otevřený a lze jej upravovat pomocí vestavěného editoru Nano.

Napište nebo vložte následující:

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

Stisknutím " Ctrl+x" kód uložíte. Potvrďte pomocí „ y“ a potvrďte jméno pomocí „ Enter“.

Napište nebo vložte následující:

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

Stisknutím " Ctrl+x" kód uložíte. Potvrďte pomocí „ y“ a potvrďte jméno pomocí „ Enter“.


Uživatelské rozhraní Raspberry Pi a Node.js WebSocket

Nyní je čas přidat HTML, které umožňuje vstup uživatele přes WebSocket.

K tomu chceme:

  • 3 posuvníky barev, jeden pro každou barvu (RGB)
  • Výběr barvy
  • Div zobrazující aktuální barvu

Přejděte do složky „public“:

pi@w3demopi:~/nodetest $ cd public

A vytvořte soubor HTML, 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>

Návrat do složky "nodetest":

pi@w3demopi:~/nodetest $ cd ..

Spusťte kód:

pi@w3demopi:~ $ sudo node rgbws.js

Poznámka: Protože modul "pigpio" používá knihovnu pigpio C, vyžaduje oprávnění root/sudo pro přístup k hardwarovým periferiím (jako je GPIO).

Otevřete webovou stránku v prohlížeči pomocí http://[RaspberryPi_IP]:8080/

Nyní by RGB LED měla změnit barvu v závislosti na uživatelském vstupu.

Ukončete program pomocí Ctrl+c.