这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » BeagleBone®Black——成果贴

共2条 1/1 1 跳转至

BeagleBone®Black——成果贴

菜鸟
2026-03-13 16:13:26     打赏

成果贴

一、前言

由于笔者一直在单片机平台开发,虽然以前也玩过树莓派和ubuntu电脑,但是在linux平台开发依然算是第一次,因此给自己指定了一个比较简单的小目标,实际开发下来,在ai的加持下还算顺利,各位大神看个乐子就好。

二、项目介绍

1、项目计划

本项目旨在利用 BeagleBone Black Rev C 内置的 Linux 系统和网络功能,搭建一个轻量级 Web 服务器,用户只需在手机或电脑浏览器中访问 BBB 的 IP 地址,即可远程控制其 4板载用户 LED的亮灭状态。该系统无需额外硬件,仅使用 BBB 自身资源,相对简单。

2、实现情况

先在ubuntu电脑上实验和开发,使用ai辅助开发,待做出一个较为满意的状态后,再移植到开发板上。虽然开发过程中遇到很多不熟悉的内容,但是也算完美达到自己的预期了!

三、整体设计思路

架构

采用经典的前后端分离架构,app.py对应后端服务,index.html对应前端界面。

前端——动态生成4个LED控制按钮,每2s自动同步状态

后端——获取LED状态,切换LED状态,返回前端页面

debian——通过文件系统I/O来控制和查询LED状态

整体架构时序图

 ┌─────────┐          ┌─────────┐          ┌─────────┐          ┌─────────┐
 │ Browser │          │  Flask  │          │ Sysfs   │          │  LED    │
 │         │          │  Server │          │ (文件)  │          │ Hardware│
 └────┬────┘          └────┬────┘          └────┬────┘          └────┬────┘
      │                    │                    │                    │
      │  GET /             │                    │                    │
      │───────────────────>│                    │                    │
      │                    │                    │                    │
      │  HTML Response     │                    │                    │
      │<───────────────────│                    │                    │
      │                    │                    │                    │
      │  GET /api/led/status                   │                    │
      │───────────────────>│                    │                    │
      │                    │  read brightness   │                    │
      │                    │───────────────────>│                    │
      │                    │                    │  read LED state    │
      │                    │                    │<───────────────────│
      │                    │  [0,1,0,1]         │                    │
      │                    │<───────────────────│                    │
      │  JSON [0,1,0,1]    │                    │                    │
      │<───────────────────│                    │                    │
      │                    │                    │                    │
      │  User clicks LED 1 │                    │                    │
      │                    │                    │                    │
      │  POST /api/led/toggle/1               │                    │
      │───────────────────>│                    │                    │
      │                    │  write '1'         │                    │
      │                    │───────────────────>│                    │
      │                    │                    │  turn on LED       │
      │                    │                    │───────────────────>│
      │                    │  success           │                    │
      │                    │<───────────────────│                    │
      │  {"success":true}  │                    │                    │
      │<───────────────────│                    │                    │
      │                    │                    │                    │
      │  (Every 2s) GET /api/led/status        │                    │
      │───────────────────>│                    │                    │
      │                    │  read brightness   │                    │
      │                    │───────────────────>│                    │
      │                    │<───────────────────│                    │
      │<───────────────────│                    │                    │
      │                    │                    │                    │
      ▼                    ▼                    ▼                    ▼

四、功能展示

网页界面:

image-20260313143933243.png

对应实物图:

29c8a46dec01339f26fa03e8b9572bde_origin(1).jpg

视频演示:哔哩哔哩——

