NanoPi-DUOを使ってみる

GPIOライブラリ

NanoPi-DUOで使えるWiringPiライブラリがこちらで公開されています。
readallコマンドで確認するとピンマップは以下の様に表示されます。


片っ端からLチカを試してみましたが、赤字のピンは正しく動きません。
ソースを見てみましたがオンボードのピン番号は1〜73の範囲となっていて、これを超えるピン番号は仮想ピン番号として扱われています。
仮想ピン番号とは例えばsr595SetupでPinBaseを74と指定すると、ピン番号74はsr595の0 番ピンとして扱われます。
オンボードのピン番号の範囲を0〜203に変更すれば動くようになりますが、仮想ピン番号のPinBaseを204以上にする必要が有ります。
BCM
wPi
Phys
Phys
wPi
BCM


1
2




3
4




5
6




7
8




9
10


198
8
11
12


199
9
13
14


15
7
15
16


16
0
17
18


14
2
19
20

13
3
21
22
16
203
12
12
23
24
18

11
13
25
26




27
28




29
30




31
32




私のお気に入りのpython-peripheryライブラリを使うことで、全てのピンを使うことができます。
インストールは以下の手順です。
$ sudo apt install python3-pip python3-setuptools
$ python3 -m pip install python-periphery

ピン番号の指定はこちらのGPIO Pin Descriptionの番号なので分かりやすいです。
GPIO番号 物理ピン GPIO番号

1
2


3
4


5
6


7
8


9
10

198
11
12

199
13
14

15
15
16

16
17
18

14
19
20

13
21 22
203
12
23 24
363
11
25 26


27 28


29 30


31
32

以下のコードで動作を確認することができます。
#!/usr/bin/python
#-*- encoding: utf-8 -*-
from periphery import GPIO
import time
import signal
import sys

argv = sys.argv
argc = len(argv)
#print argc
#print argv
if (argc == 1):
  print 'Usage: python %s gpio#' % argv[0]
  quit()

pin = int(argv[1])
gpio_out = GPIO(pin, "out")


for i in range(5):
  gpio_out.write(False)
  time.sleep(1.0)
  gpio_out.write(True)
  time.sleep(1.0)


gpio_out.write(False)
gpio_out.close()



NanoPi-DUOに対応したOPi.GPIOライブラリがこちらに公開されています。
最初はOrangePi-ZEROだけに対応していたのですが、いつの間にか様々なボードに対応していました。
インストールは以下の手順です。
$ sudo apt install python3-pip python3-setuptools
$ python3 -m pip install OPi.GPIO

RPi.GPIOは物理ピン番号(GPIO.BOARD)と、BCM番号(GPIO.BCM)でポートを指定することができますが、
このライブラリも物理ピン番号(nanopi.duo.BOARD)と、BCM番号 (nanopi.duo.BCM)でポートを指定することができます。
但し、物理ピン番号で指定する場合、実際のピンの位置ではなく、以下の番号で指定する必要が有ります。
BCM番号 物理ピン番号 物理ピン 物理ピン番号 BCM番号


1
2




3
4




5
6




7
8




9
10


14
8
11
12


15
10
13
14


10
19
15
16


9
21
17
18


11
23
19
20


8
24
21 22
7
4
2
3
23 24
12
18
3
5
25 26




27 28




29 30




31
32


以下のコードで物理ピン番号の動作を確認することができます。
HIGH/LOWの反転はものすごくスマートです。
ソースを見てみましたが、python-peripheryライブラリと同様に、直接デバイスファイルを操作しています。
ピン番号のアサインは、以下の例の様にOPi-ZEROの同じ機能の物理ピン番号を引き継いでいる様ですが、ちょっとわかりにくいです。
(例)
UART1_TX:8
UART1_RX:10
SPI1_MOS:19
SPI1_MISO:21
SPI1_CLK:23
SPI1_CS:24
#!/bin/python
#-*- encoding: utf-8 -*-
import nanopi.duo
from OPi import GPIO

import time
import signal
import sys

argv = sys.argv
argc = len(argv)
#print argc
#print argv
if (argc == 1):
  print 'Usage: python %s phys#' % argv[0]
  quit()

pin = int(argv[1])
GPIO.setmode(nanopi.duo.BOARD)
GPIO.setup(pin, GPIO.OUT)

for i in range(10):
  GPIO.output(pin, not GPIO.input(pin))
  time.sleep(1.0)

GPIO.output(pin, GPIO.LOW)
GPIO.cleanup()

以下のコードでBCM番号の動作を確認することができます。
ピン番号のアサインは、物理ピン番号と同様に、OPi-ZEROの同じ機能のBCM番号を引き継いでいる様ですが、ちょっとわかりにくいです。
OPi-ZERO用のアプリは全く変更することなく動きます。
(例)
UART1_TX:14
UART1_RX:15
SPI1_MOS:10
SPI1_MISO:9
SPI1_CLK:11
SPI1_CS:8
#!/bin/python
#-*- encoding: utf-8 -*-
import nanopi.duo
from OPi import GPIO

import time
import signal
import sys

argv = sys.argv
argc = len(argv)
#print argc
#print argv
if (argc == 1):
  print 'Usage: python %s BCM#' % argv[0]
  quit()

pin = int(argv[1])
GPIO.setmode(nanopi.duo.BCM)
GPIO.setup(pin, GPIO.OUT)

for i in range(10):
  GPIO.output(pin, not GPIO.input(pin))
  time.sleep(1.0)

GPIO.output(pin, GPIO.LOW)
GPIO.cleanup()

このライブラリは入力割り込みに対応しています。
RPi.GPIOでは入力ピンのセットアップ時にプルアップ、プルダウンを指定することができますが、OPi.GPIOではできません。
RISING割り込みの時はプルダウン、FALLING割り込みの時はプルアップの外部抵抗を追加する必要が有ります。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import nanopi.duo
from OPi import GPIO
import time
GPIO.setmode(nanopi.duo.BCM)
GPIO.setup(14, GPIO.IN)
GPIO.setup(15, GPIO.IN)

def callback(channel):
    if (channel == 14):
       print "Rising edge detected. channel=",channel
    if (channel == 15):
       print "Falling edge detected. channel=",channel

#You need external pulldown register
GPIO.add_event_detect(14, GPIO.RISING, callback=callback)
#You need external pullup register
GPIO.add_event_detect(15, GPIO.FALLING, callback=callback)

try:
    print ("Press CTRL+C to exit")
    while True:
      time.sleep(0.1)

except KeyboardInterrupt:
    GPIO.cleanup()       # clean up GPIO on CTRL+C exit
    print ("Bye.")

続く....