Raspberry Pi, Orange Pi GPIO制御

RaspbianにはWiringpiというGPIO制御の専用ライブラリがリリースされていますが、/sys/class/gpioにGPIOを操作するプラットフォームが予め用意されているため、これを操作することでもGPIO制御ができます。

https://www.kernel.org/doc/Documentation/gpio/sysfs.txt

まず使用するGPIOピンを有効にします(12ピンの場合、物理的なピン番号ではありません)。

echo 12 > /sys/class/gpio/export

/sys/class/gpio/gpio12/ というフォルダが作成されます。

このフォルダ内の以下ファイル内容を指定することでGPIOの機能を指定します。

“direction” … 入力 “in” または出力 “out” を指定

sudo echo in > /sys/class/gpio/gpio12/direction

“value” … 出力として0 (low) または 1 (high)を指定。

sudo echo 1 > /sys/class/gpio/gpio12/value

“edge” … “none”, “rising”, “falling”, or “both”. エッジ波形の読取り

sudo echo rising > /sys/class/gpio/gpio12/edge

“active_low” … 読取り 0 (false) または 1 (true)のどちらかをアクティブに設定

sudo echo 0 > /sys/class/gpio/gpio12/active_low

GPIO制御を解除するには、

echo 12 > /sys/class/gpio/unexport

赤色LEDと緑色LEDの制御

起動時の設定(SDカードへのアクセス時、赤色LEDを点灯。パワーON時、緑色LED点灯)

/boot/config.txt

dtparam=act_led_trigger=mmc0
                 
dtparam=act_led_activelow=off
# red-led 35              
dtparam=act_led_gpio=35      
                            
dtparam=pwr_led_trigger=none
                             
dtparam=pwr_led_activelow=on
# green-led 47         
dtparam=pwr_led_gpio=47

各LEDのステータス確認・変更は、

# cat /sys/class/leds/led0/brightness
# echo 255 > /sys/class/leds/led0/brightness

# echo none > /sys/class/leds/led0/trigger
# cat /sys/class/leds/led0/trigger
[none] rc-feedback kbd-scrolllock kbd-numlock kbd-capslock kbd-kanalock kbd-shiftlock kbd-altgrlock kbd-ctrllock kbd-altlock kbd-shiftllock kbd-shiftrlock kbd-ctrlllock kbd-ctrlrlock timer oneshot heartbeat backlight gpio cpu cpu0 cpu1 cpu2 cpu3 default-on input panic actpwr mmc0

