Node.js Raspberry Pi RGB LED z WebSocket


Korzystanie z modulacji szerokości impulsu

W poprzednich rozdziałach dowiedzieliśmy się, jak korzystać z WebSocket i jak używać GPIO do włączania i wyłączania diod LED.

W tym rozdziale użyjemy diody LED RGB z modulacją szerokości impulsu (PWM) do wyświetlania różnych kolorów w oparciu o dane wprowadzone przez użytkownika za pośrednictwem WebSocket.

Dioda LED RGB to dioda LED o 3 różnych kolorach. Posiada diodę CZERWONĄ, ZIELONĄ i NIEBIESKĄ (LED RGB).

A za pomocą PWM możemy ustawić indywidualną moc 3 diod LED. To pozwoli nam je wymieszać, ustawić kolor.


Czego potrzebujemy?

W tym rozdziale stworzymy przykład, w którym sterujemy diodą LED RGB za pomocą strony internetowej za pośrednictwem WebSocket.

Do tego potrzebujesz:

Kliknij łącza na powyższej liście, aby uzyskać opisy różnych komponentów.

Uwaga: Rezystor, którego potrzebujesz, może różnić się od tego, którego używamy, w zależności od typu używanej diody LED. Większość małych diod LED potrzebuje tylko małego rezystora, około 200-500 omów. Zasadniczo nie jest decydujące, jakiej dokładnej wartości użyjesz, ale im mniejsza wartość rezystora, tym jaśniej dioda LED będzie świecić.


Zainstaluj moduł pigpio

Wcześniej korzystaliśmy z modułu „onoff”, który świetnie sprawdza się przy włączaniu i wyłączaniu. Teraz chcemy ustawić siłę diod LED, więc potrzebujemy modułu GPIO o nieco większej funkcjonalności.

Użyjemy modułu „pigpio” Node.js, ponieważ pozwala on na PWM.

Dzięki PWM możemy ustawić siłę diody LED od 0 do 255.

Moduł Node.js „pigpio” jest oparty na bibliotece pigpio C.

Jeśli używasz „Lite” wersji Raspbian, najprawdopodobniej nie jest ona dołączona i należy ją zainstalować ręcznie.

Zaktualizuj listę pakietów systemowych:

pi@w3demopi:~ $ sudo apt-get update

Zainstaluj bibliotekę pigpio C:

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

Teraz możemy zainstalować moduł Node.js „pigpio” za pomocą npm:

pi@w3demopi:~ $ npm install pigpio

Teraz moduł "pigpio" powinien być zainstalowany i możemy go używać do interakcji z GPIO Raspberry Pi.

Uwaga: Ponieważ moduł „pigpio” korzysta z biblioteki pigpio C, wymaga uprawnień root/sudo, aby uzyskać dostęp do sprzętowych urządzeń peryferyjnych (takich jak GPIO).


Budowanie obwodu

Teraz nadszedł czas, aby zbudować obwód na naszej Breadboard.

Jeśli jesteś nowicjuszem w elektronice, zalecamy wyłączenie zasilania Raspberry Pi. I użyj antystatycznej maty lub paska uziemiającego, aby uniknąć uszkodzenia.

Zamknij poprawnie Raspberry Pi za pomocą polecenia:

pi@w3demopi:~ $ sudo shutdown -h now

Gdy diody przestaną migać na Raspberry Pi, wyciągnij wtyczkę zasilania z Raspberry Pi (lub wyłącz listwę zasilającą, do której jest podłączona).

Samo wyciągnięcie wtyczki bez prawidłowego wyłączenia może spowodować uszkodzenie karty pamięci.

Podczas budowania tego obwodu ważne jest, aby wiedzieć, czy masz wspólną anodę, czy wspólną katodę, diodę LED RGB:

Możesz sprawdzić u swojego dostawcy lub sam to przetestować:

Podłącz kable do GND i pinu 3.3V. Podłącz GND do najdłuższej nogi LED RGB, a 3,3 V do dowolnej innej nogi. Jeśli się zaświeci, dioda LED RGB ma wspólną katodę. Jeśli nie, ma wspólną anodę.

Raspberry Pi 3 z płytą prototypową.  Wspólna katoda LED RGB

Spójrz na powyższą ilustrację obwodu.

  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 płytce prototypowej podłącz rezystor między lewą i prawą kolumnę szyny uziemiającej dla rzędu z NIEBIESKĄ odnogą diody LED. W tym przykładzie dołączyliśmy go do wiersza 4, kolumny E i F

Twój obwód powinien być teraz kompletny, a połączenia powinny wyglądać podobnie do powyższej ilustracji.

Teraz nadszedł czas, aby uruchomić Raspberry Pi i napisać skrypt Node.js do interakcji z nim.

Raspberry Pi 3 z płytą prototypową.  Wspólna anoda LED RGB

Spójrz na powyższą ilustrację obwodu.

  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 płytce chlebowej podłącz męską nogę czwartego przewodu połączeniowego do tego samego rzędu prawej kolumny szyny uziemiającej, do której podłączono wspólną anodę. W tym przykładzie połączyliśmy go z wierszem 2, kolumną F

Twój obwód powinien być teraz kompletny, a połączenia powinny wyglądać podobnie do powyższej ilustracji.

Teraz nadszedł czas, aby uruchomić Raspberry Pi i napisać skrypt Node.js do interakcji z nim.



Raspberry Pi i Node.js RGB LED i skrypt WebSocket

Przejdź do katalogu „nodetest” i utwórz nowy plik o nazwie „ rgbws.js”:

pi@w3demopi:~ $ nano rgbws.js

Plik jest teraz otwarty i można go edytować za pomocą wbudowanego edytora Nano.

Napisz lub wklej następujące informacje:

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

Naciśnij „ Ctrl+x”, aby zapisać kod. Potwierdź za pomocą " y" i potwierdź nazwę za pomocą " Enter".

Napisz lub wklej następujące informacje:

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

Naciśnij „ Ctrl+x”, aby zapisać kod. Potwierdź za pomocą " y" i potwierdź nazwę za pomocą " Enter".


Interfejs użytkownika Raspberry Pi i Node.js WebSocket

Teraz nadszedł czas, aby dodać kod HTML, który umożliwia wprowadzanie danych przez użytkownika przez WebSocket.

W tym celu chcemy:

  • 3 suwaki kolorów, po jednym dla każdego koloru (RGB)
  • Próbnik kolorów
  • Div pokazujący aktualny kolor

Przejdź do folderu „publiczny”:

pi@w3demopi:~/nodetest $ cd public

I utwórz plik 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>

Wróć do folderu „nodetest”:

pi@w3demopi:~/nodetest $ cd ..

Uruchom kod:

pi@w3demopi:~ $ sudo node rgbws.js

Uwaga: Ponieważ moduł „pigpio” korzysta z biblioteki pigpio C, wymaga uprawnień root/sudo, aby uzyskać dostęp do sprzętowych urządzeń peryferyjnych (takich jak GPIO).

Otwórz stronę w przeglądarce, używając http://[RaspberryPi_IP]:8080/

Teraz dioda LED RGB powinna zmieniać kolor w zależności od wejścia użytkownika.

Zakończ program za pomocą Ctrl+c.