【幸狐Omni3576边缘计算套件试用体验】PWM呼吸灯
本文介绍了幸狐Omni3576边缘计算套件实现 GPIO 输出电平的控制及 PWM 输出即呼吸灯效果的项目设计流程。
GPIO 点灯
介绍了三种方法实现 GPIO 输出电平的控制,包括 sysfs 控制、Python 控制、C 程序控制。

使用 GPIO sysfs 接口控制 I/O
将 GPIO 控制从内核空间导出到用户空间
sudo su
echo 95 > /sys/class/gpio/export
设备目录和设备属性
当写入 GPIO 编号到 /sys/class/gpio/export
时,内核会将这个 GPIO 导出到用户空间,使之可以通过 /sys/class/gpio/gpio<编号>
目录来进行后续操作(如配置方向、设置或读取电平)。
root@luckfox:/home/luckfox# ls /sys/class/gpio
export gpio95 gpiochip0 gpiochip128 gpiochip32 gpiochip509 gpiochip64 gpiochip96 unexport
在 /sys/class/gpio/gpioN
(N=1,2,3,5,...)设备目录下有多种属性,可以通过这些属性控制,从而实现对 GPIO 的控制。
cd /sys/class/gpio/gpio95
root@luckfox:/sys/class/gpio/gpio95# ls
active_low device direction edge power subsystem uevent value
其中
-
direction
:设置 GPIO 的输入(in)或输出(out)方向
-
value
属性:用于读取输入电平或者控制输出电平,写入或者读取到1
表示高电平,写入或者读取到0
表示低电平
-
edge
用于设置触发电平,只有将 GPIO 设置为中断的时候才会出现和使用这个属性
- 上升沿触发:rising
- 下降沿触发:falling
- 双边沿触发:both
- 禁用中断:none
控制 GPIO 引脚电平
设置方向
root@luckfox:/sys/class/gpio/gpio95
/sys/class/gpio/gpio95
echo out > direction
echo in > direction
设置 value
属性来控制 GPIO 输出电平。
echo 1 > value
echo 0 > value

Python 方案
使用 python-periphery 库进行 IO 控制,需要安装该库
sudo apt install python3-periphery
控制 LED 交替闪烁,python 代码如下
#!/usr/bin/python3
from periphery import GPIO
import time
LED_Pin = 95
LED_GPIO = GPIO(LED_Pin, "out")
while True:
try:
LED_GPIO.write(True)
time.sleep(0.5)
LED_GPIO.write(False)
time.sleep(0.5)
except KeyboardInterrupt:
LED_GPIO.write(False)
break
except IOError:
print ("Error")
LED_GPIO.close()
新建 gpio.py
文件,使用 vim
工具粘贴上述代码,保存并退出 vim
touch gpio.py
vim gpio.py
运行程序
chmod 777 gpio.py
./gpio.py
效果见视频
C 方案
下载并解压 C 程序文件,将文件夹上传至板端;
进入工程文件夹,包含 sysfs_gpio.c
、sysfs_gpio.h
、main.c
和 Makefile
四个文件;
在 sysfs_gpio.h
文件中定义了 Omni3576 的引脚物理编码,并且在主函数中调用;
编译程序
root@luckfox:/home/luckfox/Luckfox_GPIO_C
运行程序,可以在终端上查看 GPIO信息,并逐个点亮和熄灭LED:
root@luckfox:/home/luckfox/Luckfox_GPIO_C

该程序实现所有引脚电平依次翻转输出,若要实现单个 IO 电平翻转,需要修改 main.c
int i = 0;
while (1) {
DEV_GPIO_Mode(x[i], 1);
SYSFS_GPIO_Write(x[i], 0);
DEV_Delay_ms(500);
SYSFS_GPIO_Write(x[i], 1);
DEV_Delay_ms(500);
SYSFS_GPIO_Write(x[i], 0);
DEV_Delay_ms(500);
i++;
if (i > 0)
i = 25;
}
此时仅 95
号引脚输出高低电平。
PWM 呼吸灯
脉冲宽度调制(Pulse Width Modulation,PWM)是一种通过控制信号的脉冲宽度来实现模拟信号输出的威廉希尔官方网站
。
PWM 常用于嵌入式系统和电子设备中,用于控制电机速度、LED 亮度、音频信号生成等应用。
在 Linux 系统中,PWM 设备通常通过 sysfs 文件系统进行管理和配置,其设备目录通常位于 /sys/class/pwm/
目录下。
设备查看
查看 PWM 接口,pwmchip0 为屏幕的背光,系统默认开启
root@luckfox:/# ls -l /sys/class/pwm

