Funpack3-5 BeagleBone® Black入门指南与网页点灯
所要完成的项目是funpack活动板卡2的任务2:
任务2:在系统中建立一个网页,并且与LED联动,使用网线连接到设备上时,可以从网页中控制LED的开关与闪烁
开发任务主要在板子上linux环境的搭建,连接网络,搭建板卡的开发环境。
开始之前的介绍,很详细,建议通读。
开发环境搭建
连接模式
板卡的连接模式有很多种,本身就可以当作一个小主机(SBC单板计算机)
桌面模式:microHDMI,vnc
命令行:ssh(网络连接),virtual serial port(usb连接的虚拟串口),3.3v的FTDI线缆(串口)
网络
网络连接方式
- 千兆以太网:RJ45 Port
- usb共享网络
- wifi适配器(链接中为官方推荐的wifi适配器)
连接网络
只要通过usb与主机连接,两者就连通了网络
对于主机端的ip:
BBB:
iperf带宽测试小实验
BBB作为主机,默认tcp连接
iperf3 -s
电脑作为主机
iperf3 -c 192.168.7.2
连接公网
上述主机与BBB建立了网络连接,但BBB还未与外网连接
通过usb共享网络可以很方便的实现网络连接
在linux中setting up IP masquerading
在主机上执行ipMasquerade.sh便可以共享主机网络,主要是允许了ipv4的转发,通过iptables添加流量转发规则
在主机上执行setDNS.sh,为BBB添加网关,以及dns,脚本中需要用root用户ssh登录,而默认镜像中是没有root密码的,需要在BBB上执行sudo passwd root
设置密码,且默认root是不给ssh登录的,需要更改/etc/ssh/sshd_config
中的#PermitRootLogin prohibit-password
为PermitRootLogin yes
以允许root的密码模式进行ssh连接(设置后sudo systemctl restart sshd
让配置生效)
或直接在开发板更新/etc/resolv.conf与主机相同的dns地址,并添加主机ip为默认网关,与脚本一样
至此已经完成联网
开发环境
在将开发板升级为较新的镜像后(t卡烧录好自动升级板卡mmc的镜像后插入电脑,重启会自动进入tf卡中的系统并执行升级)
在开发板中执行sudo systemctl start bb-code-server.service
启动code-server
在浏览器中打开 http://192.168.7.2:3000 即可进入板子上的vscode开发环境~首次体验这种开发环境,流畅的同时十分高效
任务
网页与LED联动
目标:
在系统中建立一个网页,并且与LED联动,使用网线连接到设备上时,可以从网页中控制LED的开关与闪烁
教程:
完整的copy仿照里面的app3.py其实就以及完成这个任务了
但默认的文字的界面实在不好看,且板子上有四个led,我们将他们统统控制起来,调整样式,最终效果如下(功能展示及说明):以及闪烁开关:
与实物的照片:
部分关键代码解析:
通过python搭建网页后台
使用库Flask搭建后台
from flask import Flask, render_template, jsonify
linux开发环境中将板子上的四个led注册到了文件系统中,
路径在:/sys/class/leds/beaglebone:green:usr0/为usr0到usr3
注册html中的事件回调来控制led的开关
@app.route('/toggle_led/<int:led_index>')
def toggle_led(led_index):
current_state = get_led_state(led_index)
new_state = 'off' if current_state == 'on' else 'on'
set_led_state(led_index, new_state)
return jsonify({"status": new_state})
再优化下界面,通过图片切换控制并表示led状态
闪烁也是同样的控制逻辑
基本流程,分为网页与后台:
完整代码(服务端):
from flask import Flask, render_template, jsonify
import threading
import time
app = Flask(__name__)
# LED 控制路径
LED_PATHS = [
"/sys/class/leds/beaglebone:green:usr0/",
"/sys/class/leds/beaglebone:green:usr1/",
"/sys/class/leds/beaglebone:green:usr2/",
"/sys/class/leds/beaglebone:green:usr3/"
]
# LED 状态管理
led_states = [{'state': 'off', 'blink': False, 'last_toggle': 0} for _ in LED_PATHS]
blink_interval = 0.5 # 闪烁间隔(秒)
def write_led_brightness(led_index, value):
"""直接操作 LED 文件写入亮度值"""
try:
with open(LED_PATHS[led_index] + 'brightness', 'w') as f:
f.write(str(value))
except Exception as e:
print(f"Error writing LED {led_index} brightness: {e}")
@app.route('/')
def index():
"""主页显示当前 LED 状态"""
# 初始化时关闭 triggers
for i in range(len(LED_PATHS)):
try:
with open(LED_PATHS[i] + 'trigger', 'w') as f:
f.write('none')
except Exception as e:
print(f"Error setting LED {i} trigger: {e}")
# 显示所有 LED 状态
led_states_display = [led['state'] for led in led_states]
return render_template('index.html', led_states=led_states_display)
@app.route('/toggle_led/<int:led_index>')
def toggle_led(led_index):
"""切换 LED 开关状态"""
if led_index < 0 or led_index >= len(LED_PATHS):
return jsonify({'error': 'Invalid LED index'}), 400
led = led_states[led_index]
if led['blink']:
# 如果正在闪烁,停止闪烁
led['blink'] = False
# 切换开关状态
new_state = 'off' if led['state'] == 'on' else 'on'
led['state'] = new_state
write_led_brightness(led_index, 1 if new_state == 'on' else 0)
return jsonify({'status': new_state})
@app.route('/blink_led/<int:led_index>')
def blink_led(led_index):
"""启动或停止 LED 闪烁"""
if led_index < 0 or led_index >= len(LED_PATHS):
return jsonify({'error': 'Invalid LED index'}), 400
led = led_states[led_index]
if led['blink']:
# 停止闪烁
led['blink'] = False
led['state'] = 'off'
write_led_brightness(led_index, 0)
return jsonify({'status': 'off'})
else:
# 开始闪烁
led['blink'] = True
print("start blink")
led['last_toggle'] = time.time()
return jsonify({'status': 'blinking'})
def update_leds():
"""后台线程定期更新 LED 闪烁状态"""
while True:
current_time = time.time()
for i, led in enumerate(led_states):
if led['blink']:
# 检查是否需要切换状态
print("blinking");
if current_time - led['last_toggle'] >= blink_interval:
led['state'] = 'off' if led['state'] == 'on' else 'on'
led['last_toggle'] = current_time
write_led_brightness(i, 1 if led['state'] == 'on' else 0)
time.sleep(0.1) # 减少 CPU 占用
if __name__ == '__main__':
threading.Thread(target=update_leds, daemon=True).start()
app.run(host='0.0.0.0', port=5000, debug=True)
对本活动的心得体会:
linux开发板玩起来很有趣,能学到很多东西,选择的板卡也很优秀,有着很多社区支持,有一本入门的cookbook和一个pru的cookbook,指导很详细。希望能多多参加这样的活动,多多学习多多总结与分享。