以下Orange Pi PC GPIOのピン配列です(WiringOPによる出力)。上記の方法でexportする場合は BCMの番号 を指定します。

 +-----+-----+----------+------+---+-Orange Pi+---+---+------+---------+-----+--+
 | BCM | wPi |   Name   | Mode | V | Physical | V | Mode | Name     | wPi | BCM |
 +-----+-----+----------+------+---+----++----+---+------+----------+-----+-----+
 |     |     |     3.3v |      |   |  1 || 2  |   |      | 5v       |     |     |
 |  12 |   8 |    SDA.0 | ALT5 | 0 |  3 || 4  |   |      | 5V       |     |     |
 |  11 |   9 |    SCL.0 | ALT5 | 0 |  5 || 6  |   |      | 0v       |     |     |
 |   6 |   7 |   GPIO.7 | ALT3 | 0 |  7 || 8  | 0 | ALT3 | TxD3     | 15  | 13  |
 |     |     |       0v |      |   |  9 || 10 | 0 | ALT3 | RxD3     | 16  | 14  |
 |   1 |   0 |     RxD2 | ALT3 | 0 | 11 || 12 | 0 | ALT3 | GPIO.1   | 1   | 110 |
 |   0 |   2 |     TxD2 | ALT3 | 1 | 13 || 14 |   |      | 0v       |     |     |
 |   3 |   3 |     CTS2 | ALT3 | 0 | 15 || 16 | 0 | ALT3 | GPIO.4   | 4   | 68  |
 |     |     |     3.3v |      |   | 17 || 18 | 0 | ALT3 | GPIO.5   | 5   | 71  |
 |  64 |  12 |     MOSI | ALT4 | 0 | 19 || 20 |   |      | 0v       |     |     |
 |  65 |  13 |     MISO | ALT4 | 0 | 21 || 22 | 0 | ALT3 | RTS2     | 6   | 2   |
 |  66 |  14 |     SCLK | ALT4 | 0 | 23 || 24 | 0 | ALT4 | CE0      | 10  | 67  |
 |     |     |       0v |      |   | 25 || 26 | 0 | ALT3 | GPIO.11  | 11  | 21  |
 |  19 |  30 |    SDA.1 | ALT4 | 0 | 27 || 28 | 0 | ALT4 | SCL.1    | 31  | 18  |
 |   7 |  21 |  GPIO.21 | ALT3 | 0 | 29 || 30 |   |      | 0v       |     |     |
 |   8 |  22 |  GPIO.22 | ALT3 | 0 | 31 || 32 | 0 | ALT3 | RTS1     | 26  | 200 |
 |   9 |  23 |  GPIO.23 |  OUT | 0 | 33 || 34 |   |      | 0v       |     |     |
 |  10 |  24 |  GPIO.24 |  OUT | 0 | 35 || 36 | 0 | ALT3 | CTS1     | 27  | 201 |
 |  20 |  25 |  GPIO.25 |  OUT | 0 | 37 || 38 | 0 | ALT3 | TxD1     | 28  | 198 |
 |     |     |       0v |      |   | 39 || 40 | 0 | ALT3 | RxD1     | 29  | 199 |
 +-----+-----+----------+------+---+----++----+---+------+----------+-----+-----+
 | BCM | wPi |   Name   | Mode | V | Physical | V | Mode | Name     | wPi | BCM |
 +-----+-----+----------+------+---+-Orange Pi+---+------+----------+-----+-----+

WiringPiに相当するWiringOPというライブラリもリリースされています。これをインストールすることでも同様のGPIO設定・制御ができます。

ピン配列の確認コマンド

gpio readall

GPIOの入出力設定:出力に設定する場合

gpio mode wPiの番号 output

出力の設定:1(High)または0(Low)

gpio write wPiの番号 1

Orange Pi PC参照ページ
http://linux-sunxi.org/Xunlong_Orange_Pi_PC

PAxx, PCxxなどをexportする場合のピン番号(BCM番号)は下記の計算ルールに則り算出されます。

http://linux-sunxi.org/GPIO

echo XX > /sys/class/gpio/export

(position of letter in alphabet - 1) * 32 + pin number

例) PH18 は ( 8 - 1) * 32 + 18 = 224 + 18 = 242 (Hがアルファベットの8番目).

ボード上のLEDピンは以下の通りです。GPIOピンとは繋がっていないため、これを制御するには配列ピン番号のルールに則った番号を指定します(/sys/class/leds/green_led, /sys/class/leds/red_led にアクセスすることでも制御できるようです)。

A red LED, connected to the PA15 pin.
A green LED, connected to the PL10 pin.

Ubuntu Bionic with Armbian Linux 4.19.62-sunxi では

  • /sys/class/leds/orangepi:green:pwr
  • /sys/class/leds/orangepi:red:status

に変更になりました。

点灯モードがON/OFFではなく、明るさのレベル指定となっています。

例)

# echo 255 > /sys/class/leds/orangepi:red:status/brightness

GPIOの設定確認

~$ cat /sys/kernel/debug/gpio

GPIOs 0-383, platform/sunxi-pinctrl, sunxi-pinctrl:
 gpio-6   (sysfs               ) in  hi
 gpio-7   (sysfs               ) in  lo
 gpio-9   (sysfs               ) out lo
 gpio-10  (sysfs               ) out lo
 gpio-15  (red_led             ) out lo
 gpio-16  (?                   ) out hi
 gpio-20  (sysfs               ) out lo
 gpio-354 (?                   ) out hi
 gpio-362 (green_led           ) out hi

