【Funpack3-5】BeagleBone® Black 变频呼吸灯
该项目使用了BeagleBone® Black,实现了变频呼吸灯的设计,它的主要功能为:基于BeagleBone® Black及其板载资源的一个变频呼吸灯。
标签
嵌入式系统
Funpack活动
MPU
开发板
dzsl_user
更新2025-01-15
15

Funpack3-5 BeagleBone® Black 变频呼吸灯

项目描述

本项目基于 BeagleBone® Black 实现了一个变频呼吸灯,所有功能全部基于 BeagleBone® Black 裸板,无需其他外设

BeagleBone® Black 是一款面向开发人员和业余爱好者的低成本、高扩展、并有社区支持的开发平台。处理器选用了TI AM3358芯片,基于ARM Cortex-A8架构处理器。还配备了丰富的扩展资源,包括HDMI接口、以太网、SD 卡槽、并预留了足够多的管脚用于AD转换、LCD显示屏、PWM输出、I2C、串口等等。板卡可运行完整的 Linux 系统,且支持多种编程语言。

基本目标如下:

  1. 使用 PRU 控制一个 LED
  2. 需要实现呼吸灯效果
  3. 使用一个按键控制闪烁速度

硬件及软件

硬件原理图

本项目所需功能在 BeagleBone® Black 裸板上全集成了,因此硬件部分直接基于裸板即可:

基于上述原理图我们可以知道如下信息:

  1. 输入为 S2 ,对应的 IO 为 LCD_DATA2,即 P8_43
    • 根据官方文档可知该 io 连接在 PRU1
  1. 输入为是个 led 中的任意一个即可,分别为:
    • USR0:对应 GPIO1_21
    • USR1:对应 GPIO1_22
    • USR2:对应 GPIO1_23
    • USR3:对应 GPIO1_24

软件 IO 适配

软件上我们需要配合硬件来操作,因此我们需要在 PRU 上编写代码前先关注下怎么配置 io

输入

对于输入 S2,由于上述硬件限制,因此我们只能够将程序放到 PRU1
又因为 S2 的输入刚好在 LCD 是 IO 上,BeagleBone® Black 中默认将这个 IO 作为了显示输出,如果我们需要在 PRU 中操作的话需要在 Linux 侧关闭原本输出功能
关闭 S2 的输出很简单,编辑板上 /boot/uEnv.txt 文件即可,将其中 disable_uboot_overlay_video=1 取消注释即可:

###Disable auto loading of virtual capes (emmc/video/wireless/adc)
#disable_uboot_overlay_emmc=1
# 就下面这句,取消注释即可
disable_uboot_overlay_video=1
#disable_uboot_overlay_audio=1
#disable_uboot_overlay_wireless=1
#disable_uboot_overlay_adc=1

此为,由于该 io 默认不是通过 PRU 控制,我们还需要在每次启动 PRU 程序前通过板载的 config-pin 将该 io 配置成 PRU 输入即可:

config-pin P8_43 pruin
config-pin -q P8_43

输出

对于输出的 LED 灯,默认这几个 LED 都被 Linux kernel 使用了:

cat /sys/class/leds/beaglebone\:green\:usr0/trigger
cat /sys/class/leds/beaglebone\:green\:usr1/trigger
cat /sys/class/leds/beaglebone\:green\:usr2/trigger
cat /sys/class/leds/beaglebone\:green\:usr3/trigger

因此我们需要在启动 PRU 程序前将其关闭。这里有两种方式关闭:

  1. 直接在启动 PRU 程序前通过自定义脚本往对应的节点里边关闭 Linux 的输出即可
  2. 借助官方提供的编译脚本来间接实现上述步骤

    在这里我们可以直接采用第二种方式来实现,基本步骤就是在对应的 PRU 源码中插入如下语句即可:
#pragma DATA_SECTION(init_pins, ".init_pins")
#pragma RETAIN(init_pins)
const char init_pins[] =
"/sys/class/leds/beaglebone:green:usr0/trigger\0none\0" \
"/sys/class/leds/beaglebone:green:usr1/trigger\0none\0" \
"/sys/class/leds/beaglebone:green:usr2/trigger\0none\0" \
"/sys/class/leds/beaglebone:green:usr3/trigger\0none\0" \
"\0\0";
  • 编译脚本会自动提取上述信息并自动设置对应 Linux kernel 的 io

各功能对应的主要代码片段及说明

之后就是软件部分了,这部分的核心逻辑如下:

