kurukuru-papaのブログ

主に、ソフトウェア開発に関連したメモを書き溜めたいと思います。

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

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

はじめに

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

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

前提条件/動作環境

要約/ポイント

サーボモータ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というライブラリを使いました。 次のコマンドでインストールできました。

$ pip install pigpio

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

$ sudo pigpiod

動作確認

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

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

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

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

サーボモータ1個を動かす(外部電源)

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

ユニバーサル・シリアル・バス - Wikipedia
USB2.0 電圧5V、電流500mA
・USB3.x 電圧5V、電流900mA

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

DSC_0582_240x240.jpg

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

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つのサーボモータに対して行っています。 少し不安定ですが、動かすことができました。

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

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

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

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

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

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

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

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

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

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

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 DSC_0586_240x240.JPG

トラブル対応

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

pigpioインストールエラー

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

$ pip install pygpio

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

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をインポートしようとすると、次のエラーが発生することがありました。

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を起動していないからでした。次のコマンドを実行してから、インポートすると解決です。

$ sudo pigpiod

おわりに

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

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

参考サイト

Raspberry Pi GPIO Pinout

  • ラズパイのGPIOピンの配置を確認しました。

マイクロサーボ9g SG-90: パーツ一般 秋月電子通商-電子部品・ネット通販

  • マイクロサーボSG90の主な仕様が書かれていて助かりました。

Raspberry Piでサーボモーター動作 Raspberry PiのハードウェアPWMをpigpioで出力する - Qiita

ユニバーサル・シリアル・バス - Wikipedia

  • USBの電源供給仕様を確認しました。