【RaspberryPi】GPIOとPWM

#概要
自走式カメラを作成したく、関連する情報を覚え書き。
本記事ではモータードライバ用のGPIO制御、PWM制御について記載。
精度の高いハードウェアPWMはカメラのチルトに使いたいので温存し、
ざっくり制御で十分なモータの回転数制御はソフトウェアPWMを使用。

#実行環境
MCU：Raspberry Pi Zero W
OS：Raspberry Pi OS(buster)
モータドライバ：TA7291P
駆動用モータ：FA-130(楽しい工作シリーズ（ユニット） No.168　ダブルギヤボックス・左右独立４速タイプ)

#絶対規格を満たしているか確認
ありあわせの部品で作ったらNGがちらほら・・・
動いているのでとりあえず良しとする。

| 規格 | 確認項目 | ディレーティング |
| :-: | :-: | :-: |
| モータドライバ：出力電流Ave.＝Max 1.0A | モータ定格負荷電流＝Max 0.85A | 85% |
| 入力端子の電圧＝Min 3.5V | ラズパイのGPIO電圧＝Typ 3.3V | 106% |
| 入力端子の電流＝Max 0.01mA | ラズパイのGPIO出力電流<br>→おそらく余裕でOKなので未確認 | - |
| PWM端子の電流＝Max 0.04mA | ラズパイのGPIO出力電流<br>→おそらく余裕でOKなので未確認 | - |
| トランジスタリーク電流＝Max 0.05ｍA | モータの無負荷電流＝Typ 200mA | 0.025% |


#TA7291Pの使用方法
メーカーHP
https://toshiba.semicon-storage.com/jp/semiconductor/product/motor-driver-ics/brushed-dc-motor-driver-ics/detail.TA7291P.html

※データシート抜粋
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321914/e4afb33b-29d1-0d8f-1f61-cf5416a89988.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321914/de152b2c-21c1-6a78-ac21-fce0c1adf6cb.png)
ピンアサインが読みにくいので整理（切り欠きがある方が1ピン）

| ピン番号 | 名称 | 端子説明 |
| :-: | :-: | :-: |
| 1 | GND | - |
| 2 | OUT1 | 出力端子(＋側) |
| 3 | NC | 空き |
| 4 | Vref | 制御電源端子(PWM入力) |
| 5 | IN1 | 入力端子(＋側) |
| 6 | IN2 | 入力端子(ー側) |
| 7 | Vcc | ロジック側入力端子（IC用電源） |
| 8 | Vs | 出力側電源端子(モータ用電源) |
| 9 | NC | 空き |
| 10 | OUT2 | 出力端子(ー側) |

#PWMを使わずに動作確認
動作確認なのでクラスを作らずだーっとコーディング
RaspberryPiに初期インストールされているライブラリのみで実行可能

```python
# coding:utf-8

import RPi.GPIO as GPIO
import time

IN1_A_PIN = 11
IN1_B_PIN = 13
IN2_A_PIN = 15
IN2_B_PIN = 16
PWM_PIN = 18

#ピン設定を物理ピン番号で指定
GPIO.setmode(GPIO.BOARD)

#ピン設定
GPIO.setup(IN1_A_PIN, GPIO.OUT)
GPIO.setup(IN1_B_PIN, GPIO.OUT)
GPIO.setup(IN2_A_PIN, GPIO.OUT)
GPIO.setup(IN2_B_PIN, GPIO.OUT)
GPIO.setup(PWM_PIN, GPIO.OUT)

GPIO.output(PWM_PIN, 1)

#右を前進
GPIO.output(IN1_A_PIN, 1)
GPIO.output(IN1_B_PIN, 0)

time.sleep(1)
GPIO.output(IN1_A_PIN, 0)
GPIO.output(IN1_B_PIN, 0)
GPIO.output(IN2_A_PIN, 0)
GPIO.output(IN2_B_PIN, 0)

#右を後進
GPIO.output(IN1_A_PIN, 0)
GPIO.output(IN1_B_PIN, 1)

time.sleep(1)
GPIO.output(IN1_A_PIN, 0)
GPIO.output(IN1_B_PIN, 0)
GPIO.output(IN2_A_PIN, 0)
GPIO.output(IN2_B_PIN, 0)

#左を前進
GPIO.output(IN2_A_PIN, 1)
GPIO.output(IN2_B_PIN, 0)

time.sleep(1)
GPIO.output(IN1_A_PIN, 0)
GPIO.output(IN1_B_PIN, 0)
GPIO.output(IN2_A_PIN, 0)
GPIO.output(IN2_B_PIN, 0)

#左を後進
GPIO.output(IN2_A_PIN, 0)
GPIO.output(IN2_B_PIN, 1)

time.sleep(1)
GPIO.output(IN1_A_PIN, 0)
GPIO.output(IN1_B_PIN, 0)
GPIO.output(IN2_A_PIN, 0)
GPIO.output(IN2_B_PIN, 0)

#GPIOを解放
GPIO.cleanup()
```

