OrangePi ZERO 2 外设应用程序开发之PWM输出


在这里插入图片描述

一、什么是 PWM?

PWM(Pulse Width Modulation)简称脉宽调制,根据相应载荷的变化来调制晶体管基极或 MOS 管栅极的偏置,来实现晶体管或 MOS 管导通时间的改变,从而实现开关稳压电源输出的改变。这种方式能使电源的输出电压在工作条件变化时保持恒定,是利用微处理器的数字信号对模拟电路进行控制的一种非常有效的技术。广泛应用在从测量、通信到功率控制与变换的许多领域中。

说白了,PWM 也是一连串的脉冲列,它是一种特殊的方波。我们平时理解的方波,也是一种高电平和低电平快速切换的波形,而且高电平和低电平持续的时间相等。而 PWM 的特点就是,它的方波的高电平部分可以调节,可以调节使其高电平的时间变长,也可以变短。当然,相应的低电平的时间也会随之被调节。想要理解并学会使用 PWM,就需要理解什么是 PWM 的周期频率占空比

1. PWM 的周期

如图所示,这是一个特殊的有规律的方波,其中由低电平跳变成高电平的过程,我们称为上升沿。每个上升沿之间的时间间隔都是固定某个值,我们用Cycle来表示,而这个Cycle就是脉冲的周期。

在这里插入图片描述

2. PWM 的占空比

在上面的脉冲中,我们可以发现每次上升沿之后高电平都维持了一段时间,而且每次上升沿之后的高电平维持的时间也相同,这个高电平的时间就是脉冲宽度(Pulse Width),也叫脉宽时间。而所谓的占空比,是指一个脉冲周期内,脉冲宽度与周期时间的比例,单位是 %(0% - 100%)。例如,我们常见的方波,占空比就是 50%。

再比方说,一串脉冲列的周期的时间是10 ms,脉宽时间是 8 ms,那么占空比是 8 / 10 = 80%,我们就可以称其占空比为80%的脉冲信号。

在这里插入图片描述

3. PWM 的频率

一般提到频率,都会联想到周期,因为这俩概念的关系互为倒数。PWM 的频率也是如此,PWM 的频率是指在1秒钟内,信号从高电平到低电平再回到高电平的次数,也就是说一秒钟 PWM 共有多少个周期,单位 Hz。

4. PWM 有什么用?

4-1. 呼吸灯

一般人的眼睛对于 80 Hz以上刷新频率则完全没有闪烁感,那么我们平时见到的 LED 灯,当它的频率大于 50 Hz 的时候,人眼就会产生视觉暂留效果,基本就看不到闪烁了,而是误以为是一个常亮的LED灯。由于频率很高时看不到闪烁,占空比越大 LED 越亮,占空比越小 LED 越暗。所以,在频率一定时,可以用不同占空比改变 LED 灯的亮度,使其达到一个呼吸灯的效果。

4-2. 电机转速控制

PWM 也能对电机转速的进行控制,通过调节占空比可以实现不同电压的输出,实现对电机转速的调节。

对于直流电机来讲,电机输出端引脚是高电平电机就可以转动,当输出端高电平时,电机会转动,但是是一点一点的提速,在高电平突然转向低电平时,电机由于电感有防止电流突变的作用是不会停止的,会保持这原有的转速,以此往复,电机的转速就是周期内输出的平均电压值,所以实质上我们调速是将电机处于一种,似停非停,似全速转动又非全速转动的状态,那么在一个周期的平均速度就是我们占空比调出来的速度了。在电机控制中,电压越大,电机转速越快,而通过 PWM 输出不同的模拟电压,便可以使电机达到不同的输出转速。

当然,在电机控制中,不同的电机都有其适应的频率 频率太低会导致运动不稳定,如果频率刚好在人耳听觉范围,有时还会听到呼啸声。频率太高时,电机可能反应不过来,正常的电机频率在 6 - 16 kHz 之间为好。

4-3. 舵机控制

舵机的控制就是通过一个固定的频率,给其不同的占空比来控制舵机不同的转角。舵机的频率一般为频率为 50 Hz,也就是一个 20 ms 左右的时基脉冲,而脉冲的高电平部分一般为 0.5 ms - 2.5 ms 范围,来控制舵机不同的转角。

