LED RGB Node.js Raspberry Pi com WebSocket


Usando Modulação por Largura de Pulso

Nos capítulos anteriores, aprendemos como usar o WebSocket e como usar o GPIO para ligar e desligar os LEDs.

Neste capítulo usaremos um LED RGB, com PWM (Pulse-width modulation) para exibir cores diferentes com base na entrada do usuário via WebSocket.

Um LED RGB é um LED com 3 cores diferentes. Possui LED VERMELHO, VERDE e AZUL (LED RGB).

E usando PWM, podemos definir a força individual dos 3 LEDs. Isso nos permitirá misturá-los, definir uma cor.


O que nós precisamos?

Neste capítulo vamos criar um exemplo onde controlamos um LED RGB com uma página web via WebSocket.

Para isso você precisa:

Clique nos links na lista acima para obter descrições dos diferentes componentes.

Nota: O resistor que você precisa pode ser diferente do que usamos dependendo do tipo de LED que você usa. A maioria dos LEDs pequenos precisa apenas de um pequeno resistor, em torno de 200-500 ohms. Geralmente não é crítico o valor exato que você usa, mas quanto menor o valor do resistor, mais brilhante o LED brilhará.


Instale o módulo pigpio

Anteriormente, usamos o módulo "onoff", que funciona muito bem para ligar e desligar. Agora queremos definir a intensidade dos LEDs, então precisamos de um Módulo GPIO com um pouco mais de funcionalidade.

Usaremos o módulo "pigpio" Node.js, pois permite o PWM.

Com o PWM podemos definir a intensidade de um LED de 0 a 255.

O módulo "pigpio" Node.js é baseado na biblioteca pigpio C.

Se você estiver usando a versão "Lite" do Raspbian, isso provavelmente não está incluído e deve ser instalado manualmente.

Atualize sua lista de pacotes do sistema:

pi@w3demopi:~ $ sudo apt-get update

Instale a biblioteca pigpio C:

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

Agora podemos instalar o módulo "pigpio" Node.js usando npm:

pi@w3demopi:~ $ npm install pigpio

Agora o módulo "pigpio" deve estar instalado e podemos usá-lo para interagir com o GPIO do Raspberry Pi.

Nota: Como o módulo "pigpio" usa a biblioteca pigpio C, ele requer privilégios de root/sudo para acessar periféricos de hardware (como o GPIO).


Construindo o Circuito

Agora é hora de construir o circuito em nossa Breadboard.

Se você é novo em eletrônica, recomendamos que desligue a energia do Raspberry Pi. E use um tapete antiestático ou uma cinta de aterramento para evitar danificá-lo.

Desligue o Raspberry Pi corretamente com o comando:

pi@w3demopi:~ $ sudo shutdown -h now

Depois que os LEDs pararem de piscar no Raspberry Pi, retire o plugue de alimentação do Raspberry Pi (ou gire o filtro de linha ao qual está conectado).

Basta puxar o plugue sem desligar corretamente pode causar corrupção do cartão de memória.

Na construção deste Circuito é importante saber se você possui um ânodo comum, ou cátodo comum, LED RGB:

Você pode verificar com seu provedor ou testar você mesmo:

Conecte os cabos ao GND e ao pino de 3,3 V. Conecte o GND à perna mais longa do LED RGB e o 3,3 V a qualquer outra perna. Se acender, seu LED RGB possui um cátodo comum. Se não, tem um ânodo comum.

Raspberry Pi 3 com Breadboard.  Catodo comum LED RGB

Observe a ilustração acima do circuito.

  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, conecte um resistor entre as colunas esquerda e direita do barramento de aterramento para a linha com a perna AZUL do LED. Neste exemplo, anexamos à linha 4, coluna E e F

Seu circuito agora deve estar completo e suas conexões devem ser bem parecidas com a ilustração acima.

Agora é hora de inicializar o Raspberry Pi e escrever o script Node.js para interagir com ele.

Raspberry Pi 3 com Breadboard.  Ânodo comum LED RGB

Observe a ilustração acima do circuito.

  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 Breadboard, conecte a perna macho do quarto jumper à mesma linha da coluna de barramento de aterramento direita à qual você conectou o ânodo comum. Neste exemplo, nós o conectamos à linha 2 coluna F

Seu circuito agora deve estar completo e suas conexões devem ser bem parecidas com a ilustração acima.

Agora é hora de inicializar o Raspberry Pi e escrever o script Node.js para interagir com ele.



Raspberry Pi e Node.js RGB LED e script WebSocket

Vá para o diretório "nodetest" e crie um novo arquivo chamado " rgbws.js":

pi@w3demopi:~ $ nano rgbws.js

O arquivo agora está aberto e pode ser editado com o Nano Editor integrado.

Escreva ou cole o seguinte:

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

Pressione " Ctrl+x" para salvar o código. Confirme com " y" e confirme o nome com " Enter".

Escreva ou cole o seguinte:

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

Pressione " Ctrl+x" para salvar o código. Confirme com " y" e confirme o nome com " Enter".


IU do WebSocket do Raspberry Pi e Node.js

Agora é hora de adicionar o HTML que permite a entrada do usuário via WebSocket.

Para isso queremos:

  • 3 controles deslizantes de cores, um para cada cor (RGB)
  • Um seletor de cores
  • Um div mostrando a cor atual

Vá para a pasta "pública":

pi@w3demopi:~/nodetest $ cd public

E crie um arquivo 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>

Volte para a pasta "nodetest":

pi@w3demopi:~/nodetest $ cd ..

Execute o código:

pi@w3demopi:~ $ sudo node rgbws.js

Nota: Como o módulo "pigpio" usa a biblioteca pigpio C, ele requer privilégios de root/sudo para acessar periféricos de hardware (como o GPIO).

Abra o site em um navegador usando http://[RaspberryPi_IP]:8080/

Agora o LED RGB deve mudar de cor dependendo da entrada do usuário.

Finalize o programa com Ctrl+c.