Node.js Raspberry Pi LED RGB với WebSocket


Sử dụng điều chế độ rộng xung

Trong các chương trước, chúng ta đã học cách sử dụng WebSocket và cách sử dụng GPIO để bật và tắt đèn LED.

Trong phần này, chúng tôi sẽ sử dụng chương, chúng tôi sử dụng đèn LED RGB, với PWM (điều chế độ rộng xung) để hiển thị các màu khác nhau dựa trên đầu vào của người dùng thông qua WebSocket.

Đèn LED RGB là đèn LED có 3 màu khác nhau. Nó có đèn LED ĐỎ, XANH LÁ và XANH LÁ (LED RGB).

Và bằng cách sử dụng PWM, chúng tôi có thể đặt cường độ riêng của 3 đèn LED. Điều này sẽ cho phép chúng tôi trộn chúng, để thiết lập một màu sắc.


Chúng ta cần gì?

Trong chương này, chúng ta sẽ tạo một ví dụ trong đó chúng ta điều khiển một đèn LED RGB với một trang web thông qua WebSocket.

Đối với điều này, bạn cần:

Nhấp vào liên kết trong danh sách ở trên để xem mô tả về các thành phần khác nhau.

Lưu ý: Điện trở bạn cần có thể khác với những gì chúng tôi sử dụng tùy thuộc vào loại đèn LED bạn sử dụng. Hầu hết các đèn LED nhỏ chỉ cần một điện trở nhỏ, khoảng 200-500 ohms. Nói chung không quan trọng giá trị chính xác mà bạn sử dụng, nhưng giá trị của điện trở càng nhỏ thì đèn LED sẽ càng sáng.


Cài đặt mô-đun pigpio

Trước đó, chúng tôi đã sử dụng mô-đun "onoff", mô-đun này hoạt động tốt khi chỉ cần bật và tắt. Bây giờ chúng tôi muốn thiết lập cường độ của đèn LED, vì vậy chúng tôi cần một Mô-đun GPIO với nhiều chức năng hơn một chút.

Chúng tôi sẽ sử dụng mô-đun Node.js "pigpio", vì điều này cho phép PWM.

Với PWM, chúng ta có thể đặt cường độ của đèn LED từ 0 đến 255.

Mô-đun "pigpio" Node.js dựa trên thư viện pigpio C.

Nếu bạn đang sử dụng phiên bản Raspbian "Lite", phiên bản này rất có thể không được bao gồm và phải được cài đặt theo cách thủ công.

Cập nhật danh sách gói hệ thống của bạn:

pi@w3demopi:~ $ sudo apt-get update

Cài đặt thư viện pigpio C:

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

Bây giờ chúng ta có thể cài đặt mô-đun "pigpio" Node.js bằng cách sử dụng npm:

pi@w3demopi:~ $ npm install pigpio

Bây giờ mô-đun "pigpio" sẽ được cài đặt và chúng ta có thể sử dụng nó để tương tác với GPIO của Raspberry Pi.

Lưu ý: Vì mô-đun "pigpio" sử dụng thư viện pigpio C nên nó yêu cầu đặc quyền root / sudo để truy cập các thiết bị ngoại vi phần cứng (như GPIO).


Xây dựng mạch

Bây giờ đã đến lúc xây dựng mạch trên Breadboard của chúng ta.

Nếu bạn là người mới sử dụng thiết bị điện tử, chúng tôi khuyên bạn nên tắt nguồn cho Raspberry Pi. Và sử dụng thảm chống tĩnh điện hoặc dây đeo tiếp đất để tránh làm hỏng thiết bị.

Tắt Raspberry Pi đúng cách bằng lệnh:

pi@w3demopi:~ $ sudo shutdown -h now

Sau khi đèn LED ngừng nhấp nháy trên Raspberry Pi, hãy rút phích cắm ra khỏi Raspberry Pi (hoặc vặn dải nguồn mà nó được kết nối).

Chỉ rút phích cắm mà không tắt đúng cách có thể làm hỏng thẻ nhớ.

Khi xây dựng mạch này, điều quan trọng là phải biết nếu bạn có một cực dương chung hoặc cực âm chung, LED RGB:

Bạn có thể kiểm tra với nhà cung cấp của mình hoặc tự kiểm tra:

Kết nối cáp với GND và chân 3.3V. Kết nối GND với chân dài nhất của đèn LED RGB và 3,3 V với bất kỳ chân nào khác. Nếu nó sáng lên, đèn LED RGB của bạn có một cực âm chung. Nếu không, nó có một cực dương chung.

Raspberry Pi 3 với Breadboard.  LED RGB Cathode chung

Nhìn vào hình minh họa trên của mạch.

  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. Trên Breadboard, kết nối một điện trở giữa các cột bus mặt đất bên trái và bên phải cho hàng có chân BLUE của đèn LED. Trong ví dụ này, chúng tôi đã gắn nó vào hàng 4, cột E và F

Mạch của bạn bây giờ đã hoàn thành và các kết nối của bạn sẽ trông khá giống với hình minh họa ở trên.

Bây giờ là lúc khởi động Raspberry Pi và viết tập lệnh Node.js để tương tác với nó.

Raspberry Pi 3 với Breadboard.  Cực dương chung LED RGB

Nhìn vào hình minh họa trên của mạch.

  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. Trên Breadboard, kết nối chân đực của dây jumper thứ tư với cùng hàng của cột bus nối đất bên phải mà bạn đã kết nối với cực dương chung. Trong ví dụ này, chúng tôi kết nối nó với hàng 2 cột F

Mạch của bạn bây giờ đã hoàn thành và các kết nối của bạn sẽ trông khá giống với hình minh họa ở trên.

Bây giờ là lúc khởi động Raspberry Pi và viết tập lệnh Node.js để tương tác với nó.



Raspberry Pi và Node.js RGB LED và WebSocket Script

Đi tới thư mục "gật đầu" và tạo một tệp mới có tên " rgbws.js":

pi@w3demopi:~ $ nano rgbws.js

Tệp hiện đã được mở và có thể được chỉnh sửa bằng Trình chỉnh sửa Nano được tích hợp sẵn.

Viết hoặc dán nội dung sau:

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

Nhấn " Ctrl+x" để lưu mã. Xác nhận với " y" và xác nhận tên bằng " Enter".

Viết hoặc dán nội dung sau:

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

Nhấn " Ctrl+x" để lưu mã. Xác nhận với " y" và xác nhận tên bằng " Enter".


Raspberry Pi và Node.js WebSocket UI

Bây giờ đã đến lúc thêm HTML cho phép người dùng nhập thông qua WebSocket.

Đối với điều này, chúng tôi muốn:

  • 3 thanh trượt màu, một thanh trượt cho mỗi màu (RGB)
  • Một công cụ chọn màu
  • Một div hiển thị màu hiện tại

Đi tới thư mục "công khai":

pi@w3demopi:~/nodetest $ cd public

Và tạo một tệp 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>

Quay lại thư mục "gật đầu":

pi@w3demopi:~/nodetest $ cd ..

Chạy mã:

pi@w3demopi:~ $ sudo node rgbws.js

Lưu ý: Vì mô-đun "pigpio" sử dụng thư viện pigpio C nên nó yêu cầu đặc quyền root / sudo để truy cập các thiết bị ngoại vi phần cứng (như GPIO).

Mở trang web trong trình duyệt bằng http: // [RaspberryPi_IP]: 8080 /

Bây giờ đèn LED RGB sẽ thay đổi màu sắc tùy thuộc vào đầu vào của người dùng.

Kết thúc chương trình với Ctrl+c.