Beagleboneblack simppru点灯
项目介绍
BeagleBone Black 是一款功能强大的开源硬件开发板,广泛应用于嵌入式系统和物联网项目。其内置的 PRU(Programmable Real-time Unit)能够实现高精度、低延迟的实时控制,为多种应用提供了便利。在本项目中,我将利用 BeagleBone Black 的 PRU 来控制 LED。项目并未通过传统的pru实现方式点灯,而是使用simppru这种语言在beagleboneblack上实现了点灯和按键控制led亮度。
设计思路
通过读取按键对应引脚的高低电平,来实现对led亮度的调节。只需在beagleboneblack上外扩一个按键和一个led即可,硬件连接方面,我们将 LED 灯与BeagleBone Black 的 GPIO 引脚相连。对应引脚分别为P8_12(LED), P8_15(key)。能够根据用户设置调整led亮度,我设置的是利用 PRU 的高精度定时能力,实现精确的灯光控制。PRU具有 1.低延迟:可以直接控制 GPIO,减少了 CPU 的干预,同时防止linux系统运行和led产生冲突。2.简单的编程模型:通过simppru语言编写程序,易于理解和实现的优势
对于初学者来说,对PRU进行编程艰巨苦难且繁琐,为 PRU编写固件,编写加载程序程序。对于经验丰富的开发人员来说,这可能是一件容易的事,但对新手极其不友好。因此,我选择simppru这个语言,隐藏所有底层操作以及提供简单易用的接口来编程PRU。
3. 硬件设计
电路设计:通过简单的电路连接 LED 和 BeagleBone Black 的 GPIO 引脚,使用电阻限流,确保led不损坏。
硬件介绍
BeagleBone Black
处理器:1 GHz ARM Cortex-A8
内存:512 MB DDR3 RAM
存储:4 GB eMMC 存储,支持 microSD 卡扩展
接口:多种 GPIO、I2C、SPI、PWM 等接口
PRU:两个独立的 PRU 单元,能够实现实时任务处理
环境部署
开箱后第一件事,给sd卡烧录最新的镜像,镜像可在管网找到:https://www.beagleboard.org/distros。我下载的是AM335x 11.7 2023-09-02 4GB microSD IoT这个镜像,IoT后缀不含图形化界面。使用win32diskimager将下载的镜像烧录到sd卡即可。完成后,插上sd卡,按住s2按键直至蓝灯亮起,等待一段较长的时间(虚拟u盘弹出后),使用putty通过ssh连接bbb。默认IP:192.168.7.2,Port:22。
登录用户debian,密码默认为temppwd,可以看到成功进入。
接下来就是想办法实现pru点亮led的,国内对于bbb在这块的使用,可以说是基本没有,完全找不到。所以,官网启动!在官网上可以找到bbb pru的cookbook。里面内容稍显复杂,对新手不太友好,我尝试另寻他法,最后发现了simppru这一语言,能够简化bbb上pru的开发。
主机与bbb之间通过Usb共享网络,因为接下来需要从github上clone。
打开网络连接,图中两个被红框框选的分别是我的笔记本连接的网络,用来给bbb共享,右键WLAN选择属性,共享,选择以太网4进行共享。将以太网4的ipv4属性改为自动获得ip地址和自动获得dns地址即可。完成后在ssh中设置默认网关。
先clone到本地,wget https://github.com/VedantParanjape/simpPRU/releases/download/1.4/simppru-1.4-armhf.deb,注意可能会报错,这是dns没有配置。
配置一下dns地址即可
Clone完成后,运行sudo dpkg -i simppru-1.4-armhf.deb完成环境配置。运行simppru –-help检查环境是否搭建完成。
完成后我们进入代码编写阶段。
运行vi test.sim开始编写。
以下是一个简单的点灯代码
代码源码
while:true {
// 当 P8_11 引脚为高电平时
while:(digital_read(P8_11)) {
start_counter(); // 启动计时器
// 在计时器读数小于 40000000 时,将 P8_12 设为高电平
while:read_counter()<40000000 {
digital_write(P8_12, true); // P8_12 设为高电平
}
// 在计时器读数小于 160000000 时,将 P8_12 设为低电平
while:read_counter()<160000000 {
digital_write(P8_12, false); // P8_12 设为低电平
}
stop_counter(); // 停止计时器
}
// 当 P8_11 引脚为低电平时
while:(not digital_read(P8_11)) {
start_counter(); // 启动计时器
// 在计时器读数小于 40000000 时,将 P8_12 设为低电平
while:read_counter()<40000000 {
digital_write(P8_12, false); // P8_12 设为低电平
}
// 在计时器读数小于 160000000 时,将 P8_12 设为高电平
while:read_counter()<160000000 {
digital_write(P8_12, true); // P8_12 设为高电平
}
stop_counter(); // 停止计时器
}
}
注意实际使用时不要将代码直接粘贴,因为simppru的编译器中没有对注释的编译,此处只是个人为了方便注释使用
运行simppru test.sim --load,一步完成对代码的编译,并加载生成的固件。再运行:
echo stop > /sys/class/remoteproc/remoteproc1/state
echo start > /sys/class/remoteproc/remoteproc1/state
观察即可看到led已亮起,通过按键可发现灯的亮度有变化。
按键改变呼吸速度代码:
int count:=200000;
while:true{
while:(digital_read(P8_11)){
start_counter();
while:read_counter()<count{
digital_write(P8_12,true);
}while:read_counter()<2000000-count{
digital_write(P8_12,false);
}
if:(count<2000000){
count:=count+200000;
}else{
count:=0;
}
stop_counter();
}
while:(not digital_read(P8_11)){
start_counter();
while:read_counter()<count{
digital_write(P8_12,true);
}while:read_counter()<2000000-count{
digital_write(P8_12,false);
}
if:(count<2000000){
count:=count+20000;
}else{
count:=0;
}
stop_counter();
}
}
程序框图
心得体会
实际在使用过程中,我感觉simmpru并没有想象中易用,在语法格式上麻烦很多,尤其是对变量的控制,编译器的提醒也不是很详细。只能用来做入门级的功能的完成。真正对于pru开发的话还是使用传统的做法,这只能说是一个尝试。
这是第一次参加funpack活动,原本以为点灯会相当简单,结果还是花费了一些时间的,最后在被环境的一次次折磨中终于完成了本次任务。因为是个学生党的原因,校园网限制设备没办法共享之类、sftp总是传输失败的问题也是层出不穷,甚至还崩了一次系统。不过幸好问题都得到了解决。总之,期待下一次活动,祝愿越办越好。