Đèn LED RGB Raspberry Pi của Node.js 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 chương này, chúng tôi sẽ sử dụng đèn LED RGB, với điều chế độ rộng xung (Pulse-width modulation) để 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 và XANH (LED RGB).
Và bằng cách sử dụng xung điều khiển, chúng ta có thể đặt cường độ riêng của 3 đèn LED. Điều này sẽ cho phép chúng ta trộn chúng để thiết lập 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 đèn LED RGB bằng một trang web thông qua WebSocket.
Đối với điều này bạn cần:
- Một Raspberry Pi có Raspian, internet, SSH, đã cài đặt Node.js
- Mô-đun pigpio cho Node.js
- Mô-đun socket.io cho Node.js
- 1 x Bảng mạch
- Điện trở 3 x 220 Ohm
- 1 x LED RGB (cực dương chung hoặc cực âm chung)
- 4 x dây nhảy từ nữ sang nam
Nhấp vào các 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 điện trở 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 ohm. Nói chung, giá trị chính xác bạn sử dụng không quan trọ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 "bật", mô-đun này hoạt động rất tốt chỉ để bật và tắt. Bây giờ chúng tôi muốn đặt cường độ của đèn LED, vì vậy chúng tôi cần Mô-đun GPIO có 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ì mô-đun này cho phép tạo ra xung điện xung.
VớiPWM, chúng ta có thể đặt cường độ của đèn LED từ 0 đến 255.
Mô-đun Node.js "pigpio" dựa trên thư viện pigpio C.
Nếu bạn đang sử dụng phiên bản Raspbian "Lite", rất có thể phiên bản này không được bao gồm và phải được cài đặt 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 Node.js "pigpio" bằng npm:
pi@w3demopi:~ $ npm install pigpio
Bây giờ mô-đun "pigpio" đã đượ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 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ờ là lúc xây dựng mạch trên Breadboard của chúng ta.
Nếu bạn chưa quen với 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 nối đất để tránh làm hỏng nó.
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 nguồn ra khỏi Raspberry Pi (hoặc tắt dải nguồn mà nó được kết nối).
Chỉ cần rút phích cắm mà không tắt đúng cách có thể gây hỏng thẻ nhớ.
Khi xây dựng Mạch này, điều quan trọng là phải biết bạn có cực dương chung hay cực âm chung, đèn 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 chân GND và 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ó cực âm chung. Nếu không, nó có một cực dương chung.
Nhìn vào hình minh họa ở trên của mạch.
- Trên Breadboard, kết nối đèn LED RGB với cột bus mặt đất bên phải và đảm bảo rằng mỗi chân kết nối với một hàng khác nhau. Chân dài nhất là chân âm cực chung. Trong ví dụ này, chúng tôi đã kết nối đèn LED với hàng 1-4, với chân catốt chung được kết nối với hàng 2 cột I. Chân ĐỎ được kết nối với hàng 1 cột J, chân XANH được kết nối với hàng 3 cột J và chân XANH được kết nối với hàng 3 cột J và chân ĐỎ được kết nối với hàng 1 cột J. Chân BLUE nối với hàng 4 cột J
- Trên Raspberry Pi, kết nối chân cái của dây nhảy đầu tiên với Ground . Bạn có thể sử dụng bất kỳ chân GND nào. Trong ví dụ này, chúng tôi sử dụng Chân vật lý 9 ( GND , hàng 5, cột bên trái)
- Trên Breadboard, kết nối chân đực của dây nhảy đầu tiên 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 cực âm chung. Trong ví dụ này, chúng tôi đã kết nối nó với hàng 2 cột F
- Trên Raspberry Pi, kết nối chân cái của cáp nhảy thứ hai với chân GPIO . Chúng tôi sẽ sử dụng chân này cho chân ĐỎ , Trong ví dụ này, chúng tôi sử dụng Chân vật lý 7 ( GPIO 4 , hàng 4, cột bên trái)
- Trên Breadboard, nối chân đực của dây nhảy thứ hai với bus mặt đất bên trái, cùng hàng với chân ĐỎ của đèn LED được kết nối. Trong ví dụ này, chúng tôi đã kết nối nó với hàng 1, cột A
- Trên Breadboard, nối một điện trở giữa cột bus mặt đất bên trái và bên phải cho hàng bằng chân ĐỎ của đèn LED. Trong ví dụ này chúng tôi đã gắn nó vào hàng 1, cột E và F
- Trên Raspberry Pi, kết nối chân cái của cáp nhảy thứ ba với chân GPIO . Chúng tôi sẽ sử dụng chân này cho chân XANH , Trong ví dụ này, chúng tôi sử dụng Chân vật lý 11 ( GPIO 17 , hàng 6, cột bên trái)
- Trên Breadboard, nối chân đực của dây nhảy thứ ba với bus mặt đất bên trái, cùng hàng với chân XANH của đèn LED được kết nối. Trong ví dụ này, chúng tôi đã kết nối nó với hàng 3, cột A
- Trên Breadboard, nối một điện trở giữa cột bus mặt đất bên trái và bên phải cho hàng có chân XANH của đèn LED. Trong ví dụ này chúng tôi đã gắn nó vào hàng 3, cột E và F
- Trên Raspberry Pi, kết nối chân cái của cáp nhảy thứ tư với chân GPIO . Chúng tôi sẽ sử dụng chân này cho chân BLUE , Trong ví dụ này, chúng tôi sử dụng Chân vật lý 13 ( GPIO 27 , hàng 7, cột bên trái)
- Trên Breadboard, nối chân đực của dây nhảy thứ tư với bus nối đất bên trái, cùng hàng với chân MÀU XANH của đèn LED được kết nối. Trong ví dụ này, chúng tôi đã kết nối nó với hàng 4, cột A
- Trên Breadboard, nối một điện trở giữa cột bus nối đất bên trái và bên phải cho hàng bằng chân XANH 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 tất 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ó.
Nhìn vào hình minh họa ở trên của mạch.
- Trên Breadboard, kết nối đèn LED RGB với cột bus mặt đất bên phải và đảm bảo rằng mỗi chân kết nối với một hàng khác nhau. Chân dài nhất là chân anode chung. Trong ví dụ này, chúng tôi đã kết nối đèn LED với hàng 1-4, với chân catốt chung được kết nối với hàng 2 cột I. Chân ĐỎ được kết nối với hàng 1 cột J, chân XANH được kết nối với hàng 3 cột J và chân XANH được kết nối với hàng 3 cột J và chân ĐỎ được kết nối với hàng 1 cột J. Chân BLUE nối với hàng 4 cột J
- Trên Raspberry Pi, kết nối chân cái của cáp nhảy đầu tiên với chân GPIO . Chúng tôi sẽ sử dụng chân này cho chân ĐỎ , Trong ví dụ này, chúng tôi sử dụng Chân vật lý 7 ( GPIO 4 , hàng 4, cột bên trái)
- Trên Breadboard, nối chân đực của dây nhảy đầu tiên với bus mặt đất bên trái, cùng hàng với chân ĐỎ của đèn LED được kết nối. Trong ví dụ này, chúng tôi đã kết nối nó với hàng 1, cột A
- Trên Breadboard, nối một điện trở giữa cột bus mặt đất bên trái và bên phải cho hàng bằng chân ĐỎ của đèn LED. Trong ví dụ này chúng tôi đã gắn nó vào hàng 1, cột E và F
- Trên Raspberry Pi, kết nối chân cái của cáp nhảy thứ hai với chân GPIO . Chúng tôi sẽ sử dụng chân này cho chân XANH , Trong ví dụ này, chúng tôi sử dụng Chân vật lý 11 ( GPIO 17 , hàng 6, cột bên trái)
- Trên Breadboard, nối chân đực của dây nhảy thứ hai với bus mặt đất bên trái, cùng hàng với chân XANH của đèn LED được kết nối. Trong ví dụ này, chúng tôi đã kết nối nó với hàng 3, cột A
- Trên Breadboard, nối một điện trở giữa cột bus mặt đất bên trái và bên phải cho hàng có chân XANH của đèn LED. Trong ví dụ này chúng tôi đã gắn nó vào hàng 3, cột E và F
- Trên Raspberry Pi, kết nối chân cái của cáp nhảy thứ ba với chân GPIO . Chúng tôi sẽ sử dụng chân này cho chân BLUE , Trong ví dụ này, chúng tôi sử dụng Chân vật lý 13 ( GPIO 27 , hàng 7, cột bên trái)
- Trên Breadboard, nối chân đực của dây nhảy thứ ba với bus nối đất bên trái, cùng hàng với chân XANH của đèn LED được kết nối. Trong ví dụ này, chúng tôi đã kết nối nó với hàng 4, cột A
- Trên Breadboard, nối một điện trở giữa cột bus nối đất bên trái và bên phải cho hàng bằng chân XANH 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
- Trên Raspberry Pi, kết nối chân cái của dây nhảy thứ tư với 3,3V . Trong ví dụ này, chúng tôi sử dụng Chân vật lý 1 ( 3,3V , hàng 1, cột bên trái)
- Trên Breadboard, nối chân đực của dây nhảy 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 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 tất 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 LED RGB và WebSocket Script
Chuyển đến thư mục "nodetest" và tạo một tệp mới có tên " rgbws.js
":
pi@w3demopi:~ $ nano rgbws.js
Tệp hiện đã mở và có thể được chỉnh sửa bằng Nano Editor tích hợp.
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 bằng " 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 bằng " y
" và xác nhận tên bằng " Enter
".
Giao diện người dùng WebSocket của Raspberry Pi và Node.js
Bây giờ là 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)
- Bộ chọn màu
- Một div hiển thị màu hiện tại
Chuyển đến 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.example.com.vn/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.example.com.vn/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 "nodetest":
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 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 https://[RaspberryPi_IP]:8080/
Bây giờ đèn LED RGB sẽ thay đổi màu tùy thuộc vào đầu vào của người dùng.
Kết thúc chương trình bằng Ctrl+c
.