電子工作初心者が ラズパイで サーボモータ1～4個を動かした方法

# はじめに

私は、電子工作初心者ですが、Raspberry Pi から、サーボモータ4つを動かすことができるようになったので、その時の手順をまとめてみます。

サーボモータ1個であれば、いろいろなブログを参考にして、その通りに動かすことができました。
サーボモータを2個以上動かすときは電源の確保が必要で、何が必要なのか、どんな物を購入する必要があるのか悩んでしまい、なかなか進まなかったのですが、手元にあるUSB充電器や、スマホ用モバイルバッテリーが使えることが分かり解決しました。

使用したプログラミング言語はPythonです。PythonからGPIO制御するライブラリがいくつかあり、どれを使ったらよいのか迷いましたが、いくつか使ってみて、pigpioに落ち着きました。

## 前提条件/動作環境

ラズパイ：Raspberry Pi 3 B+
OS：Raspbian
プログラミング言語：Python 3.7
Pythonライブラリ：pigpio
サーボモータ：マイクロサーボSG90
電源：家庭用コンセント接続のUSB充電器、スマホ用モバイルバッテリー

## 要約/ポイント

サーボモータ1個であれば、ラズパイからサーボモータへ電気を供給して、動かすことが可能。

サーボモータ2個以上の場合、ラズパイから供給できる電流が足りなくなるので、外部電源が必要。
マイクロサーボSG90は、電圧4.8～5Vで動作する。必要な電流は、いくつかのブログを見ると、だいたい、通常130～200mA、最大500mAとか1.2Aの模様。
今回、USB充電器やスマホ用モバイルバッテリーのUSBポートを使用した。USBの規格では電圧5Vに決められている。電流は、今回使ったバッテリーだと、1Aと2.1Aの2つの口があった。
今回試していないが、通常単3電池（1.5V）を3個使用し1.5V×3個＝4.5V、充電式単3電池（1.2V）を4個使用し1.2V×4個＝4.8Vでも良さそう。

サーボモータを動かすためには、PWMという制御信号を送る必要があり、そのための仕組みがラズパイやPythonライブラリに用意されている。

# サーボモータ1個を動かす（ラズパイ電源）

## pigpioインストール

PythonからラズパイのGPIOを制御するため、pigpioというライブラリを使いました。
次のコマンドでインストールできました。

```terminal
$ pip install pigpio
```

インストールしたpigpioを使うためには、事前に常駐させておく必要があるので、次のコマンドを実行しておきました。

```terminal
$ sudo pigpiod
```

## 動作確認

ラズパイで用意されているハードウェアPWMを使用するため、GPIO13を使用しました。ハードウェアPWMについては、次のブログを参考にしました。