500 - 2500 μs 的 PWM 高电平部分对应控制 180 度舵机的 0 - 180 度。

二、OrangePi ZERO 2 的 PWM 测试方法

现在大部分开发板都会自带 PWM 输出的功能,即使没有 PWM 的功能,我们也可以通过用代码的方式模拟输出 PWM。比如,89C51 单片机就没办法直接通过调用 API 来输出 PWM,但是可以通过定时器配合中断的方式来实现模拟输出 PWM。

当然了,我们的 OrangePi ZERO 2 本身有 PWM 通道,最多可以使用 4 通道 PWM,它们所在引脚的位置如下图所示:

在这里插入图片描述

仔细观察就会发现,这些 PWM 通道都是原串口的发送引脚和接收引脚。也就是说,PWM 1、PWM 2 和 26 Pin 接口中 UART 5 的 RX、TX 引脚是复用的,所以使用 PWM 1 和 PWM 2 前需要先在dts中将 UART 5 的配置关掉。而 PWM 3、PWM 4 和调试串口中的 TX、RX 引脚是复用的,所以使用 PWM 3 和 PWM 4 前需要在dts中先将 UART 0 的配置关掉。需要注意的是,UART 0 的配置被关闭后,此时调试串口就无法使用了。

进行 PWM 测试时,还需要主要 Linux 系统内核版本,目前香橙派能下载到的 Ubuntu 系统的内核版本分别有 4.95.166.1 三个版本,我这里用的是 5.16 的内核版本,和 6.1 版本一样的测试方法。而刷了 4.9 内核版本的系统的小伙伴,没办法使用这个测试方法,可以自行下载官方的用户手册,按照官方文档进行测试。

1. PWM 1 和 PWM 2 测试方法

首先需要打开/boot/orangepiEnv.txt进行配置,在命令行中输入:

sudo vim /boot/orangepiEnv.txt

输入下列的配置信息:

overlays=pwm12

如下图所示,如此即是配置了 PWM 1 和 PWM 2 两个通道开启。

在这里插入图片描述

保存退出后,重启 OrangePi ZERO 2。

重启完成后,直接可以在终端输入命令的方式(写入节点),控制 PWM 1 和 2 两个通道输出 PWM。

由于使用 PWM 通道需要 root 权限,可以先输入命令su进入 root 用户界面。进入 root 需要输入 root 密码,这个密码和登录密码并不是同一个,香橙派默认的 root 密码是:orangepi

进入 root 后,可以分别输入下列命令测试 PWM。第一句是把 PWM 1 通道设置为输出端口,第二句是设置周期为 20 ms,第三句是设置脉宽时间为 1 ms,第四句是开启 PWM 输出,即写入 1 为开启输出,写入 0 为关闭输出。

echo 1 > /sys/class/pwm/pwmchip0/export
echo 20000000 > /sys/class/pwm/pwmchip0/pwm1/period
echo 1000000 > /sys/class/pwm/pwmchip0/pwm1/duty_cycle
echo 1 > /sys/class/pwm/pwmchip0/pwm1/enable

通过示波器可以看到如下波形:

在这里插入图片描述

可以通过输入其他的脉宽数字来调整输出的脉宽,比如输入:

echo 1000000 > /sys/class/pwm/pwmchip0/pwm1/duty_cycle

这样我们就可以看脉宽的变化了。

在这里插入图片描述

输入下面的命令,就可以关闭 PWM 1 通道的 PWM 输出,会变为持续输出高电平。

echo 0 > /sys/class/pwm/pwmchip0/pwm1/enable

用同样的方法也可以测试 PWM 2 通道,只需把第一句命令中的 1 改成 2 即可,其他操作不变,这里就演示了,各位读者可以自行尝试。

2. PWM 3 和 PWM 4 测试方法

测试 PWM 3 和 PWM 4 的方法和前面的测试大同小异,同样需要打开/boot/orangepiEnv.txt 进行配置。输入下面的配置信息:

overlays=pwm34

当然,如果按上述配置信息进行修改,要把之前测试 PWM 通道 1 和通道 2 的配置先删除,因为overlays不能存在多个,如果需要设置overlays同时打开多个配置,可以这样修改:

overlays=pwm12 pwm34

也就是使用空格隔开写在一行即可,这样 PWM 四个通道就可以同时使用了,不过这样 UART 0 和UART 5 就无法使用了。

至于测试方法也都差不多,只是才选择通道时,写入/sys/class/pwm/pwmchip0/export节点的值要注意一下,写入 1、2、3、4 分别对用四个通道。具体的测试在此不做赘述。

三、基于 wiringOP 库的软件 PWM

1. softPwm 库及其函数

虽然 OrangePi ZERO 2 上有四个 PWM 输出通道,但是都不是 PWM 硬件触发的,而是靠软件模拟的 PWM 输出。因此我们如果需要用到 PWM 输出的话,也是使用软件模拟的方式来实现 PWM 输出。刚好 wiringOP 库就正好为我们提供了相应的库以及库函数:

#include <softPwm.h>

int softPwmCreate (int pin, int initialValue, int pwmRange)
void softPwmWrite (int pin, int value)

具体说明如下:

通用GPIO控制函数原型函数参数函数说明
int softPwmCreate (int pin, int initialValue, int pwmRange)pin:用来作为软件PWM输出的引脚。
initalValue:引脚输出的初始值。
pwmRange:PWM 值的范围上限,建议使用100。
返回值:0 表示成功。
使用一个指定的 pin 引脚创建一个模拟的 PWM 输出引脚。
void softPwmWrite (int pin, int value)pin:通过 softPwmCreate 创建的引脚。
value:PWM 引脚输出的值。
更新引脚输出的 PWM 值。

需要注意的是,编译时需要添 pthread 库链接,就是在编译的时候带上 -lpthread

2. 软件 PWM 测试

对于上述函数该如何使用,我们先通过一个测试例子来实现软件 PWM 输出。具体代码如下:

/* pwm_test.c */

#include <stdio.h>
#include <stdlib.h>
#include <wiringPi.h>
#include <softPwm.h>

#define PWM_PIN 2        //设置输出引脚的 wiP 序号为 2,即 7 号引脚。

int main(void)
{
    if (wiringPiSetup() == -1)
        exit(1);

        softPwmCreate(PWM_PIN, 0, 100);        //把需要输出 PWM 信号的引脚初始化,初始值为 0,周期为 100。

        softPwmWrite(PWM_PIN, 10);        //设置输出的 PWM 的脉宽为 10。

    while (1);        //保持 PWM 输出。

    return 0;
}

程序中有许多参数的单位是不明确的,先暂时不管,直接编译时运行程序,通过示波器可以看到如下现象:

在这里插入图片描述

我们把上面的代码做一些简单的修改,初始化周期改为 200。

#include <stdio.h>
#include <stdlib.h>
#include <wiringPi.h>
#include <softPwm.h>

#define PWM_PIN 2

int main(void)
{
    if (wiringPiSetup() == -1)
        exit(1);

        softPwmCreate(PWM_PIN, 0, 200);

        softPwmWrite(PWM_PIN, 10);  

    while (1);

    return 0;
}

在看一下示波器的波形,可以看到周期约为 20 ms,可见softPwmCreate函数的第三个参数的值,要除以 10 才是真实的周期,单位为 ms。同理,softPwmWrite函数的第二个参数也是一样的。

在这里插入图片描述

3. 实现呼吸灯

呼吸灯的效果其实是通过调节电压的方式实现的,从暗到亮的过程就是经过灯的电压在慢慢地增加,相反的,灯的亮度从亮到暗就是电压在慢慢地减少。而 PWM 就是我们常用地电压调整方案,不同脉宽的 PWM 波形,可以近似的看成一种连接输出的不同的电压值,具体如下图所示:

在这里插入图片描述

其实可以看出,PWM 信号的电压值,跟占空比有关,以高电平为5V为例,占空比为 75% 的 PWM 信号相当于 5V × 0.75 = 3.75V。由此可见,调节输出电压,其实就等同于调节脉冲宽度。