实际代码

 # app.py
 import os
 from flask import Flask, render_template, jsonify
 
 app = Flask(__name__)
 
 # BBB 上的 4 个 LED 名称
 LED_NAMES = [
     "beaglebone:green:usr0",
     "beaglebone:green:usr1",
     "beaglebone:green:usr2",
     "beaglebone:green:usr3"
 ]
 
 LED_PATH = "/sys/class/leds/{}/brightness"
 
 # 检测是否运行在 BBB 硬件上
 def is_bbb_hardware():
     return os.path.exists(LED_PATH.format(LED_NAMES[0]))
 
 # 开发模式下模拟 LED 状态
 SIMULATED_LEDS = [0, 0, 0, 0]
 
 def get_led_status():
     """读取所有 LED 当前状态(0=关, 1=开)"""
     if not is_bbb_hardware():
         return SIMULATED_LEDS.copy()
 
     status = []
     for name in LED_NAMES:
         try:
             with open(LED_PATH.format(name), 'r') as f:
                 val = int(f.read().strip())
                 status.append(1 if val > 0 else 0)
         except Exception as e:
             print(f"Error reading {name}: {e}")
             status.append(0)
     return status
 
 def set_led(index, state):
     """设置指定 LED 状态(0=关, 1=开)"""
     if 0 <= index < len(LED_NAMES):
         if not is_bbb_hardware():
             SIMULATED_LEDS[index] = state
             print(f"[DEV MODE] LED {index} -> {'ON' if state else 'OFF'}")
             return True
 
         name = LED_NAMES[index]
         try:
             with open(LED_PATH.format(name), 'w') as f:
                 f.write('1' if state else '0')
             return True
         except Exception as e:
             print(f"Error writing to {name}: {e}")
             return False
     return False
 
 @app.route('/')
 def index():
     return render_template('index.html')
 
 @app.route('/api/led/status')
 def led_status():
     return jsonify(get_led_status())
 
 @app.route('/api/led/toggle/<int:index>', methods=['POST'])
 def toggle_led(index):
     if 0 <= index < 4:
         current = get_led_status()[index]
         new_state = 1 - current
         success = set_led(index, new_state)
         if success:
             return jsonify({"success": True, "state": new_state})
     return jsonify({"success": False}), 400
 
 if __name__ == '__main__':
     if is_bbb_hardware():
         print("BBB hardware detected - using real LEDs")
     else:
         print("Running in DEVELOPMENT mode - simulating LEDs")
 
     app.run(host='0.0.0.0', port=5000, debug=False)
 <!-- templates/index.html -->
 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <title>BBB LED 控制面板</title>
     <style>
         body {
             font-family: Arial, sans-serif;
             text-align: center;
             padding: 40px;
             background: #f0f0f0;
         }
         h1 {
             color: #2c3e50;
         }
         .led-grid {
             display: grid;
             grid-template-columns: repeat(2, 1fr);
             gap: 20px;
             max-width: 400px;
             margin: 30px auto;
         }
         .led-btn {
             height: 80px;
             font-size: 18px;
             font-weight: bold;
             border: none;
             border-radius: 12px;
             cursor: pointer;
             transition: all 0.2s;
             background: #ccc; /* 默认灰色 = 关 */
             color: white;
         }
         .led-btn.on {
             background: #2ecc71; /* 绿色 = 开 */
             box-shadow: 0 0 15px #2ecc71;
         }
         .led-btn:active {
             transform: scale(0.95);
         }
         .status {
             margin-top: 20px;
             font-size: 14px;
             color: #7f8c8d;
         }
     </style>
 </head>
 <body>
     <h1>BeagleBone Black LED 控制器</h1>
     <div class="led-grid" id="ledGrid">
         <!-- 按钮由 JS 动态生成 -->
     </div>
     <div class="status" id="status">正在加载状态...</div>
 
     <script>
         const ledCount = 4;
         const grid = document.getElementById('ledGrid');
         const statusEl = document.getElementById('status');
 
         // 创建按钮
         for (let i = 0; i < ledCount; i++) {
             const btn = document.createElement('button');
             btn.className = 'led-btn';
             btn.textContent = `LED ${i}`;
             btn.dataset.index = i;
             btn.onclick = () => toggleLED(i);
             grid.appendChild(btn);
         }
 
         // 获取当前状态并更新 UI
         async function updateStatus() {
             try {
                 const res = await fetch('/api/led/status');
                 const states = await res.json();
                 const buttons = document.querySelectorAll('.led-btn');
                 buttons.forEach((btn, i) => {
                     if (states[i] === 1) {
                         btn.classList.add('on');
                     } else {
                         btn.classList.remove('on');
                     }
                 });
                 statusEl.textContent = "状态已同步";
             } catch (e) {
                 statusEl.textContent = "❌ 无法获取 LED 状态";
                 console.error(e);
             }
         }
 
         // 切换 LED
         async function toggleLED(index) {
             statusEl.textContent = "切换中...";
             try {
                 const res = await fetch(`/api/led/toggle/${index}`, {
                     method: 'POST'
                 });
                 const data = await res.json();
                 if (data.success) {
                     updateStatus();
                 } else {
                     statusEl.textContent = "❌ 操作失败";
                 }
             } catch (e) {
                 statusEl.textContent = "❌ 网络错误";
                 console.error(e);
             }
         }
 
         // 页面加载时获取状态
         updateStatus();
         // 每 2 秒自动同步一次(防止手动操作导致不一致)
         setInterval(updateStatus, 2000);
     </script>
 </body>
 </html>

五、心得体会

由于笔者主要开发单片机,因此体验linux+web开发的感觉很不一样:

●要先安装一堆依赖,搞一堆环境;

●开发起来真快,很少的代码就能实现一个很炫的效果(相对单片机来说);

●涉及面广。

可能这就是封装和分层思想的一种体现吧,若论指令如何一条一条执行的,那这个项目是无比复杂的:网页、网络、python脚本、linux内核,硬件。每一个深入下去都深不见底,一个简单的点灯都能牵扯背负这么多。但是现代成熟的软件工程将之分解,使“点灯”不再复杂。





关键词: 成果     BeagleBone    

专家
2026-03-14 17:25:19     打赏
2楼

学习能力很强啊


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]