Slide 1

Slide 1 text

PythonでRaspberry Piの GPIOを制御する 2019/11/13 平原貴⾳ Start Python Club #51

Slide 2

Slide 2 text

Motivation MMFS2019 : Mini MakerCon Tokyo 2019 ⽇本の名カームブメントの⾃⽴と持続可能性を議論する。

Slide 3

Slide 3 text

Motivation • できないことができるようにするのは喜びがあ る。しかし⾝の回りのものは「できることをや らないようにすむ」ようにしている。 • できるようになる喜びを味わえるように

Slide 4

Slide 4 text

Motivation • 「⾃分が得たものをほかの⼈に伝える」 • 「⾃分が学んでいる姿を⼈に⾒せる」

Slide 5

Slide 5 text

Agenda • GPIOとは • Input • スイッチON/OFF • Output • Lチカ • サーボモーター • サンプルプログラム • https://github.com/kioto/raspi_gpio_sample (この資料はRaspberry Pi 3B + Raspbian Stretchで動作確認)

Slide 6

Slide 6 text

GPIOとは • General-Purpose Input/Output • ⽇本語で⾔うと「汎⽤⼊出⼒」 • 汎⽤じゃないI/O • SPI • I2C • UART

Slide 7

Slide 7 text

Raspberry PiのI/O • GPIOは24系統 • UARTは1系統 • SPIは2系統 • GPIOとピン共⽤ • I2Cは1系統 • GPIOとピン共⽤ • ピン配置の確認 • https://pinout.xyz

Slide 8

Slide 8 text

デモのシステム構成 USB3 USB Analog Discovery 2 MacBook Pro Raspberry Pi 4 プローブ I/O ブレッドボード

Slide 9

Slide 9 text

Analog Discovery 2 • 「アナログ回路万能測定ツール」 • という名称で秋⽉電⼦で紹介されている • 千⽯電商、共⽴エレショップでも売ってる • オシロスコープ • アナログ波形を観測 • ロジックアナライザ • デジタル波形を観測 • 可変電圧DC電源 • etc…

Slide 10

Slide 10 text

Input • GPIOでデジタル⼊⼒ • タクトスイッチ • 押すとON • 離すとOFF

Slide 11

Slide 11 text

実体配線図 • こんな感じ

Slide 12

Slide 12 text

Fritzing • 回路図エディタ • 実体配線図も描ける • 昔は無料だったけど今は有料? • http://fritzing.org

Slide 13

Slide 13 text

SW⼊⼒検知プログラム 5 import RPi.GPIO as GPIO 6 import time 7 8 SWITCH_PORT = 23 9 10 GPIO.setmode(GPIO.BCM) # GPIO番号で指定 11 GPIO.setup(SWITCH_PORT, GPIO.IN, pull_up_down=GPIO.PUD_UP) 12 13 state = False 14 while True: 15 current_state = GPIO.input(SWITCH_PORT) 16 if current_state != state: 17 if current_state: 18 print('OFF') 19 else: 20 print('Pushed') 21 state = current_state 01_switch.py

Slide 14

Slide 14 text

01_switch.py • パッケージはRpi.GPIOを使⽤ • ⼊⼒はGPIO 23番を使⽤ • setMode()でピン番号の指定⽅法を設定 • setup() • ⼊⼒ピン設定 • プルアップ(HighでON)設定 • input()でピンの状態を取得 • whileループで監視

Slide 15

Slide 15 text

ターミナルマルチプレクサ • Raspbianにログインする時に使う便利なコマンド • 昔はscreenコマンド、今はtmux • 単⼀のウィンドウで複数のセッション • 制御端末からプロセスを切断できる • 通信が切れてもセッションは⽣きている • 使い⽅ • c:セッション追加 • d :デタッチ • tmux ls:セッション確認 • tmux a [-t セッション名]:アタッチ

Slide 16

Slide 16 text

Pythonプログラムの実⾏ • 必ずsudoで実⾏すること • rootでないとGPIOデバイスにアクセスできないから $ sudo python3 01_switch.py

Slide 17

Slide 17 text

