Node.js Raspberry Pi RGB LED مع WebSocket


باستخدام تعديل عرض النبض

لقد تعلمنا في الفصول السابقة كيفية استخدام WebSocket ، وكيفية استخدام GPIO لتشغيل وإيقاف تشغيل مصابيح LED.

في هذا الفصل سنستخدم RGB LED ، مع PWM (تعديل عرض النبضة) لعرض ألوان مختلفة بناءً على مدخلات المستخدم عبر WebSocket.

RGB LED هو LED بثلاثة ألوان مختلفة. يحتوي على LED أحمر وأخضر وأزرق (RGB LED).

وباستخدام PWM ، يمكننا ضبط القوة الفردية لمصابيح LED الثلاثة. سيسمح لنا ذلك بخلطها وتحديد لونها.


ماذا نحتاج؟

في هذا الفصل ، سننشئ مثالًا حيث نتحكم في RGB LED بصفحة ويب عبر WebSocket.

لهذا تحتاج:

انقر فوق الارتباطات الموجودة في القائمة أعلاه للحصول على أوصاف للمكونات المختلفة.

ملاحظة: يمكن أن يكون المقاوم الذي تحتاجه مختلفًا عما نستخدمه اعتمادًا على نوع LED الذي تستخدمه. معظم المصابيح الصغيرة تحتاج فقط إلى مقاومة صغيرة ، حوالي 200-500 أوم. ليس من المهم بشكل عام القيمة الدقيقة التي تستخدمها ، ولكن كلما كانت قيمة المقاوم أصغر ، كلما كان مؤشر LED أكثر إشراقًا.


قم بتثبيت وحدة Pigpio

في وقت سابق ، استخدمنا وحدة "onoff" ، والتي تعمل بشكل رائع لمجرد التشغيل وإيقاف التشغيل. نريد الآن ضبط قوة المصابيح ، لذلك نحتاج إلى وحدة GPIO مع وظائف أكثر قليلاً.

سوف نستخدم وحدة "pigpio" Node.js ، لأن هذا يسمح لـ PWM.

مع PWM يمكننا ضبط قوة LED من 0 إلى 255.

تعتمد الوحدة النمطية "pigpio" Node.js على مكتبة pigpio C.

إذا كنت تستخدم الإصدار "Lite" من Raspbian ، فمن المحتمل ألا يتم تضمين هذا الإصدار ويجب تثبيته يدويًا.

قم بتحديث قائمة حزمة النظام الخاص بك:

pi@w3demopi:~ $ sudo apt-get update

قم بتثبيت مكتبة Pigpio C:

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

الآن يمكننا تثبيت وحدة "pigpio" Node.js باستخدام npm:

pi@w3demopi:~ $ npm install pigpio

الآن يجب تثبيت وحدة "pigpio" ويمكننا استخدامها للتفاعل مع GPIO الخاص بـ Raspberry Pi.

ملاحظة: نظرًا لأن الوحدة النمطية "pigpio" تستخدم مكتبة pigpio C ، فإنها تتطلب امتيازات root / sudo للوصول إلى الأجهزة الطرفية (مثل GPIO).


بناء الدائرة

حان الوقت الآن لبناء الدائرة على اللوح الخاص بنا.

إذا كنت جديدًا في مجال الإلكترونيات ، فننصحك بإيقاف تشغيل جهاز Raspberry Pi. واستخدم حصيرة مقاومة للكهرباء الساكنة أو شريط تأريض لتجنب إتلافها.

قم بإغلاق Raspberry Pi بشكل صحيح باستخدام الأمر:

pi@w3demopi:~ $ sudo shutdown -h now

بعد أن تتوقف مصابيح LED عن الوميض على Raspberry Pi ، ثم اسحب قابس الطاقة من Raspberry Pi (أو اقلب شريط الطاقة المتصل به).

قد يؤدي مجرد سحب القابس دون إيقاف التشغيل بشكل صحيح إلى تلف بطاقة الذاكرة.

