1 项目简介
本项目使用BeagleBone Black开发板(以下简称:BBB开发板)控制板载LED。通过Web界面,用户可以控制每个LED的开关状态,实现全开和全关操作。项目使用Node.js作为服务器端技术栈,Express.js作为Web服务器框架,Socket.IO实现前后端实时通信,EJS作为模板引擎渲染页面。
2 环境准备
2.1 下载并烧录最新的官方镜像
在路由器后台查询开发板ip,使用ssh登录到开发板,或者使用cloud9
2.2 安装node
sudo apt update && sudo apt full-upgrade
sudo apt-get install curl
curl -sL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y build-essential nodejs
执行上述命令,安装Node.js 18 LTS
安装完成后,执行
node -v
npm -v
返回如下图所示,表示安装成功
2.3 安装pm2用于管理node项目
注意使用管理员权限,不然不能全局安装
sudo npm install pm2@latest -g
3 工程介绍
工程中主要代码为后端server.js、前端index.html
后端流程图如下
前端流程图如下
3.1 设计思路
想要控制BBB开发板控制LED开关,只需要通过命令行控制,下面这行代码即可打开LED0
echo 1 > /sys/class/leds/beaglebone:green:usr0/brightness
BBB开发板有四个led分别对应usr0、usr1、usr2、usr3通过控制他们的brightness控制位为0或1点亮或关闭led
设计网页,点击对应按钮后,执行响应操作即可实现对led的控制
由于BBB开发板系统内对led有占用,会导致usr0和usr2不规律闪烁,因此在程序执行前需要关闭其他触发器对led的占用
for led in /sys/class/leds/beaglebone:green:usr*/; do
echo none > $led/trigger
done
3.2 核心代码
3.2.1 初始化LED
后端启动时,关闭其他触发器对led的占用,并使全部led为关闭状态
function initializeLEDs() {
const command = 'for led in /sys/class/leds/beaglebone:green:usr*/; do echo none > $led/trigger; done';
childProcess.exec(command, (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
// 可以在这里打印输出或错误信息
console.log(`stdout: ${stdout}`);
console.error(`stderr: ${stderr}`);
});
}
3.2.2 LED状态广播
为了确保每个网页客户端打开后,led状态统一,在客户端链接时,向客户端发送当前led状态,
io.on('connection', (socket) => {
console.log('A user connected');
for (let i = 0; i < 4; i++) {
exec(`cat /sys/class/leds/beaglebone:green:usr${i}/brightness`, (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
const state = parseInt(stdout) === 1;
ledStates[i] = state;
socket.emit('ledStatus', i, state);
});
}
3.2.3 LED操作命令执行
执行对应led的开关命令
function execCommands(turnOn) {
for (let i = 0; i < 4; i++) {
const ledPath = `/sys/class/leds/beaglebone:green:usr${i}/`;
exec(`echo none > ${ledPath}trigger`, (error) => {
if (error) console.error(`exec error: ${error}`);
});
exec(`echo ${turnOn ? 1 : 0} > ${ledPath}brightness`, (error) => {
if (error) console.error(`exec error: ${error}`);
io.emit('ledStatus', i, turnOn);
});
}
}
3.2.4 前端程序
index.html
文件通常是一个网页的入口点,包含 HTML、CSS 和 JavaScript 代码,用于定义网页的结构、样式和行为。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Funpack3-5 LED Control</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
padding-top: 50px;
}
.led-container {
display: inline-block;
margin: 0 10px;
}
.led {
width: 50px;
height: 50px;
border-radius: 50%;
background-color: #ccc;
border: 2px solid #000;
cursor: pointer;
display: inline-block;
}
button {
margin: 10px;
padding: 10px 20px;
font-size: 16px;
}
.buttons-row {
text-align: center;
margin-top: 20px;
}
</style>
</head>
<body>
<h1>Funpack3-5 LED Control</h1>
<!-- LED circles with onclick event listeners -->
<div class="led-container"><div class="led" id="led0" onclick="toggleLED(0)"></div></div>
<div class="led-container"><div class="led" id="led1" onclick="toggleLED(1)"></div></div>
<div class="led-container"><div class="led" id="led2" onclick="toggleLED(2)"></div></div>
<div class="led-container"><div class="led" id="led3" onclick="toggleLED(3)"></div></div>
<!-- Buttons row -->
<div class="buttons-row">
<button onclick="turnOnLEDs()">全开</button>
<button onclick="turnOffLEDs()">全关</button>
</div>
<script src="https://cdn.socket.io/4.0.1/socket.io.min.js"></script>
<script>
const socket = io();
let ledStates = {0: false, 1: false, 2: false, 3: false};
function turnOnLEDs() {
socket.emit('turnOnLEDs');
}
function turnOffLEDs() {
socket.emit('turnOffLEDs');
}
function toggleLED(ledNumber) {
const newState = !ledStates[ledNumber];
socket.emit('toggleLED', ledNumber, newState);
ledStates[ledNumber] = newState;
updateLEDStatus(ledNumber, newState);
}
function updateLEDStatus(ledNumber, isOn) {
const ledElement = document.getElementById('led' + ledNumber);
ledElement.style.backgroundColor = isOn ? 'red' : '#ccc';
}
// 监听服务器发送的LED状态更新事件
socket.on('ledStatus', (ledNumber, isOn) => {
ledStates[ledNumber] = isOn;
updateLEDStatus(ledNumber, isOn);
});
</script>
</body>
</html>
4 部署流程与效果
4.1 部署完成nodejs后,打开下载的工程文件
在项目文件夹中,运行下面的命令安装依赖
npm install express socket.io ejs
4.2 启动工程
在项目文件夹中,运行下面的命令启动项目
node server.js
返回如下条目即运行成功
打开 http://<BeagleBone-IP>:9000 ,即可访问网页客户端,点击按钮点亮对应的LED,效果如下:
4.3 部署工程并开机启动(可选)
4.3.1 输入下面的代码,使用pm2部署服务
pm2 start server.js --name funpack3
或以下命令指定运行的端口,默认监听9000
pm2 start server.js --name funpack3 --port=9000
4.3.2 查询pm2运行状态
pm2 status
可以看到已经成功运行
4.3.3 保存配置
pm2 save
4.3.4 开机启动
pm2 startup
这个命令会检测你的操作系统,并提供一个命令,让你复制并执行。这个命令会安装一个系统服务,用于管理PM2的启动。
比如这里这个指令是
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u debian --hp /home/debian
执行即可开机启动
4.4 防火墙配置(或许需要)
使用iptables 管理防火墙,开放9000端口
sudo iptables -A INPUT -p tcp --dport 9000 -j ACCEPT
5 总结
本项目展示了如何使用BeagleBone Black开发板和Node.js技术栈来控制硬件LED。通过Web界面,用户可以直观地控制LED的状态,实现全开和全关操作。