树莓派GPIO和PWM控制教程

1. 目的

在汽车电子开发中,CAN通讯是很难避开的一个技术点,当前CAN已经形成了行业内较为稳定的开发及相关测试验证方法,其中一种较为主流的就是使用CANoe和开发相应的CAPL脚本配合测试。然而,这套方案下来无论人力财力都是价格不菲,而且面对日异月新的技术发展也显得较为保守。所以笔者尝试使用树莓派配合MCP2515模块,进行低成本的CAN网络节点搭建和报文模拟,试图拓宽一下视野和思路。

本文针对普通外设和通讯外设,分别使用了Python 和 C进行编写控制,可以作为案例以便参考。

2. 材料准备

  • 树莓派 zero w
  • MCP2515模块
  • 2路继电器模块
  • linux 使用基础

first

3. 初始设置

树莓派安装最新的官方程序,安装好之后将ssh,gpio,spi等设置统统设为开启。

然后将树莓派连接到局域网wifi,进行ssh登录管理(此处也可使用usb网卡模式进行ssh连接,好处是免除连接屏幕进行系统初始设置)。

ssh连接成功后将树莓派换成国内的源(笔者使用的阿里的源),进行 sudo apt-get updatesudo apt-get upgrade更新。


002

我们使用树莓派,需要进行GPIO设置和spi通讯,控制这两部分可以使用官方推荐的WringPi库,在官方系统中是默认安装的。经过如上操作后会将库更新至最新,使用gipo -v进行版本查看,使用gpio readall进行所有引脚定义查看。

003

除了WringPi库之外,树莓派还能够使用python进行GPIO的控制操作,导入RPi.GPIO模块即可。

4. GPIO 控制继电器

继电器模块采用[带光耦保护 2路 继电器模块],淘宝可以直接买到,该继电器模块是5v供电,需要两路输出IO进行低有效的控制,根据硬件特性选取树莓派如下引脚,与继电器模块进行连接。
005

4.1. 使用Python 的RPi.GPIO模块进行控制

针对继电器,可以使用python的RPi.GPIO模块进行控制,默认系统中会安装此模块,如果没有可以使用如下命令sudo pip3 install RPi.GPIO进行安装。

根据模块物理特性,需要设置38,40两个引脚为低电平输出,设置37脚为PWM模式,使用如下代码进行设置。

import RPi.GPIO as GPIO

# Use BCM chip number as handle
GPIO.setmode(GPIO.BCM)

# Set useful channel
RELAY_1 = 20
RELAY_2 = 21
PWM_1   = 26

# Collect chip channel as setting list
output_list = [RELAY_1,RELAY_2,PWM_1]

# Set GPIO and PWM peripheral
GPIO.setup(output_list, GPIO.OUT, initial=GPIO.HIGH)
init_freq = 50  # initial frequency in Hz
pwm_pin37 = GPIO.PWM(PWM_1, init_freq)

# Set gpio as low output ,if high output then use GPIO.HIGH
GPIO.output(RELAY_1,GPIO.LOW)

# Start pwm ,initial duty cycle in 0.0 ,100.0
init_dc = 50  
pwm_pin37.start(init_dc)

# Change frequency and duty cycle
para_freq = 60
para_duty = 20
pwm_pin37.ChangeFrequency(para_freq)
pwm_pin37.ChangeDutyCycle(para_duty)

# Stop PWM out
pwm_pin37.stop()

# Release system resource and close gpio control
GPIO.cleanup()

其中 PWM引脚输出电平最高为3.3V,输出波形较为工整,但是与设定的误差较大,当设定载频为1K时,实际测试为850Hz,设定载频为3K,实际输出2K,设定10K,实际输出3.6K。所以在使用PWM功能时需要实际测试输出的载频,在进行设定。

如下为载频设定为10K,实际输出3.6K的波形。
006

4.2. 使用WringPi库函数进行控制

WringPi库为C语言,需要进行编译后运行,与RPi的区别就是WringPi支持spi和iic通讯控制,后续进行CAN网络节点模拟也只能使用WringPi进行编写。如下为基本的设置函数示例,具体需要查看官方文档进行相应的函数调用及开发。

/*-----------------------------------------------------------------------------
 Function   : Used for testing RaspberryPi ZeroW's gpio pin -> Relay 
 FileName   : TestRelay.c
 Author     : Tomato
 Time       : 2019.2.4
 Version    : 0.1
 Notes      : None
-----------------------------------------------------------------------------*/
#include <wiringPi.h>
#include <softPwm.h>

/* Macro config define */
#define RELAY_1   20U
#define RELAY_2   21U
#define PWM_1     26U

/* Parameter define */
static int high_edge_time = 0;   // uint :0.1ms
static int cycle_time     = 200; // uint :0.1ms

int main (void)
{
    /* Initial gpio with chip pin ,if use mapping pin -> wiringPiSetup*/
    wiringPiSetupGpio () ;
    /* Set relay1&2 pwm pin as output */
    pinMode (RELAY_1, OUTPUT) ;  /* INPUT
                                    OUTPUT
                                    PWM_OUTPUT
                                    GPIO_CLOCK
                                    SOFT_PWM_OUTPUT
                                    SOFT_TONE_OUTPUT
                                    PWM_TONE_OUTPUT */
    pinMode (RELAY_2, OUTPUT) ;
    pinMode (PWM_1, SOFT_PWM_OUTPUT) ;
    softPwmCreate(PWM_1,high_edge_time,cycle_time);

    /* Main loop function */
    for (;;)
    {
        /* Control relay */
        digitalWrite (RELAY_1, HIGH) ; 
        delay (500) ;
        digitalWrite (RELAY_1,  LOW) ; 
        delay (500) ;

        /* Control pwm */
        softPwmWrite(PWM_1, 20); // duty = 20/cycle_time
        delay (5000);
        softPwmWrite(PWM_1, 50);
        delay (5000);
        softPwmWrite(PWM_1, 90);
        delay (5000);
    }
    return 0 ;
}

编写好如上函数后,进行编译和链接,链接的时候需要使用 -lwringPi 这个指令,进行相应库函数的链接。如需要编译PWM引脚控制部分,则需要增加 -lpthread 链接指令。

gcc -o TestRelay TestRelay.c -lwiringPi -lpthread

编译成功后,使用sudo ./TestRelay命令直接运行我们编译指定的程序标识名TestRelay,实际可以看到继电器的切合,以及PWM输出。
008

如程序中设定,测试实际输出如下图所示,使用PWM控制有如下限制,
- PWM设定的程序跑在10ms的线程任务下,所以每s最多更改100次,
- 每操控一个GPIO引脚,CPU负载率会上升 0.5%左右,要根据当前树莓派的负载率进行合理设置,以保证有足够的资源进行外部通讯连接。
009

需要注意的是 PWM控制中,使用RPi 和WringPi所输入的参数的角度不同,如需要切换使用则要参考如上两个源码示例,进行测试。

5. 小结

至此已经能够正常操纵树莓派的GPIO和PWM接口了,后续我会讲CAN通讯的设计和使用。