#PWMを使ってに動作確認
ピン設定の部分を変更
上手くいけば回転数が遅くなる

```python
# coding:utf-8

import RPi.GPIO as GPIO
import time

IN1_A_PIN = 16
IN1_B_PIN = 15
IN2_A_PIN = 13
IN2_B_PIN = 11
PWM_PIN = 18

#ピン設定を物理ピン番号で指定
GPIO.setmode(GPIO.BOARD)

#ピン設定
# coding:utf-8

import RPi.GPIO as GPIO
import time

IN1_A_PIN = 16
IN1_B_PIN = 15
IN2_A_PIN = 13
IN2_B_PIN = 11
PWM_PIN = 18

#ピン設定を物理ピン番号で指定
GPIO.setmode(GPIO.BOARD)

#ピン設定
GPIO.setup(IN1_A_PIN, GPIO.OUT)
GPIO.setup(IN1_B_PIN, GPIO.OUT)
GPIO.setup(IN2_A_PIN, GPIO.OUT)
GPIO.setup(IN2_B_PIN, GPIO.OUT)
GPIO.setup(PWM_PIN, GPIO.OUT)

motorSpeed = GPIO.PWM(PWM_PIN, 50)     #第2引数はPWM周波数(Hz)
motorSpeed.start(0)                    #Duty 0%で制御開始

motorSpeed.ChangeDutyCycle(30)

#右を前進
GPIO.output(IN1_A_PIN, 1)
GPIO.output(IN1_B_PIN, 0)

time.sleep(1)
GPIO.output(IN1_A_PIN, 0)
GPIO.output(IN1_B_PIN, 0)
GPIO.output(IN2_A_PIN, 0)
GPIO.output(IN2_B_PIN, 0)

#右を後進
GPIO.output(IN1_A_PIN, 0)
GPIO.output(IN1_B_PIN, 1)

time.sleep(1)
GPIO.output(IN1_A_PIN, 0)
GPIO.output(IN1_B_PIN, 0)
GPIO.output(IN2_A_PIN, 0)
GPIO.output(IN2_B_PIN, 0)

#左を前進
GPIO.output(IN2_A_PIN, 1)
GPIO.output(IN2_B_PIN, 0)

time.sleep(1)
GPIO.output(IN1_A_PIN, 0)
GPIO.output(IN1_B_PIN, 0)
GPIO.output(IN2_A_PIN, 0)
GPIO.output(IN2_B_PIN, 0)

#左を後進
GPIO.output(IN2_A_PIN, 0)
GPIO.output(IN2_B_PIN, 1)

time.sleep(1)
GPIO.output(IN1_A_PIN, 0)
GPIO.output(IN1_B_PIN, 0)
GPIO.output(IN2_A_PIN, 0)
GPIO.output(IN2_B_PIN, 0)

#GPIOを解放
motorSpeed.stop()
GPIO.cleanup()
```