按键部分

uint8_t isEdgeTriggered() {
static uint8_t lastButtonState = 1;

if (((__R31 & USER_KEY2) != USER_KEY2) && lastButtonState == 1) {
delay_ms(100);
if (((__R31 & USER_KEY2) != USER_KEY2)) {
lastButtonState = 0;
return lastButtonState;
}
}
else if (((__R31 & USER_KEY2) == USER_KEY2) && lastButtonState == 0) {
lastButtonState = 1;
return lastButtonState;
}
return 2;
}
  • 这部分主要的逻辑是通过 PRU 的 R31 寄存器从对应的 IO 口读取值
  • 然后通过配合延时逻辑实现软件消抖,防止误触
  • 最后通过一个静态变量实现边缘检测,在不同边沿返回不同的值,如果没有边沿则返回 2,方便其他逻辑

呼吸灯部分

void breathEffect(unsigned int delayTime) {
unsigned int i;
for (i = 0; i < STEP; i++) {
led(3, 1);
delay_us(i * delayTime / STEP);
led(3, 0);
delay_us((STEP - i) * delayTime / STEP);
}

for (i = STEP; i > 0; i--) {
led(3, 1);
delay_us(i * delayTime / STEP);
led(3, 0);
delay_us((STEP - i) * delayTime / STEP);
}
}
  • 这部分逻辑通过传入的延时时间来控制对应的频率
  • 同时也能够通过宏 STEP 来控制不同的步进,使得变频更加顺滑

总体逻辑

基本流程图如下:

image.png

对应的源码实现如下:

void main(void) {
unsigned int delayTime = SPEED_SLOW;
led_init();
led(0, 1);
led(1, 0);
led(2, 0);
while (1) {
if (isEdgeTriggered() == 1) {
if (delayTime == SPEED_FAST) {
delayTime = SPEED_SLOW;
led(0, 1);
led(1, 0);
led(2, 0);
} else if (delayTime == SPEED_SLOW) {
delayTime = SPEED_MEDIUM;
led(0, 0);
led(1, 1);
led(2, 0);
} else {
delayTime = SPEED_FAST;
led(0, 0);
led(1, 0);
led(2, 1);
}
}
breathEffect(delayTime);
}
}
  • 这部分为总体逻辑部分,我们会在开始初始化 led0 ~ led2,用于显示当前的挡位信息
  • 之后会通过按键检测切换不同的挡位,并亮起对应的 led
  • 最后通过上述呼吸灯程序来点亮 led3

功能展示及说明

本项目最终效果如下:

  • 通过下方 S2 开关切换挡位
  • 上方右边三个 led 为挡位显示
  • 上方最左边的 led 为对应控制的呼吸灯

对本活动的心得体会

本项目以 BeagleBone® Black 为核心,开发了一款变频呼吸灯,通过硬件与软件的结合,充分展示了嵌入式开发的魅力。在以下方面让我收获颇多:

  • 技术层面
    1. 硬件资源的高效利用:通过合理配置 PRU(可编程实时单元)和 GPIO 管脚,最大程度发挥了硬件的潜力
    2. Linux 系统与 PRU 的结合:利用 PRU 实现高效的实时控制,充分体现了 Linux 系统的灵活性和实时性之间的平衡
    3. 软件逻辑的模块化设计:将按键检测、呼吸灯效果及主逻辑分别独立成模块,便于调试和扩展
    4. 实时控制能力的发挥:PRU 的高效性在呼吸灯的控制中得到了充分验证,通过精细的延时和步进调整,实现了顺滑的变频效果,表现出优秀的实时控制性能
  • 实践能力提升
    1. 硬件与软件的协同开发能力:在硬件资源有限的情况下,需要结合硬件设计和软件调试,通过逐步排查和配置,实现对复杂功能的精准控制
    2. 动手调试能力的加强:从禁用 Linux 默认功能,到使用 config-pin 命令配置 IO,以及调试 LED 输出模式,整个过程强化了对嵌入式开发流程的理解和实践
    3. 嵌入式系统的深入理解:项目开发过程中,涉及到对 PRU 寄存器的直接操作和 Linux 系统层的配置,深刻体会到嵌入式系统底层设计的复杂性和精妙之处
      总之,本项目从硬件、软件到调试,充分展示了嵌入式开发的魅力和挑战,为未来进一步探索嵌入式技术打下了良好的基础
附件下载
src.zip
团队介绍
暂无团队
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号