Arduino与JavaScript开发实例-LED基础控制-(点亮、关闭、PWM及FadeIn和FadeOut) LED基础控制-(点亮、关闭、PWM及FadeIn和FadeOut) 文章目录
Johnny-Five库中的Led 类构造了表示连接到物理板上的单个 Led 的对象。本次实例将演示如何在Electron的基础上通过Johnny-Five库与Arduino开发板通信,并实现控制LED点亮、关闭、PWM、及FadeIn和FadeOut。
1、硬件准备
Arduino Mega2560开发板一块
发光LED一个
杜邦线若干
数据线一条
硬件接线如下:
2、软件准备
VS Code IDE
Arduino IDE
NodeJs(本次使用的版本为v16.13.0)
Visual Studio 2019
Electron(本次使用版本为v17.0.1)
前面的文章已经对Arduino与JavaScript开发环境已经做了详细描述,请参考:开发环境搭建
3、代码实现 3.1 LED对象创建 3.1.1 参数
pin :LED引脚的数字或字符串地址(数字/PWM)。 对于只有开/关状态的LED,请使用数字引脚。
1 2 3 const five = require('johnny-five') let led = new five.Led(13)
对于具有开/关状态的LED,以及与间隔或颜色相关的状态(脉冲、亮度、RGB 等),请使用PWM引脚。
属性名称
类型
值/描述
默认值
是否必要
pin
Number
LED引脚。LED 连接到的引脚的编号地址。
yes
controller
String
控制器,默认为”PCA9685”。
"DEFAULT"
no
board
Object Instance
LED 连接到的板实例。 仅当您的项目中安装了多个板时才需要
First board mounted
no
**PCA9685 Options (PCA9685控制器)**:属性参数的对象
属性名称
类型
值/描述
默认
是否必要
address
Number
I2C设备地址。
0x04
no
3.1.2 初始化 1 2 3 4 5 6 7 8 // 只有一个引脚 var led = new five.Led(13); // 具有 pin 属性的选项对象 new five.Led({ pin: 13 });
使用PCA9685 控制器初始化
1 2 3 4 5 new five.Led({ controller: "PCA9685", pin: 0, // PCA9685的0引脚 });
3.1.3 调用 LED闪烁
1 2 3 4 5 6 7 8 9 // LED闪烁 var five = require("johnny-five"); var board = new five.Board(); board.on("ready", function() { var led = new five.Led(13); led.blink(); });
多开发板控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 // 多个开发板 var five = require("johnny-five"); var board1 = new five.Board(); var board2 = new five.Board(); board1.on("ready", function() { var led1 = new five.Led(board1, 13); led.blink(); }); board2.on("ready", function() { var led2 = new five.Led(board2, 13); led.blink(); });
PCA9685控制器
1 2 3 4 5 6 7 8 9 10 11 12 var five = require("johnny-five"); var board = new five.Board(); board.on("ready", function() { var led = new five.Led({ controller: "PCA9685", pin: 0, }); led.blink() });
3.2 Electron代码实现 1)package.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 { "name": "Arduino Firmata Electron", "version": "0.0.1", "main": "main.js", "dependencies": { "bootstrap": "^5.1.3", "echarts": "^5.3.0", "jquery": "^3.6.0", "socket.io": "^4.4.1", "ws": "^8.5.0", "mqtt": "^4.3.6", "johnny-five": "^2.1.0", "path": "^0.12.7", "react": "^17.0.2", "react-bootstrap": "^2.2.0", "react-dom": "^17.0.2", "react-scripts": "^5.0.0" } }
2)页面布局(index.html)
Electron应用程序的页面通过Bootstrap、Bootstrap Slider插件 、JQuery实现。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>LED控制</title> <script>window.$ = window.jQuery = require('jquery');</script> <script src="../bootstrap-5.1.3-dist/js/bootstrap.min.js"></script> <script src="../bootstrap-slider-master/dist/bootstrap-slider.min.js"></script> <script> window.echarts = require('echarts'); </script> <link href="../bootstrap-5.1.3-dist/css/bootstrap.min.css" rel="stylesheet"></link> <link href="../bootstrap-slider-master/dist/css/bootstrap-slider.min.css" rel="stylesheet"></link> </head> <body> <div class="row"> <div class="col-md-2"> <div class="panel panel-default" style="width:128px;height:256px"> <div class="panel-heading text-center">LED开关</div> <div class="panel-body"> <button type="button" class="btn" id="led-btn"> <image src="../images/led\_off.png" id="led-ctr-bg-img"></image> </button> </div> <div class="panel-footer text-center" id="led-controller-title">打开LED</div> </div> </div> <div class="col-md-2"> <div class="panel panel-default" style="width:128px;height:256px"> <div class="panel-heading text-center">LED闪烁</div> <div class="panel-body"> <button type="button" class="btn" id="led-blink-btn"> <image src="../images/led\_off.png" id="led-blink-bg-img"></image> </button> </div> <div class="panel-footer text-center" id="led-controller-blink-title">打开闪烁</div> </div> </div> <div class="col-md-2"> <div class="panel panel-default" style="width:512px;height:256px"> <div class="panel-heading text-center">LED PWM</div> <div class="panel-body"> <div class="row"> <div class="col d-flex flex-row"> <label class="form-check-label" for="led-pulse-slider-d">延时</label> <input id="led-pulse-slider" data-slider-id='led-pulse-slider-d' type="text" data-slider-min="100" data-slider-max="5000" data-slider-step="100" data-slider-value="1000"/> <div class="form-check"> <input class="form-check-input" type="checkbox" value="" id="led-pulse-stop-cb"> <label class="form-check-label" for="led-pulse-stop-cb">自动停止</label> </div> <div class="form-check"> <input class="form-check-input" type="checkbox" value="" id="led-pulse-anim-cb"> <label class="form-check-label" for="led-pulse-anim-cb">动画效果</label> </div> <div class="form-check"> <input class="form-check-input" type="checkbox" value="" id="led-pulse-fade-cb"> <label class="form-check-label" for="led-pulse-fade-cb">淡入淡出</label> </div> </div> </div> <div class="row"> <div class="clo d-flex flex-row"> <button type="button" class="btn btn-primary" id="led-pulse-btn">开始</button> </div> </div> </div> <div class="panel-footer text-center" id="led-controller-pulse-title"></div> </div> </div> </div> <div class="row"> <div class="col-md-2"> <div class="panel panel-default" style="width:512px;height:256px"> <div class="panel-heading ">LED亮度调节</div> <div class="panel-body"> <label class="form-check-label" for="led-brightness-slider-d">亮度</label> <input id="led-brightness-slider" data-slider-id='led-brightness-slider-d' type="text" data-slider-min="0" data-slider-max="255" data-slider-step="1" data-slider-value="128"/> </div> <div class="panel-footer" id="led-controller-brightness-title">当前亮度:128</div> </div> </div> </div> <script src="../../static/js/renderer/led\_controll\_renderer.js"></script> </body> </html>
上面代码实现的页面效果如下:
3)页面逻辑控制(renderer.js)
由于johnny-five库调用到serialport库(nodejs addon),Electron v14+后不支持在渲染进程中直接调用,只能在主进程中调用。为了johnny-five库正常使用,可以通过Electron的进程间通信方式实现,即通过Electron的ipcMain和ipcRender来实现渲染进程与主进程间的通信。
导入类或库
1 2 const { ipcRenderer } = require('electron')
LED开关控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 // LED ON/OF $('#led-btn').on('click',() => { if(!ledState){ // 向主进程发送led-on事件 ipcRenderer.send('led-on',''); console.log('led on') }else{ // 向主进程发送led-off事件 ipcRenderer.send('led-off','') console.log('led off') } // 更新LED状态和页面更新 ledState = !ledState if(ledState){ $('#led-ctr-bg-img').attr('src','../images/led\_on.png') $('#led-controller-title').html('关闭LED') }else{ $('#led-ctr-bg-img').attr('src','../images/led\_off.png') $('#led-controller-title').html('打开LED') } // 更新LED闪烁状态和页面更新 isLedBlinking = false $('#led-blink-bg-img').attr('src','../images/led\_off.png') })
LED闪烁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // LED闪烁 $('#led-blink-btn').on('click', () => { if(!isLedBlinking){ // 向主进程发送led-blink-start事件,500毫秒间隔 ipcRenderer.send('led-blink-start',{delay:500}) // 更新UI $('#led-controller-blink-title').html('停止闪烁') $('#led-blink-bg-img').attr('src','../images/led\_blink.gif') console.log('start blinking') }else{ // 向主进程发送led-blink-stop事件,500毫秒间隔 ipcRenderer.send('led-blink-stop',{delay:-1}) // 更新UI $('#led-controller-blink-title').html('开始闪烁') $('#led-blink-bg-img').attr('src','../images/led\_off.png') console.log('stop blink') } isLedBlinking = !isLedBlinking // 更新UI ledState = false $('#led-ctr-bg-img').attr('src','../images/led\_off.png') $('#led-controller-title').html('打开LED') })
LED PWM控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 var ledPulseValue = 1000 // 初始化Bootstrap Slider并注册change事件 var ledPWMSlider = $('#led-pulse-slider').bootstrapSlider().on('change',() => { // 获取当前Slider的值 ledPulseValue = $('#led-pulse-slider').bootstrapSlider('getValue') console.log('led pulse:' + ledPulseValue) }) $('#led-pulse-btn').on('click',() =>{ // 获取延时值(毫秒) let stopForDelay = $('#led-pulse-stop-cb').is(':checked'); // 是否启用动画方式 let isAnimate = $('#led-pulse-anim-cb').is(':checked') // 是否启用淡入和淡出方式 let isFade = $('#led-pulse-fade-cb').is(':checked') // 向主进程发送led-pulse命令 ipcRenderer.send('led-pulse',{ delay:ledPulseValue, stopAfterDelay:stopForDelay, isAnimate:isAnimate,isFade:isFade}) // 更新UI isLedBlinking = false $('#led-blink-bg-img').attr('src','../images/led\_off.png') $('#led-controller-blink-title').html('开始闪烁') ledState = false $('#led-ctr-bg-img').attr('src','../images/led\_off.png') $('#led-controller-title').html('打开LED') console.log('led pulse:' + ledPulseValue) })
LED亮度控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 // LED 亮度 var ledBrightness = 128; // 初始化Bootstrap Slider var ledBrightnessSlider = $('#led-brightness-slider').bootstrapSlider().on('change',() => { // 获取当前亮度值 ledBrightness = $('#led-brightness-slider').bootstrapSlider('getValue') console.log('led brightness:' + ledBrightness) // 向主进程发送led-brightness命令 ipcRenderer.send('led-brightness',{brightness:ledBrightness}) // 更新UI $('#led-controller-brightness-title').html('当前亮度:' + ledBrightness) isLedBlinking = false $('#led-blink-bg-img').attr('src','../images/led\_off.png') $('#led-controller-blink-title').html('开始闪烁') ledState = false $('#led-ctr-bg-img').attr('src','../images/led\_off.png') $('#led-controller-title').html('打开LED') console.log('led pulse:' + ledPulseValue) })
4)应用程序入口(main.js)
应用程序初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 const { app, BrowserWindow,ipcMain } = require('electron') const path = require('path') const url = require('url') // Keep a global reference of the window object, if you don't, the window will // be closed automatically when the JavaScript object is garbage collected. let mainWindow function createWindow() { // Create the browser window. mainWindow = new BrowserWindow({ width: 1024, height: 600, backgroundColor: "#ccc", webPreferences: { nodeIntegration: true, // to allow require contextIsolation: false, // allow use with Electron 12+ preload: path.join(__dirname, 'preload.js') } }) // and load the index.html of the app. mainWindow.loadURL(url.format({ pathname: path.join(__dirname+'/static/html', 'led\_control.html'), //pathname:path.join(\_\_dirname,'index.html'), protocol: 'file:', slashes: true })) // Open the DevTools. mainWindow.webContents.openDevTools() // Emitted when the window is closed. mainWindow.on('closed', function() { // Dereference the window object, usually you would store windows // in an array if your app supports multi windows, this is the time // when you should delete the corresponding element. mainWindow = null }) } // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. app.on('ready', createWindow) // Quit when all windows are closed. app.on('window-all-closed', function() { // On OS X it is common for applications and their menu bar // to stay active until the user quits explicitly with Cmd + Q app.quit() }) app.on('activate', function() { // On OS X it's common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. if (mainWindow === null) { createWindow() } })
LED控制响应实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 const five = require('johnny-five') const board = new five.Board({port:'COM12',repl:false}) board.on('ready',() => { console.log('board inited') const led = new five.Led(13) let isLedBlinking = false; // LED打开 ipcMain.on('led-on', (event, arg) =>{ console.log('led on') led.stop() // 关闭内部定时器 led.on() }) // LED关闭 ipcMain.on('led-off',(event,arg) => { console.log('led off') led.off() }) // LED闪烁开始 ipcMain.on('led-blink-start',(event,arg) => { var delay = arg.delay led.stop() // // 关闭内部定时器 console.log('led start to bink:delay = ' + delay + ' ms'); led.blink(delay) isLedBlinking = true }) // LED闪烁关闭 ipcMain.on('led-blink-stop',(event,arg) => { console.log('led stop blink'); led.stop() isLedBlinking = false }) // LED PWM控制 ipcMain.on('led-pulse',(event,arg) =>{ let delay = arg.delay // 延时 let stopForDelay = arg.stopAfterDelay // PWM输出完成后关闭定时器 let isAnimate = arg.isAnimate // 动画方式输出 let isFade = arg.isFade // 淡入淡出 console.log(arg) led.stop() // // 关闭内部定时器 if(isAnimate && !isFade){ led.pulse({ easing: "linear", duration: delay, cuePoints: [0, 0.2, 0.4, 0.6, 0.8, 1], keyFrames: [0, 10, 0, 50, 0, 255], onstop() { console.log("Animation stopped"); } }); }else if(isFade && !isAnimate){ function fadeNext(){ led.fadeIn(delay) console.log('fadeNext:fadeIn') board.wait(delay,() => { led.fadeOut(delay,fadeNext) console.log('fadeNext:fadeOut') }) } led.on() led.fadeOut(delay,fadeNext) // 淡出、启动回调循环 console.log('fadeNext:fadeOut') }else{ led.fade() } if(stopForDelay){ board.wait(delay,() => { led.stop().off() // 停止LED定时器并关闭LED }) } }) // LED亮度控制 ipcMain.on('led-brightness',(event,arg) => { let brightness = arg.brightness led.stop() led.brightness(brightness) console.log('brightness:' + brightness) }) })
4、运行结果
文章来源: https://iotsmart.blog.csdn.net/article/details/124931168
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!