Raspberry Piの場合には/sys/class/gpioへのリードライトアクセス権が、ユーザpiも属しているgpioというグループにも付与されています。このためgpio制御はpiユーザレベルでできるようになっているようです。

Armbianにも同様のアクセス権を付与するため、グループgpioを追加しsudoユーザを所属させます。

$ sudo su -

# addgroup gpio

# usermod -aG gpio ${SUDO_USER} <—グループsudoのユーザ /etc/groupを参照して追加

以下ファイルを新規に作成します。80-gpio-noroot.rulesの番号は任意です。

https://www.raspberrypi.org/forums/viewtopic.php?f=66&t=118879

$ sudo pico /etc/udev/rules.d/80-gpio-noroot.rules

# /etc/udev/rules.d/80-gpio-noroot.rules
# need to add group "gpio" for reading and writing access GPIO dir
#
#Group gpio chown
SUBSYSTEM=="gpio", PROGRAM="/bin/sh -c '/bin/chown -R root:gpio /sys/devices/platform/sunxi-pinctrl/gpio'"
#Group gpio chmod
SUBSYSTEM=="gpio", PROGRAM="/bin/sh -c '/bin/chmod -R ug+rw /sys/devices/platform/sunxi-pinctrl/gpio'"

#Group gpio chown
SUBSYSTEM=="gpio", PROGRAM="/bin/sh -c '/bin/chown -R root:gpio /sys/class/gpio'"
#Group gpio chmod
SUBSYSTEM=="gpio", PROGRAM="/bin/sh -c '/bin/chmod -R ug+rw /sys/class/gpio'"

設定をリロード、または再起動します。(再起動が望ましい)

$ sudo udevadm trigger --subsystem-match=gpio

pimatic-gpioプラグインのgpio.coffeeのコード修正。gpioの定義をonoffモジュールのみで定義します。

Gpio = env.Gpio or require(‘onoff’).Gpio
----->
Gpio = require(‘onoff’).Gpio

      # * pimatic imports.
      Promise = env.require 'bluebird'
      assert = env.require 'cassert'
      _ = env.require 'lodash'

      Gpio = require('onoff').Gpio  ここを修正
      Promise.promisifyAll(Gpio.prototype)

Orange Piの場合、WiringOPを使用するよりもBCMのピン番号を直接指定するsysfsによるGPIO制御法を選択した方が間違いがありません。WiringOPではOrange PiのBCM番号に対応していないようです。(該当するRaspberry PiのBCM番号を指定しなければならないようです)

sysfsによるGPIO制御サンプルコード(Python, Node.js)を以下に列挙します。

ユーザレベルで /sys/class/gpio ファイルに書込みを行うには、上の投稿で紹介したgpioグループを追加しユーザを所属させて下さい。 sudo pico /etc/udev/rules.d/80-gpio-noroot.rules も作成する必要があります。

Pythonサンプルコード

スイッチONでLED点灯

#!/usr/bin/env python

import sys
import time
import os

if not os.getegid() == 0:
    sys.exit('Script must be run as root')

print ("Push Button LED ON")
print ("Press CTRL + C to exit")

#def pins_export():
        #try:
                #pin1export = open("/sys/class/gpio/export","w")
                #pin1export.write(str(63))
                #pin1export.close()
        #except IOError:
                #print "INFO: GPIO 63 already Exists, skipping export gpio"

def read_button():
        fp1 = open("/sys/class/gpio/gpio6/value","r")
        value = fp1.read()
        return int(value)
        fp1.close()

def write_led(value):
        fp2 =  open("/sys/class/gpio/gpio10/value","w")
        fp2.write(str(value))
        fp2.close()