当然了,如果要实现呼吸灯还需要注意 PWM 的频率,前面提到 LED 灯的频率大于 50 Hz 的时候,人眼就会产生视觉暂留效果,基本就看不到闪烁了。所以我们可以把频率设置为 50 Hz ,也就是 PWM 的周期为 20 ms。而呼吸灯的 PWM 波形变化,可以先慢慢增加脉冲宽度,当达到脉宽最大值时,在慢慢减少脉冲宽度,到了最小值时,再循环重复上述步骤,类似的波形图如下(橙色虚线表示近似电压值):

在这里插入图片描述

如果要在 OrangePi ZERO 2 实现这个输出波形的变化过程,其实就是不断地用softPwmWrite函数修改脉宽,具体代码实现如下:

/* breathing_light.c */

#include <stdio.h>
#include <stdlib.h>
#include <wiringPi.h>
#include <softPwm.h>

#define PWM_PIN       2        //PWM 信号输出引脚的 wiP 序号
#define PWM_CYCLE     200      //设置为 20 ms
#define PWM_DUTY_MAX  190      //最大脉宽为 19 ms
#define PWM_DUTY_MIN  10       //最小脉宽为 1 ms

int main(void)
{
    if (wiringPiSetup() == -1)
        exit(1);

    softPwmCreate(PWM_PIN, PWM_DUTY_MAX, PWM_CYCLE);

    int val = PWM_DUTY_MAX;        //脉宽变量
    int mark = 0;        //脉宽增量标记

    while (1) {
         if (mark == 0)
                 val--;
         else
                 val++;

         if (val <= PWM_DUTY_MIN)
                 mark = 1;
         else if (val >= PWM_DUTY_MAX)
                 mark = 0;

         softPwmWrite(PWM_PIN, val);
         delay(10);
    }

    return 0;
}

示波器和实际效果如下视频:

呼吸灯示例

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
编译 Linux 内核需要以下步骤: 1. 获取 Linux 内核源代码。你可以从官方网站或 GitHub 上下载最新的内核源代码。 2. 安装交叉编译工具链。如果你的开发环境是 x86 架构的,你需要安装交叉编译工具链来编译适用于 ARM 架构的内核。你可以使用 apt-get 命令或其他包管理器来安装工具链。例如,在 Ubuntu 或 Debian 上,你可以使用以下命令来安装: ``` sudo apt-get install gcc-arm-linux-gnueabihf ``` 3. 配置内核。进入内核源代码目录,使用以下命令来配置内核: ``` make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- orangepi_zero2_defconfig ``` 这将使用默认配置文件来配置内核。 4. 编译内核。使用以下命令来编译内核: ``` make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage dtbs modules ``` 这将编译内核镜像、设备树和内核模块。 5. 安装内核。将编译好的内核镜像和设备树文件复制到 SD 卡的 boot 分区中。例如,在 Ubuntu 或 Debian 上,你可以使用以下命令来安装: ``` sudo cp arch/arm/boot/zImage /media/boot/ sudo cp arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero2.dtb /media/boot/ ``` 6. 配置引导加载程序。编辑 SD 卡的 boot 分区中的 boot.cmd 文件,并添加以下内容: ``` setenv bootargs console=ttyS0,115200 root=/dev/mmcblk0p2 rootwait panic=10 fatload mmc 0:1 ${kernel_addr_r} zImage fatload mmc 0:1 ${fdt_addr_r} sun8i-h2-plus-orangepi-zero2.dtb bootz ${kernel_addr_r} - ${fdt_addr_r} ``` 这将配置引导加载程序以加载内核镜像和设备树,并指定内核参数。 7. 生成引导加载程序镜像。使用以下命令来生成引导加载程序镜像: ``` mkimage -C none -A arm -T script -d boot.cmd boot.scr ``` 这将生成一个名为 boot.scr 的文件,它是引导加载程序镜像。 8. 将引导加载程序镜像复制到 SD 卡的 boot 分区中: ``` sudo cp boot.scr /media/boot/ ``` 9. 将 SD 卡插入 Orange Pi Zero 2 开发板,并启动板子。如果一切正常,你应该看到内核启动信息在串口终端中输出。 注意:这只是一个简单的指南,实际的操作可能会因环境和设备而有所不同。请确保你熟悉 Linux 内核编译和 Orange Pi Zero 2 开发板的使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Grayson_Zheng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值