SW⼊⼒検知プログラム • 割り込み制御のコード 13 def cb_switch(ch): 14 current_state = GPIO.input(ch) 15 if current_state: 16 print('OFF') 17 else: 18 print('Pushed') 19 20 21 GPIO.add_event_detect(SWITCH_PORT, GPIO.BOTH, callback=cb_switch) 22 23 time.sleep(10) # なにか処理をしているものとする 01_switch_inter.py

Slide 18

Slide 18 text

01_switch_inter.py • パッケージはRpi.GPIOを使⽤ • ⼊⼒はGPIO 23番を使⽤ • setMode()でピン番号の指定⽅法を設定 • setup()で⼊⼒ピンとプルアップ設定 • input()でピンの状態を取得 • add_event_detect() • ⽴ち上がりと⽴ち下がりを検出(BOTH) • 割り込み発⽣時に呼び出すコールバック関数設定

Slide 19

Slide 19 text

SW⼊⼒検知プログラム • GUIを使った例 02_switch_inter_gui.py

Slide 20

Slide 20 text

Output • GPIOでデジタル出⼒ • Lチカ • GPIOがONになると点灯 • GPIOがOFFになると消える

Slide 21

Slide 21 text

配線図

Slide 22

Slide 22 text

LED点灯プログラム 5 import RPi.GPIO as GPIO 6 import time 7 8 LED_PORT = 18 9 10 GPIO.setmode(GPIO.BCM) # GPIO番号で指定 11 GPIO.setup(LED_PORT, GPIO.OUT) 12 13 # LEDを5秒間点灯する 14 GPIO.output(LED_PORT, True) 15 time.sleep(5) 16 GPIO.output(LED_PORT, False) 17 18 GPIO.cleanup() 19 20 print('done') 02_led.py

Slide 23

Slide 23 text

02_led.py • パッケージはRpi.GPIOを使⽤する • setMode()でピン番号の指定⽅法を設定 • setup()で出⼒ピン設定 • output()でピンの状態を設定 • cleanup()ですべてのピンを開放

Slide 24

Slide 24 text

LEDの明るさを変えるには • 電圧を変える • 規格範囲内で電圧を変化させる • 電圧の制御回路が必要 • PWMを使⽤する • デジタル信号を周期的にON/OFFする • ソフトウェアで実現できる • ⾃分でsleepを呼び出して実装する • OSの割り込みを使う • Raspberry PiはハードウェアPWMを持っている

Slide 25

Slide 25 text

PWMとは • Pulse With Modulation(パルス幅変調) • パルス幅をデジタルで変える • PWMの変調⽅法は⾊々あるけど、Raspberry Pi では周波数とduty⽐の2つだけ

Slide 26

Slide 26 text

ソフトウェアPWMの例 9 PWM_FREQUENCY = 500 # Hz 10 11 GPIO.setmode(GPIO.BCM) # GPIO番号で指定 12 GPIO.setup(LED_PORT, GPIO.OUT) 13 14 # PWM 15 pwm = GPIO.PWM(LED_PORT, PWM_FREQUENCY) 16 pwm.start(0) 17 18 # LEDを2秒間点灯する 19 for duty in (5, 20, 50, 80, 100): 20 print(duty) 21 pwm.ChangeDutyCycle(float(duty)) 22 time.sleep(2) 23 24 GPIO.cleanup() 02_led_pwm.py

Slide 27

Slide 27 text

ソフトウェアPWMを使⽤した プログラム • パッケージはRpi.GPIOを使⽤する • setMode()でピン番号の指定⽅法を設定 • setup()で出⼒ピン設定 • PWM()でPWMオブジェクトを⽣成 • PWM.start()で初期duty⽐を設定 • PWM.ChangeDutyCycle ()でduty⽐を設定 • cleanup()ですべてのピンを開放

Slide 28

Slide 28 text

ソフトウェアPWMの波形 (Rpi.GPIO) • 100Hz Duty⽐5% • 測定値:98.5Hz, パルス幅572us (duty⽐ 5.72%)

Slide 29

Slide 29 text

ソフトウェアPWMの波形 (Rpi.GPIO) • 500Hz Duty⽐5% • 測定値:465Hz, パルス幅171us (duty⽐ 7.95%)

Slide 30

Slide 30 text

