IoT演習第６回、２種類のモータ制御

# 1. はじめに
[IoT演習シラバス案その２（授業計画表）](https://qiita.com/takashiyamanoue/items/0cf9d58265bff5883698)の第6週に予定している内容の一部です。

マイクロコントローラ（マイコンと呼ぶこともあります）は、コンピュータ(CPU+メモリ)と入出力機能を、ICの１つのチップや１枚のボードにまとめたものです。マイコンには電源を供給する端子の他に入出力を行う端子がついています。マイコンの入出力端子に、情報を入力するセンサ、情報を出力する表示装置、動作を行うアクチュエータ（モータなど）を接続して、様々な物を制御することができます。

https://ja.wikipedia.org/wiki/マイクロコントローラ

今回は、マイクロコントローラのGPIOの出力を使った（ブラシ付き）直流モータの制御、および、マイクロコントローラのPWM出力を使ったサーボモータの制御について説明します。内容は以下のとおりです。

- Hブリッジによる(ブラシ付き)直流モーターの制御
- Hブリッジによる(ブラシ付き)直流モーターの制御の演習
- PWMによるサーボモータの制御
- PWMによるサーボモータの制御の演習
- 授業の振り返り


# 2.  Hブリッジによる(ブラシ付き)直流モータの制御

***ブラシ付き直流モータ***とは、工作でよく使われる小型モータや、ミニ四駆のモータ等によく使われている、２本の導線が出ていて、それに電池をつなぐと回りだすようなモータです。モータには中心に導線がくるくる巻かれた電磁石が（通常３つ）ついた回転子があり、それが回転軸につながっています。回転子の周りには固定された永久磁石があります。回転子と導線は、回転子に繋がった整流子と呼ばれる金属の板と、導線につながったブラシで電気的につながっていて、導線に電流が流れると、回転子の電磁石が固定子の永久磁石に吸収・反発し、回転方向に力がかかるようになっています。また、回転子の回転に伴って整流子が回転することで、回転子のコイルに流れる電流の向きが変わり、常に回転子に回転する力が加わるように、回転子のコイルの磁界が変化します。

https://ja.wikipedia.org/wiki/%E7%9B%B4%E6%B5%81%E9%9B%BB%E5%8B%95%E6%A9%9F

https://jp.aspina-group.com/ja/learning-zone/columns/what-is/013/

https://toshiba.semicon-storage.com/jp/semiconductor/knowledge/e-learning/brushless-motor/chapter2/comparison-brushed-dc-motor-and-brushless-motor.html

ブラシ付き直流モータは、その導線にかける電圧の向きを逆にすることで、回転方向を逆にすることができます。

また、モーターの端子を電源から離してモーターを回転させると、モーターが発電機の役割を果たして、モーターの端子の間に電圧が発生します。この時、この端子をショートすると、回転を止める方向に力が働き、ブレーキがかかります。

**Hブリッジ**とは、モーターにかかる電圧(+と-)を順方向にかけたり、それを逆方向にしたり、電圧をかけなくしたり（ニュートラル）、ショートしたり（ブレーキ）するような制御を行うことができる素子です。ニュートラルとは、モーターに外から回転の力を加えると空回りする状態です。自動車のギアのニュートラルの状態と一緒です。

https://tohan-denshi.co.jp/technical-information/8244/

https://sakigake-robo.com/motor-6/


上のリンク先のページで述べられているように、Hブリッジの２つの出力端子がモーターに電圧をかける線とつながり、モータを中心に、H型に接続された４つのスイッチのON/OFFの状態を変えることによって、モーターの回転を制御しています。また、回転とニュートラルの状態を細かく切り替えることにより、モーターの回転速度を変えることもできます。

# 3. Hブリッジによる(ブラシ付き)直流モーターの制御の演習

この演習では、内部に２つのHブリッジを持つモーターコントローラIC、DRV8835を使ったボード、AE-DRV8835-Sを使って、２つのモーターを制御してみます。

https://akizukidenshi.com/catalog/g/g109848/

https://akizukidenshi.com/goodsaffix/AE-DRV8835-S_20210526.pdf

https://www.ti.com/product/ja-jp/DRV8835

モーターは以下のものを使用します。

https://akizukidenshi.com/catalog/g/g113629/

## 3.1 回路例

DRV8835 のAIN1端子とAIN2端子のHighとLowの組み合わせにより、AOUT1とAOUT2の間に接続されたモーター(モーターM1)の正転、逆転、停止（ニュートラル）、ブレーキを制御します。モーターの電源は、DRV8835のVM端子とGND端子の間に接続された乾電池（3V）から供給されます。Hブリッジを構成する４つのFETのON/OFFの制御のための電源(+)はDRV8835のVCC端子に接続されたPico Wの3V3端子(3.3V出力端子)から供給されます。

AIN1及び AIN2の入力(High/Low)と, AOUT1, AOUT2の出力(High(+VM), Low(GND), Z(High impedance))の関係は以下のようになります。AOUT1とAOUT2のZは、その端子がHighでもなく、Lowでもなく、宙に浮いている（+VMにもGNDにも接続されていない）ことを意味します。

| AIN1 | AIN2 | AOUT1 | AOUT2 | モーターM1の回転|
|:-:|:-:|:-:|:-:|:-:|
| Low(0)  | Low(0)  | Z  | Z  | ニュートラル |
| Low(0)  | High(1) | Low(GND)  | High(+VM)  | 逆転|
| High(1) | Low(0)  | High(+VM) | Low(GND)  | 正転|
| High(1) | High(1) | Low(GND)  | Low(GND)  | ブレーキ|

同様に、
DRV8835 のBIN1端子とBIN2端子のHighとLowの組み合わせにより、BOUT1とBOUT2の間に接続されたモーター(モーターM2)の正転、逆転、停止（ニュートラル）、ブレーキを制御します。モーターの電源は、DRV8835のVM端子とGND端子の間に接続された乾電池（3V）から供給されます。Hブリッジを構成する４つのFETのON/OFFの制御のための電源(+)はDRV8835のVCC端子に接続されたPico Wの3V3端子(3.3V出力端子)から供給されます。

BIN1及び BIN2の入力(High/Low)と, BOUT1, BOUT2の出力(High(+VM), Low(GND), Z)の関係は以下のようになります。BOUT1とBOUT2のZも、その端子がHighでもなく、Lowでもなく、宙に浮いている（+VMにもGNDにも接続されていない）ことを意味します。

| BIN1 | BIN2 | BOUT1 | BOUT2 | モーターM2の回転|
|:-:|:-:|:-:|:-:|:-:|
| Low(0)  | Low(0)  | Z  | Z  | ニュートラル |
| Low(0)  | High(1) | Low(GND)  | High(+VM)  | 逆転|
| High(1) | Low(0)  | High(+VM) | Low(GND)  | 正転|
| High(1) | High(1) | Low(GND)  | Low(GND)  | ブレーキ|

AIN1はGP10, AIN2はGP11, BIN1はGP12, BIN2はGP13に接続されています。
GP11からGP13までの４つのGPIO端子のHigh(1)/Low(0)を変化させることにより、モーターM1とモーターM2の、２つのモーターの正転、逆転、停止、ブレーキ、を制御することができます。

![20240824-picp-w-ae-drv8853-brd-sche-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585767/ee259a78-1508-f892-aee5-5f59e43bca74.png)



## 3.2 プログラム例

(以下は、[第２回](https://qiita.com/takashiyamanoue/items/4baba8e23c86dc07962d)で説明している、Anaconda(Python), VSCode, VSCodeのMicroPicoのExtentionがインストール済みであることを前提としています。)


以下のプログラムは、２つのモータの回転を停止（ニュートラル）した後、
- モーターM1を一秒間正転
- 回転を一秒間停止（ニュートラル）
- モーターM2を一秒間正転
- 回転を一秒間停止（ニュートラル）
- モーターM1を一秒間逆転
- 回転を一秒間停止（ニュートラル）
- モーターM2を一秒間逆転
- 回転を一秒間停止（ニュートラル）
を繰り返し行うものです。

```Python
from machine import Pin
import time
in1=Pin(10, Pin.OUT)
in2=Pin(11, Pin.OUT)
in3=Pin(12, Pin.OUT)
in4=Pin(13, Pin.OUT)
in1.off()
in2.off()
in3.off()
in4.off()
while True:
    in1.on()
    time.sleep(1.0)
    in1.off()
    time.sleep(1.0)
    in3.on()
    time.sleep(1.0)
    in3.off()
    time.sleep(1.0)
    in2.on()
    time.sleep(1.0)
    in2.off()
    time.sleep(1.0)
    in4.on()
    time.sleep(1.0)
    in4.off()
    time.sleep(1.0)   
```

## 3.3 演習１
上の回路を作成し、２つのモーターを１つの紙コップの縁に貼り付けて、以下の、コップロボのような簡単なロボットを作ってください（下のコップロボの電池とスイッチは、Pico WとAE-DRV8835-Sと電池を接続したブレッドボードと入れ替えてください）。このロボットを上のプログラムで動かして、モーターの回転が想定した通り動くことを確認した後、プログラムを書き換えて、ロボットを自分が好きなように動かすプログラムを作成し、ロボットを動かしてください。

https://www.kagakutankentai.jp/2018/12/04/コップロボ/

https://youtu.be/LBul6vPKH7Y?si=hU_ytMupOIdF1bns


## 3.4 考えてみよう

Pico Wの3v3端子の出力電圧は3.3Vですが、モーターへ電源を供給している電池も、1.5Vの電池を直列接続しているので3Vになり、ほぼ、Pico Wの3v3端子の電圧と変わりません。なのに、なぜ、わざわざ、モーターの電源を別の電池から取っているのでしょうか？　気になる人は調べてみてください。

# 4. PWMによるサーボモータの制御の演習

IoT演習第5回で述べたように、Pico WのGPIOは、**PWM**(Pulse Width Modulation, ***パルス変調***)の機能を持っています。

PWMとは、一定周期(逆数をとると一定周波数)でHigh(1,On)とLow(0,Off)の繰り返し（***パルス***）を出力するのですが、そのとき、Highのときの時間の比率と、Lowの時の時間の比率(***デューティー比***)を変化させるものです。

![pwm-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585767/c7edf80f-bc06-8189-61b1-ea51319d52a2.png)


https://en.wikipedia.org/wiki/Pulse-width_modulation

PWMはサーボモータの制御信号としてよく用いられています。サーボモータとは、ラジコンカーやラジコン飛行機の進行方向の制御などに用いられている、モータの軸の位置（回転角度）を信号で変化させることができるモーターです。

https://ja.wikipedia.org/wiki/%E3%82%B5%E3%83%BC%E3%83%9C%E3%83%A2%E3%83%BC%E3%82%BF

Pico WのMicro Python でPWMを利用する場合、
```Python
<PWM変数名>=PWM(Pin(<GPIOピン番号>),freq=<周波数>,duty_u16=<デフォルトのデューティー比>)
```
を実行し、GPIOピン番号で指定した端子にPWM出力を割り当てます。freqとduty_u16は省略することが可能で、その場合はデフォルトの値となります。

```Python
<PWM変数名>.freq(<新周波数>)
```
を実行すると、PWMの周波数が新周波数になります。

```Python
<PWM変数名>.duty_u16(<デューティー比>)
```
を実行すると、そのデューティー比のPWM信号が、<GPIOピン番号>の端子から出力されます。
Highの時の電圧は3.3VでLowの時の電圧は0Vです。

https://micropython-docs-ja.readthedocs.io/ja/latest/rp2/quickref.html#pwm-pulse-width-modulation


## 4.1 回路例

Pico WのGPIO端子はPWM信号を出力することができ、かつ、サーボモータの信号線に入れる信号の電圧は3.3VでもOKなので、以下の回路のように、サーボモータの信号線をGPIO端子の１つに直接接続し、電源を外部の電池から供給することで、サーボモータを動かすことができます（3Vでは動く場合と動かない場合があります。動かない場合は電源の電圧を上げてみてください（最大6V））。

![20240824-pico-w-servo-brdb-sche-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585767/67b12b26-eef7-6b16-5c64-91367bd4b797.png)

サーボモータは以下のものを使います。

https://akizukidenshi.com/catalog/g/g108761/

以下の資料の中に、PWM信号の周期、サーボホーンの回転角と、その時のパルスのHighの時の時間が書かれています。PWM信号については
- 周期は1/50Hz=0.02sec,
- サーボホーンが中間点(0度)の時のHighのパルス幅(時間)は、1.45msec.
- サーボホーンが左回転最大(-90度)の時のHighのパルス幅(時間)は、0.5msec.
- サーボホーンが右回転最大(90度)の時のHighのパルス幅(時間)は、2.4msec.

になっています。

https://akizukidenshi.com/goodsaffix/SG90_a.pdf

## 4.2 プログラム例

以下のプログラムは、サーボモータSG90のホーンの向きを、２秒ごとに、
- 0度
- 90度
- 0度
- -90度

に変化させるプログラムです。

```Python
from machine import PWM, Pin
from time import sleep

servo = PWM(Pin(9))
servo.freq(50)

angle_M90 = int(2.5 / 20 * 65536)
angle_0 = int(1.5 / 20 * 65536)
angle_90 = int(0.5 / 20 * 65536)

while True:
    servo.duty_u16(angle_0)
    print(angle_0)
    sleep(2)
    servo.duty_u16(angle_90)
    print(angle_90)
    sleep(2)
    servo.duty_u16(angle_0)
    print(angle_0)
    sleep(2)
    servo.duty_u16(angle_M90)
    print(angle_M90)
    sleep(2)
```

## 4.3 演習２
上の回路を作成し、サーボモータを動かして動作を確認してください。