控制 PWM
导出到用户空间(对应 GPIO0_D3_d)
echo 0 > /sys/class/pwm/pwmchip0/export
Python 方案
安装 python3-periphery
库
sudo apt install python3-periphery
新建 pwm.py
文件
mkdir PWM
cd PWM
touch pwm.py
通过 vim
工具编辑 pwm.py
文件
from periphery import PWM
import time
import numpy as np
pwm = PWM(0, 0)
pwm.frequency = 100
pwm.polarity = "normal"
pwm.duty_cycle = 0
pwm.enable()
try:
while True:
for i in np.linspace(0, 2 * np.pi, 100):
duty_cycle = (np.sin(i) + 1) / 2
pwm.duty_cycle = duty_cycle
time.sleep(0.01)
except KeyboardInterrupt:
pwm.disable()
pwm.close()
其中 time.sleep(0.01)
与呼吸周期有关。
pwm = PWM(0, 0) # 开启 PWM chip 0, channel 0
pwm.frequency = 100 # 设置100Hz频率
pwm.polarity = "normal" # 设置 PWM 极性
pwm.duty_cycle = 0 # 初始占空比
pwm.enable() # 使能 PWM
要实现呼吸灯效果,只需创建一个占空比循环,逐步增加占空比到最大值,再逐步减少到最小值。
该循环可使用 np.sin()
函数来模拟,达到亮度平稳变化的目标效果。
while True:
for i in np.linspace(0, 2 * np.pi, 100):
duty_cycle = (np.sin(i) + 1) / 2
pwm.duty_cycle = duty_cycle
time.sleep(0.02)
sin(x)
函数在一个周期内的值会在 -1
和 1
之间变化,
通过设计函数 (np.sin(i) + 1) / 2
(输出范围:0
~ 1
)
使得占空比 ( duty_cycle
) 在 0
和 1
之间变化。
运行程序
chmod +x pwm.py
./pwm.py
效果见视频。
C 方案
新建 pwm.c
文件
touch pwm.c
通过 vim
工具编辑 pwm.c
文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#define PWM_PATH "/sys/class/pwm/pwmchip10"
#define PERIOD_NS 1000000
#define MAX_DUTY_CYCLE_NS 1000000
#define MIN_DUTY_CYCLE_NS 0
#define PI 3.141592653589793
int pwm_export(int channel) {
FILE *pwm_export = fopen(PWM_PATH "/export", "w");
if (!pwm_export) {
perror("Failed to open PWM export");
return 1;
}
fprintf(pwm_export, "%d", channel);
fclose(pwm_export);
return 0;
}
int pwm_unexport(int channel) {
FILE *pwm_unexport = fopen(PWM_PATH "/unexport", "w");
if (!pwm_unexport) {
perror("Failed to open PWM unexport");
return 1;
}
fprintf(pwm_unexport, "%d", channel);
fclose(pwm_unexport);
return 0;
}
int pwm_set_period(int channel, int period_ns) {
char period_path[128];
snprintf(period_path, sizeof(period_path), PWM_PATH "/pwm%d/period", channel);
FILE *period_file = fopen(period_path, "w");
if (!period_file) {
perror("Failed to open PWM period");
return 1;
}
fprintf(period_file, "%d", period_ns);
fclose(period_file);
return 0;
}
int pwm_set_duty_cycle(int channel, int duty_cycle_ns) {
char duty_cycle_path[128];
snprintf(duty_cycle_path, sizeof(duty_cycle_path), PWM_PATH "/pwm%d/duty_cycle", channel);
FILE *duty_cycle_file = fopen(duty_cycle_path, "w");
if (!duty_cycle_file) {
perror("Failed to open PWM duty cycle");
return 1;
}
fprintf(duty_cycle_file, "%d", duty_cycle_ns);
fclose(duty_cycle_file);
return 0;
}
int pwm_enable(int channel, int enable) {
char enable_path[128];
snprintf(enable_path, sizeof(enable_path), PWM_PATH "/pwm%d/enable", channel);
FILE *enable_file = fopen(enable_path, "w");
if (!enable_file) {
perror("Failed to open PWM enable");
return 1;
}
fprintf(enable_file, "%d", enable);
fclose(enable_file);
return 0;
}
int main() {
int channel = 0;
if (pwm_export(channel)) {
return 1;
}
if (pwm_set_period(channel, PERIOD_NS)) {
return 1;
}
if (pwm_enable(channel, 1)) {
return 1;
}
double step_size = (2 * PI) / 100.0;
while (1) {
for (double i = 0; i <= 2 * PI; i += step_size) {
double duty_cycle_ratio = (sin(i) + 1) / 2;
int duty_cycle_ns = (int)(duty_cycle_ratio * MAX_DUTY_CYCLE_NS);
if (pwm_set_duty_cycle(channel, duty_cycle_ns)) {
return 1;
}
usleep(20000);
}
}
if (pwm_enable(channel, 0)) {
return 1;
}
if (pwm_unexport(channel)) {
return 1;
}
return 0;
}
编译运行程序
gcc pwm.c -o pwm -lm
效果
见视频。
踩坑指南
出厂测试固件不包含 PWM 、IIC 等设备信息,因此若要调试 PWM 功能,需要重新烧录系统镜像。
准备工作
下载适用于 eMMC 的 Debian12 镜像;
镜像文件约 4 GB,需要进行哈希值校验;
进入镜像所在文档,PowerShell 执行指令
certutil -hashfile xxx.img MD5
待其输出哈希值后,与官方提供的 MD5.txt 文本中的数值进行对比,确保镜像完整。
下载 RK 驱动助手 DriverAssitant-RK驱动助手 和刷机工具 RKDevTool ;
打开 RK 驱动助手 DriverAssitant 并安装 USB 驱动程序;
硬件连接,开发板电源供电,Type-C 数据线连接电脑和开发板;
打开 瑞芯微开发工具
,选择 升级固件
标签下的 切换
选项,之后便会显示 切换 Rockusb 成功
字样。

固件烧录
打开瑞芯微刷机工具 RKDevTool此时会看到设备处于 LOADER 模式,
点击 固件
,选择系统 .img
镜像路径
等待镜像加载成功,点击 升级

烧录完成后,此时会看到 发现一个 ADB 设备
字样。
此时进入 /sys/class/pwm/
路径,即可获得 pwmchip0
相关文件,并通过 echo
指令查看或设置 PWM 参数。
总结
本文介绍了幸狐Omni3576边缘计算套件实现 GPIO 输出电平的控制及 PWM 输出即呼吸灯效果的项目设计流程,包括方案介绍、引脚设备开启、Python语言控制、C 程序控制方案,为相关外设的开发和联合调用提供了参考。