ハードウェアPWMの例 (WiringPi) 5 import wiringpi 7 LED_PORT = 18 # GPIO 18 8 PWM_RANGE = 1024 9 PWM_FREQUENCY = 500 # Hz 10 CLOCK_BASE = int(18750 / PWM_FREQUENCY) 13 wiringpi.wiringPiSetupGpio() 14 wiringpi.pinMode(LED_PORT, wiringpi.GPIO.PWM_OUTPUT) 15 wiringpi.pwmSetMode(wiringpi.GPIO.PWM_MODE_MS) 16 wiringpi.pwmSetRange(PWM_RANGE) 17 wiringpi.pwmSetClock(CLOCK_BASE) 18 19 # LEDを2秒間点灯する 20 for duty_cycle in (5, 20, 50, 80, 100): 22 wiringpi.pwmWrite(LED_PORT, int(PWM_RANGE * duty_cycle / 100)) 23 wiringpi.delay(2000) 25 26 wiringpi.pwmWrite(LED_PORT, 0) 02_led_wiringpi_hardware_pwm.py

Slide 31

Slide 31 text

ハードウェアPWMの波形 • 500Hz Duty⽐5% • 測定値499Hz, パルス幅99.89us(duty⽐ 4.98%)

Slide 32

Slide 32 text

ソフトウェアPWMの例 (WiringPi) 5 import wiringpi 6 7 LED_PORT = 18 8 PWM_RANGE = 100 9 11 wiringpi.wiringPiSetupGpio() 12 wiringpi.pinMode(LED_PORT, wiringpi.GPIO.PWM_OUTPUT) 13 wiringpi.softPwmCreate(LED_PORT, 0, PWM_RANGE) 14 15 # LEDを2秒間点灯する 16 for duty in (5, 20, 50, 80, 100): 17 print(duty) 18 wiringpi.softPwmWrite(LED_PORT, duty) 19 wiringpi.delay(2000) 20 22 wiringpi.softPwmStop(LED_PORT) 02_led_wiringpi_software_pwm.py

Slide 33

Slide 33 text

ソフトウェアPWMの波形 (WiringPi) • 100Hz Duty⽐ 5%(周波数は変更できない?) • 測定値:99.6Hz, パルス幅519us (duty⽐ 5.17%)

Slide 34

Slide 34 text

PWM性能⽐較 測定条件 (周波数, duty⽐) Rpi.GPIO Software PWM WiringPi Software PWM WiringPi Hardware PWM 100Hz, 5% 98.5Hz, 5.72% 99.6Hz, 5.17% 100Hz, 4.93% 500Hz, 5% 465.0Hz, 7.95% - 499Hz, 4.98% 1kHz, 5% 866.1Hz, 11.2% - 1.0kHz, 4.93% 2kHz, 5% 1.56kHz, 14.0% - 2.1kHz, 4.9% 5kHz, 5% 2.90kHz, 23.2% - 6.26kHz, 4.9% 9.3kHz, 5% 3.94kHz, 30.4% - 9.37kHz, 5.0% 9.4kHz, 5% 3.99kHz, 30.8% - (動作せず) • グレーの⽂字は誤差20%以上 • “-”は未サポート

Slide 35

Slide 35 text

Software PWM vs Hardware PWM ソフトウェアPWM ハードウェアPWM ソフトウェア割り込みで実装 ハードウェアで⽤意されたPWM GPIOのピン数だけ⽤意できる Raspberry Piでは2系統使える※ 周期が⻑いなら安定 周期が短いと不安定 ハードウェア性能の範囲で安定 ※ https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf

Slide 36

Slide 36 text

Rpi.GPIO vs WiringPi ⽐較項⽬ RPi.GPIO WiringPi 使⽤感 ○⼿軽に使える △設定が⾯倒 サンプルと資料 ○⽇本語情報多い ○サンプル多数 △⽇本語情報少ない ⼊⼒割り込み ○使⽤可 ×未サポート ソフトウェアPWM ○使⽤可 △100Hzのみ使⽤可 ハードウェアPWM ×未サポート ○使⽤可

Slide 37

Slide 37 text

PiGpioパッケージ • http://abyz.me.uk/rpi/pigpio/ • ⼊⼒割り込みが使える • ハードウェアPWMが使える • リモートGPIOが使える • sudoでの実⾏が不要 • ただし、 • 使う時はデーモンを⽴ち上げる必要がある • pipでインストールできない • ⽇本語のドキュメントが皆無 • からあげ(@karaage0703)さんが積極的に情報発信 されている • https://karaage.hatenadiary.jp/entry/2017/02/10/073000