>[Raspberry PiのハードウェアPWMをpigpioで出力する - Qiita](https://qiita.com/s417-lama/items/0ef64a7af3fcf6a56cc5)
>・ラズパイではハードウェアPWMに対応しているピンが4つあり、独立に制御できるのは2組ずつです。
>・PWM Channel 0 : GPIO12、GPIO18
>・PWM Channel 1 : GPIO13、GPIO19

プログラムは、こんな感じです。上手く動きました。

```python
import pigpio
import time

SERVO_PIN = 13
pi = pigpio.pi()

try:
    while True:
        pi.hardware_PWM(SERVO_PIN, 50, int(1000000*1.45/20))
        time.sleep(3)
        pi.hardware_PWM(SERVO_PIN, 50, int(1000000*2.4/20))
        time.sleep(3)
        pi.hardware_PWM(SERVO_PIN, 50, int(1000000*0.5/20))
        time.sleep(3)
except KeyboardInterrupt:
    pass

pi.hardware_PWM(SERVO_PIN, 50, 0)
pi.stop()
```
![DSC_0583_240x240.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24511/5026fc88-1b63-2a46-4911-1a5bbd44fb13.jpeg)

# サーボモータ1個を動かす（外部電源）

サーボモータ2個を動かすためには、外部電源が必要になるので、外部電源を使う練習をしてみました。
外部電源としてUSB充電器を使っています。USBの仕様が次のように決められているので、サーボモータを動かすのにちょうどよいと考えました。

> [ユニバーサル・シリアル・バス - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%A6%E3%83%8B%E3%83%90%E3%83%BC%E3%82%B5%E3%83%AB%E3%83%BB%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%AB%E3%83%BB%E3%83%90%E3%82%B9)
>・USB2.0 電圧5V、電流500mA
>・USB3.x 電圧5V、電流900mA

プログラムは、ラズパイ電源で動かした時と同じです。上手く動かすことができました。

![DSC_0582_240x240.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24511/1fef7c7e-f19c-7d61-4b2a-48745bc4e979.jpeg)

上記では、ハードウェアPWMを使いましたが、ソフトウェアPWMでも動かしてみました。
次のプログラムで、動かすことができましたが、高周波が少し不安定になってしまった気もしました。

```python
import pigpio
import time

SERVO_PIN = 13
pi = pigpio.pi()

try:
    while True:
        pi.set_servo_pulsewidth(SERVO_PIN, 1450)
        time.sleep(3)
        pi.set_servo_pulsewidth(SERVO_PIN, 2400)
        time.sleep(3)
        pi.set_servo_pulsewidth(SERVO_PIN, 500)
        time.sleep(3)
except KeyboardInterrupt:
    pass

pi.set_servo_pulsewidth(SERVO_PIN, 0)
pi.stop()
```

# サーボモータ2個を動かす

ハードウェアPWMを使うため、GPIO12,13に接続しました。
プログラムは次です。サーボモータ1個のときと同じ処理を、2つのサーボモータに対して行っています。
少し不安定ですが、動かすことができました。

```python
import pigpio 
import time

SERVO_PIN_1 = 13 
SERVO_PIN_2 = 12 
pi = pigpio.pi()

try: 
    while True: 
        pi.hardware_PWM(SERVO_PIN_1, 50, int(1000000*1.45/20)) 
        time.sleep(1) 
        pi.hardware_PWM(SERVO_PIN_2, 50, int(1000000*1.45/20)) 
        time.sleep(1) 
        pi.hardware_PWM(SERVO_PIN_1, 50, int(1000000*2.4/20)) 
        time.sleep(1) 
        pi.hardware_PWM(SERVO_PIN_2, 50, int(1000000*2.4/20)) 
        time.sleep(1) 
        pi.hardware_PWM(SERVO_PIN_1, 50, int(1000000*0.5/20)) 
        time.sleep(1) 
        pi.hardware_PWM(SERVO_PIN_2, 50, int(1000000*0.5/20)) 
        time.sleep(1) 
except KeyboardInterrupt: 
    pass 

pi.hardware_PWM(SERVO_PIN_1, 50, 0) 
pi.hardware_PWM(SERVO_PIN_2, 50, 0) 
pi.stop()
```

![DSC_0582 (1)_240x240.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24511/fb6930e4-382a-f0c0-b8b1-d6a09d49411c.jpeg)

# サーボモータ3個を動かす

サーボモータ3個を動かそうとすると、また電源の壁がありました。
今回使ったUSB充電器では、電流が1Aまでで、サーボモータ3個を動かすのは無理でした。
なので、USB充電器でサーボモータ2個を動かし、ラズパイ電源でサーボモータ1個を動かしました。
あと、USB充電器よりもスマホ用モバイルバッテリーの方が扱いが楽だったので、モバイルバッテリーを使っています。

サーボモータ制御用のGPIOピンですが、GPIO 13,12をハードウェアPWMで使用、GPIO 17をソフトウェアPWMで使用しています。

プログラムを次のようにしました。サーボモータが増えたので、処理が長くなりましたが、やっていることは今までとあまり変わりませんでした。

```python
import pigpio 
import time

SERVO_PIN_1 = 13 
SERVO_PIN_2 = 12 
SERVO_PIN_3 = 17 
pi = pigpio.pi() 

try: 
    while True: 
        pi.hardware_PWM(SERVO_PIN_1, 50, int(1000000*1.45/20)) 
        time.sleep(1) 
        pi.hardware_PWM(SERVO_PIN_2, 50, int(1000000*1.45/20)) 
        time.sleep(1) 
        pi.set_servo_pulsewidth(SERVO_PIN_3, 1450) 
        time.sleep(1) 
        pi.hardware_PWM(SERVO_PIN_1, 50, int(1000000*2.4/20)) 
        time.sleep(1) 
        pi.hardware_PWM(SERVO_PIN_2, 50, int(1000000*2.4/20)) 
        time.sleep(1) 
        pi.set_servo_pulsewidth(SERVO_PIN_3, 2400) 
        time.sleep(1) 
        pi.hardware_PWM(SERVO_PIN_1, 50, int(1000000*0.5/20)) 
        time.sleep(1) 
        pi.hardware_PWM(SERVO_PIN_2, 50, int(1000000*0.5/20)) 
        time.sleep(1) 
        pi.set_servo_pulsewidth(SERVO_PIN_3, 500) 
        time.sleep(1) 
except KeyboardInterrupt: 
    pass 

pi.hardware_PWM(SERVO_PIN_1, 50, 0) 
pi.hardware_PWM(SERVO_PIN_2, 50, 0) 
pi.set_servo_pulsewidth(SERVO_PIN_3, 0) 
pi.stop()
```

![DSC_0582(2)_240x240.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24511/31361156-b0ac-30bf-7c0f-120b7abd19a2.jpeg)

# サーボモータ4個を動かす

サーボモータ4個を動かそうとすると、またまた電源の壁がありました。
モバイルバッテリーだとサーボモータ2個まで、ラズパイ電源だと1個までなので、最大3個までしか動かせられません。
でも、モバイルバッテリーを見ると、USBポートが2つあったので、各ポートでサーボモータ2個を動かし、計4個動かすことにしました。結果、上手く動きました。

サーボモータ制御用のGPIOピンですが、GPIO 13,12をハードウェアPWMで使用、GPIO 27,23をソフトウェアPWMで使用しています。

プログラムを次のようにしました。これも、サーボモータの増加に伴い処理が増えただけで、やっていることは同じです。

```python
import pigpio 
import time 

SERVO_PIN_1 = 13 
SERVO_PIN_2 = 12 
SERVO_PIN_3 = 27 
SERVO_PIN_4 = 23 
pi = pigpio.pi() 

try: 
    while True: 
        pi.hardware_PWM(SERVO_PIN_1, 50, int(1000000*1.45/20)) 
        time.sleep(1) 
        pi.hardware_PWM(SERVO_PIN_2, 50, int(1000000*1.45/20)) 
        time.sleep(1) 
        pi.set_servo_pulsewidth(SERVO_PIN_3, 1450) 
        time.sleep(1) 
        pi.set_servo_pulsewidth(SERVO_PIN_4, 1450) 
        time.sleep(1) 
        pi.hardware_PWM(SERVO_PIN_1, 50, int(1000000*2.4/20)) 
        time.sleep(1) 
        pi.hardware_PWM(SERVO_PIN_2, 50, int(1000000*2.4/20)) 
        time.sleep(1) 
        pi.set_servo_pulsewidth(SERVO_PIN_3, 2400) 
        time.sleep(1) 
        pi.set_servo_pulsewidth(SERVO_PIN_4, 2400) 
        time.sleep(1) 
        pi.hardware_PWM(SERVO_PIN_1, 50, int(1000000*0.5/20)) 
        time.sleep(1) 
        pi.hardware_PWM(SERVO_PIN_2, 50, int(1000000*0.5/20)) 
        time.sleep(1) 
        pi.set_servo_pulsewidth(SERVO_PIN_3, 500) 
        time.sleep(1) 
        pi.set_servo_pulsewidth(SERVO_PIN_4, 500) 
        time.sleep(1) 
except KeyboardInterrupt: 
    pass 

pi.hardware_PWM(SERVO_PIN_1, 50, 0) 
pi.hardware_PWM(SERVO_PIN_2, 50, 0) 
pi.set_servo_pulsewidth(SERVO_PIN_3, 0) 
pi.set_servo_pulsewidth(SERVO_PIN_4, 0) 
pi.stop()
```

![DSC_0583_5_240x240.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24511/ca83cfc3-a763-7fe3-6533-d25900aca160.jpeg)
![DSC_0586_240x240.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24511/09304914-8fbb-d937-b80d-d68704bc1e2b.jpeg)

# トラブル対応

作業中、躓いたところを書いておきます。

## pigpioインストールエラー

Pythonライブラリのpigpioをインストールしようとして、試行錯誤、次のようなコマンドを実行していました。

```terminal
$ pip install pygpio
```

そして、Pythonの対話形式モードから使おうとすると次のエラーが発生しました。

```terminal
In [1]: import pygpio
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-1-462f3c478519> in <module>
----> 1 import pygpio
~/.pyenv/versions/3.7.3/lib/python3.7/site-packages/pygpio/__init__.py in <module>
      1 from __future__ import absolute_import
      2
----> 3 from Adafruit_GPIO.GPIO import *
ModuleNotFoundError: No module named 'Adafruit_GPIO'
```

原因は、ライブラリ名のスペルミスで、誤「pygpio」、正「pigpio」でした。

## pigpioインポートエラー

上手くインストールできた後、Pythonからpigpioをインポートしようとすると、次のエラーが発生することがありました。

```terminal
Can't connect to pigpio at localhost(8888) 
Did you start the pigpio daemon? E.g. sudo pigpiod 
Did you specify the correct Pi host/port in the environment 
variables PIGPIO_ADDR/PIGPIO_PORT? 
E.g. export PIGPIO_ADDR=soft, export PIGPIO_PORT=8888 
Did you specify the correct Pi host/port in the 
pigpio.pi() function? E.g. pigpio.pi('soft', 8888) 
```

これは、事前にpigpiodを起動していないからでした。次のコマンドを実行してから、インポートすると解決です。

```terminal
$ sudo pigpiod
```

# おわりに

今回、Raspberry Pi から、サーボモータを1個、2個、3個、4個と増やして動かしてみました。電子工作の経験がなく、電源管理に悩まされましたが、動かすことができました。ものが動くと達成感がありますね。

サーボモータ4個を動かした際、4つ足のロボットを作れるかも、と無邪気に素人考えをしてしまいました。
ためしに作成して、何となく歩行した気がするので、動画も作成してみました。良かったらご覧ください。

<iframe width="320" height="240" src="https://www.youtube.com/embed/qGTSfgEfjE0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

<iframe width="320" height="240" src="https://www.youtube.com/embed/ZpqVt6AZ9Do" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

<iframe width="320" height="240" src="https://www.youtube.com/embed/0n1Yuz06ijo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

# 参考サイト

[Raspberry Pi GPIO Pinout](https://pinout.xyz/)
・ラズパイのGPIOピンの配置を確認しました。

[マイクロサーボ９ｇ　ＳＧ－９０: パーツ一般 秋月電子通商-電子部品・ネット通販](https://akizukidenshi.com/catalog/g/gM-08761/)
・マイクロサーボSG90の主な仕様が書かれていて助かりました。

[Raspberry Piでサーボモーター動作](https://monomonotech.jp/kurage/raspberrypi/servo.html)
[Raspberry PiのハードウェアPWMをpigpioで出力する - Qiita](https://qiita.com/s417-lama/items/0ef64a7af3fcf6a56cc5)
・サーボモータを制御するのに参考にさせていただきました。

[ユニバーサル・シリアル・バス - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%A6%E3%83%8B%E3%83%90%E3%83%BC%E3%82%B5%E3%83%AB%E3%83%BB%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%AB%E3%83%BB%E3%83%90%E3%82%B9)
・USBの電源供給仕様を確認しました。