跳转至

06 PWM输出和舵机控制

PWM说明

树莓派的硬件引脚PWM有4个引脚。GPIO.1、GPIO.26、GPIO.23、GPIO.24,对应到WiringPi就是1、26、23、24。bcm的引脚编号18、12、13、19,我们的扩展板上面引出了4个引脚,板子上注释的是BCM编号。

硬件PWM,bcm的引脚编号18、12、13、19,我写代码测试的时候,发现18、12会同时输出,13、19会同时输出。而且如果你初始化了18,即使没有初始化12,他也能控制12的输出。

软件PWM没有上述问题。

我们可以用PWM信号,来控制舵机,模拟智能家居中的门窗开关。

image-20240817201702470

代码

wiringPi 可以使用硬件PWM,硬件PWM的话,就是那几个脚可以输出,软件PWM输出的话,每个引脚都可以。

硬件Pwm

树莓派内部pwm发生器的基频为19.2MHz,输出频率 freq(Hz) = 19200000 / divisor / range

1、void pwmSetMode (int mode) ;

mode:PWM运行模式

pwm发生器可以运行在2种模式下,通过参数指定:

  • PWM_MODE_BAL :树莓派默认的PWM模式

  • PWM_MODE_MS :传统的pwm模式

我使用PWM_MODE_BAL怎么调都不对,就改成PWM_MODE_MS来使用了。

2、void pwmSetRange (unsigned int range) ;

range,范围的最大值 0~range,设置pwm发生器的数值范围,默认是1024

3、void pwmSetClock (int divisor)

设置时钟分频

4、void pwmWrite(int pin, int value) ;

设置占空比

下面是一个设置PWM输出的例子

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

#define PWM 18

int main(int argc,char **argv)
{   
    if(wiringPiSetupGpio() < 0) //当使用这个函数初始化树莓派引脚时,程序使用的是BCM引脚编号表。
        return 1;

    pinMode(PWM,PWM_OUTPUT); //设置引脚为PWM输出模式
    pwmSetMode (PWM_MODE_MS);
    pwmSetRange(1024);              // pwm脉宽范围 0~1024
    pwmSetClock(75);                // 250Hz,19.2MHz / 75 / 1024 = 250Hz
    pwmWrite(PWM,512);              // 设置高电平占的计数值

    while (1)
    {

    }
    return 0;
}

然后编译这段代码

cc -Wall -o main main.c -lwiringPi

-Wall 表示编译时显示所有警告,-lwiringPi 表示编译时动态加载 wiringPi 库

编译完成后调用生成的main文件

sudo ./main

想要停止这个程序,Ctrl+c即可。

软件pwm

除了硬件PWM,该库还支持软件PWM的输出

1、int softPwmCreate (int pin, int initialValue, int pwmRange)

pin:用来作为软件PWM输出的引脚

initalValue:引脚输出的初始值

pwmRange:PWM值的范围上限

返回:0表示成功。

2、void softPwmWrite (int pin, int value)

pin:通过softPwmCreate创建的引脚

value:PWM引脚输出的值

具体实现如下,频率设置为PWMfreq = 1 x 10^6 / (100 x range)

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

#include <softPwm.h>

#define PWM 18

int main(int argc,char **argv)
{   
    if(wiringPiSetup() < 0) //当使用这个函数初始化树莓派引脚时,程序使用的是wiringPi 引脚编号表。
        return 1;

    pinMode(PWM,OUTPUT); //设置引脚为 输出模式
    //PWMfreq = 1 x 10^6 / (100 x range)  需要50hz 
    softPwmCreate(PWM , 0, 200);// 设置周期分为200份
    softPwmWrite(PWM , 50); //占空比就是50/200

    while (1)
    {

    }
    return 0;
}