Slide 38

Slide 38 text

PiGpioのインストールと設定 • Raspberry Piから • raspi-configでRemote GPIOを有効にする • 5Interfacing Options -> P8 Remote GPIO • 以下のコマンドを実⾏ • デーモンからGPIOにアクセスしている $ sudo apt-get update $ sudo apt-get install pigpio python-pigpio python3-pigpio # pigpiodを⾃動起動する $ sudo systemctl enable pigpiod

Slide 39

Slide 39 text

PiGpioでソフトウェアPWM 5 import time 6 import pigpio 7 8 LED_PORT = 18 9 PWM_FREQUENCY = 500 # Hz 10 RANGE = 100 11 13 pi = pigpio.pi() 14 pi.set_mode(LED_PORT, pigpio.OUTPUT) 15 pi.set_PWM_frequency(LED_PORT, PWM_FREQUENCY) 16 pi.set_PWM_range(LED_PORT, RANGE) 17 18 # LEDを2秒間点灯する 19 for duty in (5, 20, 50, 80, 100): 21 pi.set_PWM_dutycycle(LED_PORT, duty) 22 time.sleep(2) 23 24 # ピンをINPUTモードにしておかないと、LEDが点灯し続けてしまう 25 pi.set_mode(LED_PORT, pigpio.INPUT) 26 pi.stop() 02_led_pigpio_software_pwm.py

Slide 40

Slide 40 text

PiGpioでハードウェアPWM 5 import time 6 import pigpio 7 8 LED_PORT = 18 9 PWM_FREQUENCY = 500 # Hz 10 12 pi = pigpio.pi() 13 pi.set_mode(LED_PORT, pigpio.OUTPUT) 14 16 for duty in (5, 20, 50, 80, 100): 18 pi.hardware_PWM(LED_PORT, PWM_FREQUENCY, duty * 10000) 19 time.sleep(2) 20 22 pi.set_mode(LED_PORT, pigpio.INPUT) 23 pi.stop() 02_led_pigpio_hardware_pwm.py

Slide 41

Slide 41 text

PWM性能⽐較 測定条件 (周波数, duty⽐) Rpi.GPIO Software PWM WiringPi Hardware PWM PiGpio Software PWM PiGpio Hardware PWM 100Hz, 5% 98.5Hz, 5.72% 100Hz, 4.93% 100Hz, 5.00% 100Hz, 5.04% 500Hz, 5% 465Hz, 7.95% 499Hz, 4.98% 500Hz, 5.00% 501Hz, 4.93% 1.0kHz, 5% 866Hz, 11.2% 1.0kHz, 4.93% 1.0kHz, 4.97% 1.0kHz, 4.98% 2.0kHz, 5% - - 2.0kHz, 4.80% 2.0kHz, 5.00% 9.3kHz, 5% 3.94kHz, 30.4% 9.37kHz, 5.0% 8.02kHz, 5.0% - 9.4kHz, 5% 3.99kHz, 30.8% (動作せず) 8.00kHz, 3.65% - 100kHz, 5% - - - 100kHz, 4.92% 1MHz, 5% - - - (1MHz, 4.05%) • グレーの⽂字は誤差10%以上 • “-”は未測定 • 1MHz時のduty⽐測定はオシロの性能限界なので参考値

Slide 42

Slide 42 text

リモートGPIO • Raspberry Piとネットワークで接続されている マシンから、Raspberry PiのGPIOにアクセスす るプログラムが書ける • 引数でホスト名指定 • デーモン起動時に、アクセス可能なホストを制 限できる • デフォルトで制限なし

Slide 43

Slide 43 text

リモートGPIOの例 4 import sys 5 import time 6 import pigpio 7 8 LED_PORT = 18 9 HIGH = 1 10 LOW = 0 11 12 def main(hostname): 13 pi = pigpio.pi(hostname) 14 pi.set_mode(LED_PORT, pigpio.OUTPUT) 15 17 pi.write(LED_PORT, HIGH) 18 time.sleep(5) 19 pi.write(LED_PORT, LOW) 20 remote/02_led_on_off.py