عند بناء هذه الدائرة ، من المهم معرفة ما إذا كان لديك أنود مشترك ، أو كاثود مشترك ، RGB LED:

يمكنك التحقق من مزود الخدمة الخاص بك ، أو اختباره بنفسك:

قم بتوصيل الكابلات بـ GND ودبوس 3.3 فولت. قم بتوصيل GND بأطول ساق من RGB LED و 3.3 V بأي ساق أخرى. إذا أضاء ، فإن RGB LED الخاص بك يحتوي على كاثود مشترك. إذا لم يكن كذلك ، فإنه يحتوي على أنود مشترك.

Raspberry Pi 3 مع اللوح.  RGB LED كاثود مشترك

انظر إلى الرسم التوضيحي أعلاه للدائرة.

  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. في Breadboard ، قم بتوصيل المقاوم بين أعمدة الناقل الأرضية اليمنى واليسرى للصف مع الساق الزرقاء من LED. في هذا المثال قمنا بإرفاقه بالصف 4 والعمود E و F.

يجب أن تكون دائرتك الآن مكتملة ، ويجب أن تبدو اتصالاتك مشابهة تمامًا للشكل التوضيحي أعلاه.

حان الوقت الآن لتشغيل Raspberry Pi ، وكتابة البرنامج النصي Node.js للتفاعل معه.

Raspberry Pi 3 مع اللوح.  RGB LED الأنود المشترك

انظر إلى الرسم التوضيحي أعلاه للدائرة.

  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. في Breadboard ، قم بتوصيل الساق الذكرية لسلك العبور الرابع بنفس الصف من عمود الناقل الأرضي الأيمن الذي قمت بتوصيل القطب الموجب به. في هذا المثال قمنا بتوصيله بالصف 2 العمود F

يجب أن تكون دائرتك الآن مكتملة ، ويجب أن تبدو اتصالاتك مشابهة تمامًا للشكل التوضيحي أعلاه.

حان الوقت الآن لتشغيل Raspberry Pi ، وكتابة البرنامج النصي Node.js للتفاعل معه.



Raspberry Pi و Node.js RGB LED و WebSocket Script

انتقل إلى دليل "nodetest" ، وأنشئ ملفًا جديدًا يسمى " rgbws.js":

pi@w3demopi:~ $ nano rgbws.js

الملف مفتوح الآن ويمكن تحريره باستخدام محرر النانو المدمج.

اكتب أو الصق ما يلي:

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

اضغط على " Ctrl+x" لحفظ الكود. أكد بـ " y" ، وقم بتأكيد الاسم بـ " Enter".

اكتب أو الصق ما يلي:

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

اضغط على " Ctrl+x" لحفظ الكود. أكد بـ " y" ، وقم بتأكيد الاسم بـ " Enter".


Raspberry Pi و Node.js WebSocket UI

حان الوقت الآن لإضافة HTML الذي يسمح للمستخدم بإدخال عبر WebSocket.

لهذا نريد:

  • 3 منزلقات ملونة ، واحد لكل لون (RGB)
  • منتقي الألوان
  • يظهر div اللون الحالي

انتقل إلى المجلد "public":

pi@w3demopi:~/nodetest $ cd public

وأنشئ ملف 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>

ارجع إلى مجلد "nodetest":

pi@w3demopi:~/nodetest $ cd ..

قم بتشغيل الكود:

pi@w3demopi:~ $ sudo node rgbws.js

ملاحظة: نظرًا لأن الوحدة النمطية "pigpio" تستخدم مكتبة pigpio C ، فإنها تتطلب امتيازات root / sudo للوصول إلى الأجهزة الطرفية (مثل GPIO).

افتح الموقع في متصفح باستخدام http: // [RaspberryPi_IP]: 8080 /

الآن يجب أن يتغير لون RGB LED اعتمادًا على إدخال المستخدم.

قم بإنهاء البرنامج بامتداد Ctrl+c.