#pins_export()
try:
    while True:
        button_value =  read_button()
        write_led(button_value)
        
except KeyboardInterrupt:
    print ("Goodbye.")

LED点灯制御

#!/usr/bin/env python

import sys
import time
import os

if not os.getegid() == 0:
    sys.exit('Script must be run as root')

print ("Blinking User LED")
print ("Enter CTRL+C to exit")

def ledon():
        value = open("/sys/class/leds/gpio20/value","w")
        value.write(str(1))
        value.close()

def ledoff():
        value = open("/sys/class/leds/gpio20/value","w")
        value.write(str(0))
        value.close()

while True:
        ledon()
        time.sleep(.5)
        ledoff()
        time.sleep(.5)

Node.jsサンプルコード npm onoffモジュールによる操作

"use strict";

var Gpio = require('../onoff').Gpio,
  led = new Gpio(10),
  button = new Gpio(6);

function exit() {
  //led.unexport();
  //button.unexport();
  process.exit();
}

button.watch(function (err, value) {
  if (err) {
    throw err;
  }

  led.writeSync(value);
});

process.on('SIGINT', exit);

ARMBIAN 5.73 stable Debian GNU/Linux 9 (stretch) 4.19.17-sunxi

ユーザレベルでのGPIO制御設定

gpioグループの追加、gpioグループへのユーザ登録、udev設定ファイルを作成します。

$ sudo addgroup gpio
$ sudo usermod -aG gpio <current_user>
$ sudo nano /etc/udev/rules.d/99-gpio.rules

内容は上記の80-gpio-noroot.rulesと異なります。
4.19.17-sunxi*ではgpio-sunxiモジュールが用意されていないため、/sys/devices/platform/sunxi-pinctrl/gpioの箇所は削除します。

$ echo XX > /sys/class/gpio/export

によってエクポートされたgpioXXフォルダはエイリアスでリンク先が指定されているだけなので、リンク先のアクセス権も変更する必要があります。

# /etc/udev/rules.d/99-gpio.rules
# need to add group "gpio" for reading and writing access GPIO dir
#
#Group gpio chown
SUBSYSTEM=="gpio", PROGRAM="/bin/sh -c '/bin/chown -R root:gpio /sys/class/gpio'"
#Group gpio chmod
SUBSYSTEM=="gpio", PROGRAM="/bin/sh -c '/bin/chmod -R ug+rw /sys/class/gpio'"
#Group chown
SUBSYSTEM=="gpio", PROGRAM="/bin/sh -c '/bin/chown -R root:gpio /sys/devices/platform/soc/1c20800.pinctrl/gpiochip0/gpio'"
#Group chmod
SUBSYSTEM=="gpio", PROGRAM="/bin/sh -c '/bin/chmod -R ug+rw /sys/devices/platform/soc/1c20800.pinctrl/gpiochip0/gpio'"

設定をリロードします。

sudo udevadm trigger --subsystem-match=gpio

または以下のルールを適用しても構いません。

$ sudo pico /etc/udev/rules.d/10-gpio.rules

SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c 'find -L /sys/class/gpio/ -maxdepth 2 -exec chown root:gpio {} \; -exec chmod 770 {} \; || true'"

Home Assistant GPIO Component for Orangepi

DockerコンテナとしてHassをインストールした場合、以下ディレクトリにコンポーネントとしてインストールされています。

/usr/src/homeassistant/homeassistant/components/orangepi_gpio

orangepi_gpioでは入力機能しか備わっていないため、rpi_gpioをベースに出力機能を追加したものが以下。

2021-04-12T15:00:00Z
opi_gpioアップデート

DockerコンテナからホストマシンのGPIO制御

https://stackoverflow.com/questions/30059784/docker-access-to-raspberry-pi-gpio-pins

I2Sを利用したスピーカとマイクロホンの接続

https://forums.raspberrypi.com/viewtopic.php?t=183617