Node.js Raspberry Pi RGB LED dengan WebSocket


Menggunakan Modulasi Lebar Pulsa

Pada bab sebelumnya, kita telah mempelajari cara menggunakan WebSocket, dan cara menggunakan GPIO untuk menghidupkan dan mematikan LED.

Dalam bab ini kita akan menggunakan LED RGB, dengan PWM (Pulse-width modulation) untuk menampilkan warna yang berbeda berdasarkan input pengguna melalui WebSocket.

LED RGB adalah LED dengan 3 warna berbeda. Ini memiliki LED MERAH, HIJAU dan BIRU (LED RGB).

Dan menggunakan PWM, kita dapat mengatur kekuatan individu dari 3 LED. Ini akan memungkinkan kita untuk mencampurnya, untuk mengatur warna.


Apa yang kita butuhkan?

Dalam bab ini kita akan membuat contoh di mana kita mengontrol LED RGB dengan halaman web melalui WebSocket.

Untuk ini, Anda perlu:

Klik tautan dalam daftar di atas untuk deskripsi berbagai komponen.

Catatan: Resistor yang Anda butuhkan dapat berbeda dari yang kami gunakan tergantung pada jenis LED yang Anda gunakan. Kebanyakan LED kecil hanya membutuhkan resistor kecil, sekitar 200-500 ohm. Umumnya tidak penting nilai pasti yang Anda gunakan, tetapi semakin kecil nilai resistor, semakin terang LED akan bersinar.


Instal Modul pigpio

Sebelumnya, kami telah menggunakan modul "onoff", yang berfungsi baik hanya untuk menghidupkan dan mematikan. Sekarang kami ingin mengatur kekuatan LED, jadi kami membutuhkan Modul GPIO dengan fungsionalitas yang lebih sedikit.

Kami akan menggunakan modul Node.js "pigpio", karena ini memungkinkan untuk PWM.

Dengan PWM kita dapat mengatur kekuatan sebuah LED dari 0 sampai 255.

Modul Node.js "pigpio" didasarkan pada pustaka pigpio C.

Jika Anda menggunakan Raspbian versi "Lite", kemungkinan besar ini tidak disertakan dan harus diinstal secara manual.

Perbarui daftar paket sistem Anda:

pi@w3demopi:~ $ sudo apt-get update

Instal perpustakaan pigpio C:

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

Sekarang kita dapat menginstal modul Node.js "pigpio" menggunakan npm:

pi@w3demopi:~ $ npm install pigpio

Sekarang modul "pigpio" harus diinstal dan kita dapat menggunakannya untuk berinteraksi dengan GPIO dari Raspberry Pi.

Catatan: Karena modul "pigpio" menggunakan pustaka pigpio C, modul ini memerlukan hak akses root/sudo untuk mengakses periferal perangkat keras (seperti GPIO).


Membangun Sirkuit

Sekarang saatnya untuk membangun sirkuit di Breadboard kita.

Jika Anda baru mengenal elektronik, kami sarankan Anda mematikan daya untuk Raspberry Pi. Dan gunakan alas anti-statis atau tali pengikat untuk menghindari kerusakan.

Matikan Raspberry Pi dengan benar dengan perintah:

pi@w3demopi:~ $ sudo shutdown -h now

Setelah LED berhenti berkedip pada Raspberry Pi, kemudian cabut steker listrik dari Raspberry Pi (atau putar soket ekstensi yang terhubung).

Hanya mencabut steker tanpa mematikan dengan benar dapat menyebabkan kerusakan pada kartu memori.

Dalam membangun Sirkuit ini, penting untuk mengetahui apakah Anda memiliki anoda umum, atau katoda umum, LED RGB:

Anda dapat memeriksa dengan penyedia Anda, atau mengujinya sendiri:

Hubungkan kabel ke pin GND dan 3.3V. Hubungkan GND ke kaki terpanjang dari LED RGB dan 3,3 V ke kaki lainnya. Jika menyala, LED RGB Anda memiliki katoda umum. Jika tidak, ia memiliki anoda umum.

Raspberry Pi 3 dengan papan tempat memotong roti.  RGB LED umum Katoda

Perhatikan ilustrasi rangkaian di atas.

  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. Pada Breadboard, sambungkan resistor antara kolom bus ground kiri dan kanan untuk baris dengan kaki BIRU LED. Dalam contoh ini kami telah melampirkannya ke baris 4, kolom E dan F

Sirkuit Anda sekarang harus lengkap, dan koneksi Anda akan terlihat sangat mirip dengan ilustrasi di atas.

Sekarang saatnya untuk mem-boot Raspberry Pi, dan menulis skrip Node.js untuk berinteraksi dengannya.

Raspberry Pi 3 dengan papan tempat memotong roti.  RGB LED Anoda Umum

Perhatikan ilustrasi rangkaian di atas.

  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. Di Breadboard, sambungkan kaki kabel jumper keempat ke baris yang sama dari kolom bus ground kanan yang Anda hubungkan dengan anoda umum. Dalam contoh ini kami menghubungkannya ke baris 2 kolom F

Sirkuit Anda sekarang harus lengkap, dan koneksi Anda akan terlihat sangat mirip dengan ilustrasi di atas.

Sekarang saatnya untuk mem-boot Raspberry Pi, dan menulis skrip Node.js untuk berinteraksi dengannya.



Raspberry Pi dan Node.js RGB LED dan Skrip WebSocket

Buka direktori "nodetest", dan buat file baru bernama " rgbws.js":

pi@w3demopi:~ $ nano rgbws.js

File sekarang terbuka dan dapat diedit dengan Nano Editor bawaan.

Tulis, atau tempel yang berikut ini:

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

Tekan " Ctrl+x" untuk menyimpan kode. Konfirmasikan dengan " y", dan konfirmasikan nama dengan " Enter".

Tulis, atau tempel yang berikut ini:

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

Tekan " Ctrl+x" untuk menyimpan kode. Konfirmasikan dengan " y", dan konfirmasikan nama dengan " Enter".


Raspberry Pi dan Node.js WebSocket UI

Sekarang saatnya menambahkan HTML yang memungkinkan input pengguna melalui WebSocket.

Untuk ini kami ingin:

  • 3 penggeser warna, satu untuk setiap warna (RGB)
  • Seorang pemilih warna
  • Sebuah div yang menunjukkan warna saat ini

Buka folder "publik":

pi@w3demopi:~/nodetest $ cd public

Dan buat file 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>

Kembali ke folder "nodetest":

pi@w3demopi:~/nodetest $ cd ..

Jalankan kode:

pi@w3demopi:~ $ sudo node rgbws.js

Catatan: Karena modul "pigpio" menggunakan pustaka pigpio C, modul ini memerlukan hak akses root/sudo untuk mengakses periferal perangkat keras (seperti GPIO).

Buka situs web di browser menggunakan http://[RaspberryPi_IP]:8080/

Sekarang LED RGB harus berubah warna tergantung pada input pengguna.

Akhiri program dengan Ctrl+c.