Slide 44

Slide 44 text

DCモーター • プラモデルなどでよく使われる • 安価である • 電圧を変えると回転速度も変わる • ⾼速回転できる • 低速の回転速度の調整が難しい マブチモーター FA-130RA

Slide 45

Slide 45 text

DCモーターを電圧制御で動か す • マブチモーターFA-130 RAを使⽤する • Raspberry Piで直接電圧を制御できないので、 ここではAnalog Discovery 2の直流電源を使う • モーターの規格は以下の通り https://product.mabuchi-motor.co.jp/detail.html?id=9

Slide 46

Slide 46 text

DCモーターをPWM制御で動か す(動かさない) • Duty⽐を変えることにより、使⽤電⼒を変化さ せ、モーターの速度を制御する • 理論上、Duty⽐が50%だと使⽤電⼒も50%になるの で、回転速度もそれに伴う • モーターが必要とする電⼒が、ラズパイの GPIOで提供できる電流で⼗分とは思えないの で、今回は対象外とする • 普通、モータードライバ回路を⽤意する

Slide 47

Slide 47 text

サーボモーター • 回転⾓度を指定して、その位置まで回る • 普通、何周もぐるぐる回るものでない • でも、何周もぐるぐる回るものもある(SG90-HV) • 産業⽤ロボットの関節や、ラジコンのステアリ ングなどで使われる • PWMで制御する TowerPro SG90

Slide 48

Slide 48 text

サーボモーターを動かす • SG90を使⽤する • モーターの規格は以下の通り http://akizukidenshi.com/download/ds/towerpro/SG90_a.pdf Position "0" (1.45 ms pulse) is middle, "90" (~2.4 ms pulse) is all the way to the right, thele . "-90" (~ 0.5 ms pulse) is all the way left.

Slide 49

Slide 49 text

サーボモーターを動かす

Slide 50

Slide 50 text

サーボモーターを動かす 4 import time 5 import RPi.GPIO as GPIO 6 7 MOTOR_PORT = 19 8 WAIT_TIME = 1.0 9 10 # SG90 11 # 12 # Position "0" (1.45 ms pulse) is middle, 13 # "90" (~2.4 ms pulse) is all the way to the right, 14 # "-90" (~ 0.5 ms pulse) is all the way left. 15 16 PWM_FREQUENCY = 50 # Hz 17 PWM_CYCLE = 1/ PWM_FREQUENCY * 1000 # 20 ms 18 DUTY_MIDDLE = 1.45 / PWM_CYCLE * 100 # duty % 19 DUTY_PLUS_90 = 2.4 / PWM_CYCLE * 100 # duty % 20 DUTY_MINUS_90 = 0.5 / PWM_CYCLE * 100 # duty % 03_servo_software_pwm.py

Slide 51

Slide 51 text

サーボモーターを動かす 22 # Software PWM 23 GPIO.setmode(GPIO.BCM) 24 GPIO.setup(MOTOR_PORT, GPIO.OUT) 25 pwm = GPIO.PWM(MOTOR_PORT, PWM_FREQUENCY) 26 pwm.start(DUTY_MIDDLE) 27 time.sleep(WAIT_TIME) 28 29 for i in range(3): 30 for duty in [DUTY_MINUS_90, 31 DUTY_MIDDLE, 32 DUTY_PLUS_90, 33 DUTY_MIDDLE,]: 34 pwm.ChangeDutyCycle(duty) 35 time.sleep(WAIT_TIME) 03_servo_software_pwm.py

Slide 52

Slide 52 text

お前、誰よ • 平原貴⾳ @takaneh • 三浦半島のフリーランスプログラマ • ⾞載組み込み系とかdjangoでwebサービスとか • 元Start Python Club名古屋⽀部スタッフ • 鎌倉Maker Lab⽴ち上げました

Slide 53

Slide 53 text

• 鎌倉Tech Meetup #1 • 2019/12/7 (Sat) 9:00-12:00 • 鎌倉商⼯会議所101会議室(JR鎌倉駅徒歩5分) • 初⼼者歓迎 • 興味のある⼈なら誰でも参加できます • 途中参加、途中退場OK • 鎌倉観光のついでにどうぞ • connpassで公開中 • https://kamakurapython.connpass.com/event/154096/