mieki256's diary



2016/07/19(火) [n年前の日記]

#1 [raspberrypi] Raspberry Pi3でサーボモータを制御。その1

秋月電子から購入したマイクロサーボモータ、 _SG92R を、Raspberry Pi3 から制御したいなと。

サーボモータってのは…。この場合は、PWMで角度を指定して動かせるモータ、という認識でいいのだろうか。 _サーボモータ - Wikipedia を眺めるとゴイスなヤツからホビー用まで色々あるらしいけど。今回使うのはホビー用。

仕様をメモ。 :

とりあえず、SG92Rの仕様を秋月電子さんのサイトからコピペしてメモ。特に、PWMサイクル、制御パルスの仕様が重要。
SG92R : メーカー : Tower Pro Pte Ltd
PWMサイクル : 20ms
制御パルス : 0.5ms〜2.4ms
制御角 : ±約90°(180°) 配線 : 茶 = GND、赤 = 電源[+]、橙 = 制御信号 [JRタイプ]
トルク : 2.5 kgf・cm
動作速度 : 0.1秒 / 60度
動作電圧 : 4.8V(〜6V)
温度範囲 : 0℃〜55℃
外形寸法 : 23 x 12.2 x 27mm
重量 : 9g

マイクロサーボ SG92R: サーボ 秋月電子通商 電子部品 ネット通販 より


つまり、20ms間隔でPWMを流して…。0.5ms幅のパルスを送ると -90度に、2.4ms幅のパルスを送ると90度にモータが回転してくれる、のであろうと。

ピンコネクタでちょっと失敗。 :

サーボモータの端子をブレッドボードに差すために、 _細ピンヘッダ 1 x 20 も購入したのだけど。試してみたら長さが足りなかった…。もしかすると、ここは _両端ロングピンヘッダ なるものを購入すべきだったのだろうか…。

とりあえず、 _ブレッドボード用ジャンパーコード(オス - オス) をサーボモータ側の端子に差し込んでどうにか。

回路図。 :

こんな感じに。
servo_motor_02_bb.png

servo_motor_02_c.png
  • Raspberry Pi3 の GPIO 18番を、サーボモータの制御信号に接続。GPIO 18番なら、PWMが使える場合が多いらしいので。
  • サーボモータの電源は、単三電池 x 4 で確保。
  • モータがノイズを出すらしいので、ノイズ対策としてモータの電源(VCC - GND)の間に 100uF のコンデンサを追加。コンデンサにはプラスマイナスがあるので注意。

巷の解説記事を眺めてると、コンデンサや抵抗を入れる場合と入れない場合があるようで。
  • コンデンサをつけるとしても 0.1uF とか 100uF とか色々あって、どれが正しいのやら。
  • Raspberry Pi3 の GPIOピンと、サーボモータの制御信号の間に、1KΩ程度の抵抗を入れる場合も。サーボモータが壊れた際に逆流しないように、という理由だとか。

Pythonで動かしてみる。 :

とりあえず、LEDをPWMで光らせた時と同じやり方で ―― Python + RPi.GPIO を使う形で制御してみたり。servo_pwm.py として保存。
#!/usr/bin/python
# -*- coding: utf-8 -*-

import RPi.GPIO as GPIO
import time

PULSE_PIN = 18
TOTAL_MS = 20.0
MIN_MS = 0.5
MAX_MS = 2.4
MIN_DCV = (float(MIN_MS) / TOTAL_MS) * 100.0 - 0.7
MAX_DCV = (float(MAX_MS) / TOTAL_MS) * 100.0 - 0.5

def get_dc(ang):
    ang += 90
    if ang < 0.0:
        ang = 0.0
    if ang > 180.0:
        ang = 180.0
    dc = MIN_DCV + ((MAX_DCV - MIN_DCV) * (float(ang) / 180.0))
    return dc

GPIO.setmode(GPIO.BCM)
GPIO.setup(PULSE_PIN, GPIO.OUT)
pwm = GPIO.PWM(PULSE_PIN, 50)
pwm.start(get_dc(0))

try:
    for ang in [0, -90, 0, 90, 0, -90, -45, 0, 45, 90, 0]:
        dc = get_dc(ang)
        print "ang %f , dc %f" % (ang, dc)
        pwm.ChangeDutyCycle(dc)
        time.sleep(3)

except KeyboardInterrupt:
    pass

pwm.stop()
GPIO.cleanup()

sudo python servo_pwm.py として実行。



動いた。

と思ったら、甘かった。指定角度で止まってくれたように一瞬見えたけど、なんだか「ジャジャッ…ジャッ…」と鳴きながら、ガクガクブルブルしている…。これじゃ使えない…。

Python + RPi.GPIO はPWM制御に関して精度がよろしくない、という話も見かけたけれど。ひょっとして、そのせいでガクブルしてしまうのだろうか…。それとも別の原因が…。

全然関係ないけど、サーボモータ上に乗せたのは _2012/05/15 に作ったペーパークラフト。机の中を探したらコレが見つかったので。

ServoBlasterをインストールしてみた。 :

サーボモータを制御することに特化した、ServoBlaster なるものがあるそうで。デーモンとして動くことで、比較的正確なPWM制御が可能になっているらしい。

_Raspberry PI でサーボを動かす ・ Airwhite Memo
_Raspberry Pi でサーボモータ制御 - Qiita
_Raspberry-PiにおけるGPIO関係ツールのインストール方法
_[raspberry] GPIOの制御とservoblasterの併用時 | Gerolian
_Indoor airplane world
_raspberry Pi でサーボモータ制御 | Linux & Android Dialy

コレを使えば、RPi.GPIO 使用時と違う結果になるのでは。試してみないと。

インストールは以下。
$ git clone git://github.com/richardghirst/PiBits.git
$ cd PiBits/ServoBlaster/user
$ make servod
$ sudo make install
servod てのが、コマンド名(?)らしい。

デーモンとして起動。あるいは、デーモンが起動中なら現在の状態を表示。
sudo servod

デーモンを終了。
sudo killall servod

ServoBlaster をインストールすると、サービスとして自動起動するように設定される。自動起動しないように設定する場合は以下。
sudo update-rc.d servoblaster remove

自動起動するように設定する場合は以下。
sudo update-rc.d servoblaster defaults

サーボ番号と、GPIO番号の対応は以下のようになってるらしい。コピペさせてもらってメモ。
サーボ番号01234567
GPIO番号4171821/2722232425
P1ピン番号?711121315161822

例えば、GPIO 18番のdutyを、パーセント指定で変えたければ、以下のように打つ。
echo 2=0% > /dev/servoblaster
/dev/servoblaster に何かを書き込んでやることで指定できる、ということなんだろう…。

パーセントではなく、パルス幅(10マイクロ秒単位)で指定することも可能。
echo 2=120 > /dev/servoblaster

さて。手持ちの SG92R の場合、受け付けるパルス幅は、最小 0.5ms 〜 最大 2.4ms らしいので、以下が指定できるはずだけど。
echo 2=50 > /dev/servoblaster
echo 2=240 > /dev/servoblaster

試してみたところ、実際には指定できず…。以下の範囲でしか指定できなかった。
echo 2=50 > /dev/servoblaster
echo 2=213 > /dev/servoblaster
213より大きい値を指定すると異音がする…おそらく回りっぱなし…。本来なら 240 まで指定できそうだが…。

つまり、ServoBlaster + SG92R を使う際は、-90度 = 50, 0度 = 131, 90度 = 213 を指定する感じになりそう。

さておき。前述のPythonスクリプトで制御するとガクブルだったけど、ServoBlaster を使った場合は、ちゃんとピタリと止まってくれた。状況が改善した、ような気がする。

ServoBlasterが握るピンの数を変更。 :

ところで、このままだと ServoBlaster が複数のGPIOのピンを握り続けてしまって、他の実験がちょっとやりにくくなる。今回は GPIO 18番だけを使いたいわけで…。

ということで、GPIO 18番だけを利用しなさい、他は使わんでくれ、と指定する。P1ピン番号を使って指定するらしい。
sudo servod --p1pins=12
ただし、コレを一度発行すると、ピン番号が入れ替わるので注意。デフォルトでは、
echo 2=50 > /dev/servoblaster
echo 2=213 > /dev/servoblaster
と指定したけど、1本だけ有効状態にすると、以下のような指定になる。
echo 0=50 > /dev/servoblaster
echo 0=213 > /dev/servoblaster

再度 sudo servod を実行すると、元のピン設定に戻ってしまう模様。

それと、sudo servod 実行時に --idel-timeout=1000 をつけると、指定時間(ms)が過ぎたらアイドル状態になる、ような設定にできる、のかもしれないけど、このあたりよく分かってない。

ServoBlasterを使ったPythonスクリプト。 :

ServoBlaster を使った場合の Pythonスクリプトを書いてみたり。servo_pwm2.py として保存。
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# required servoblaster

import subprocess
import time

START_V = 50
END_V = 213
CENTER_V = 131

def get_pulse(ang):
    ang += 90
    if ang < 0.0:
        ang = 0.0
    if ang > 180.0:
        ang = 180.0
    v = float(END_V - START_V) * (ang / 180.0) + START_V
    return v

try:
    cmd = "servod --p1pins=12 --idle-timeout=1000"
    subprocess.call(cmd, shell=True)
    for ang in [0, -90, 0, 90, 0, -45, 0, 45, 0]:
        pulse = get_pulse(ang)
        print "ang = %f , v = %f" % (ang, pulse)
        cmd = "echo 0=%d > /dev/servoblaster" % (pulse)
        subprocess.call(cmd, shell=True)
        time.sleep(3)

except KeyboardInterrupt:
    pass
要するに、bash上で手打ちしていたコマンドを、subprocess.call() を使って再現してるだけですが。

sudo python servo_pwm2.py として実行。

こちらもガクブルしなかった。指定角度で、ちゃんと止まってるように見える。

pigpioを試用。 :

ServoBlaster はイイ感じにサーボモータを制御できるのだけど、コマンドを呼び出してる感がなんだか気になるわけで。

他の方法を探してみたところ、Python + RPi.GPIO ではなく、Python + RPIO ならサーボモータ専用のモジュールが既に用意されていたそうで。しかし、RPIOは随分前から開発停止状態。Pi3 や Pi2 に非対応なのだとか。残念。

ただ、RPIO関係を調べていたら、pigpio なるものがあると知り。ServoBlasterと同様にデーモンとして動く仕組みで、コマンドラインでも使えるし、Pythonから呼ぶためのモジュールも用意されているらしい。

ということで、pigpio を試用してみる。 Raspberry Pi3 の場合は、最初からインストールされてるっぽいが、入ってない時はおそらく sudo apt-get install pigpio でインストールできるんじゃないか、という気がするけど自信無し。

デーモンの起動と殺し方。
sudo pigpiod
sudo killall pigpiod

ひとまず、コマンドラインから使ってみる。pigs というコマンドを使って、GPIOに色々送れるっぽい。

GPIO 18番にサーボモータが繋がってるものとして、1.45ms のパルス幅を送る例。
pigs SERVO 18 1450
オプション内容は、pigs SERVO GPIOピン番号 パルス幅(単位はマイクロ秒?)、だと思う。

パルス幅には、500 - 2500 の値を指定可能。つまり、0.5ms - 2.5ms の範囲で指定できる。

SERVO の記述は、s でも代替できる。以下は 0.5ms、2.4ms のパルス幅を送る例。
pigs s 18 500
pigs s 18 2400

サーボモータ用のパルスを切る例。
pigs s 18 0

詳細は _pigpio library を参照。

ところで、ServoBlaster を使った際は、最大値として 213 (2.13ms) までしか指定できなかったけど。pigpio (pigs) を使った場合は、2400 (2.4ms)まで指定できた。もしかするとPWMの精度に関して、ServoBlaster より pigpio のほうが高い、ということだろうか…。わからんけど。

pigpioを自動起動。 :

Raspberry Pi3起動時に、pigpio が自動で起動するようにしたい。以下のページにやり方が色々載っていた。一つは crontab を使う方法。他には、サービスとして登録できるようにする方法。

_Raspberry Pi - View topic - PIGPIO daemon

とりあえず、サービスとして登録できるやり方を試してみたり。

最初に、pigpiod の場所を ―― /usr/local/bin/以下にあるのか、/usr/bin/以下にあるのか、把握しておく。
which pigpiod

サービス起動用の雛形ファイルをコピー。
sudo cp /etc/init.d/skeleton /etc/init.d/pigpiod
sudo chmod 755 /etc/init.d/pigpiod

中身を編集
sudo vi /etc/init.d/pigpiod

/etc/init.d/pigpiod の中身は、上記のサイトからコピペ。ただし、Pi3 などでは、
DAEMON=/usr/local/bin/$NAME
の行は、
DAEMON=/usr/bin/$NAME
になる。かもしれない。

サービスとして登録。
sudo update-rc.d pigpiod defaults
sudo update-rc.d pigpiod enable

サービスの起動・終了ができるか確認してみる。
sudo service pigpiod start
sudo service pigpiod status
sudo service pigpiod stop
sudo service pigpiod status

参考ページ。 :

_サーボモーター(SG-90)を試す - Raspberry Pi 備忘録
_くたじんの鎌倉生活 RaspberryPiのPWM制御、周波数とデューティー比について
_Raspberrypi2 PWMでサーボモータを動かす | Myブーム & My備忘録
pwmSetClockの値の設定についてだが、調べたところ以下の条件式が成立するらしい。

- pwm周波数=raspiのPWMが持つベースクロック周波数/clock * range
- pwm周波数: 50Hz
- raspiのPWMが持つベースクロックの周波数: 19.2MHz
- range: 1024
- clock: pwmSetClockで設定する値

従ってclockを求める式は、clock = 19.2 x 10^6 / (pwm周波数 x 1024) となる。
故に、clock = 18750 / pwm周波数
ということは、50ms にしたいなら…。clock = 18750 / 50 = 375、なのかな。

#2 [nitijyou] 自転車で買い物に

門のチャイムが壊れたとのことで。親父さんが線を繋ぎ直しても鳴らないのだとか。どこかで断線したままなのだろうけど、断線箇所を見つけようにも…。線は壁の中を通ってるわけで…。てなわけで、ここはワイヤレスのチャイムを買って、ソレを設置しようという話に。

ということで、ホームセンターホーマックまで電動自転車で。以下を購入。 _電源タップ WHS2523JP は、Raspberry Pi3 の電源を取ってる位置をもっと伸ばしたくなったので購入してみたり。他にも電源を取りたくなるだろうから、スイッチ付・数個口のモノを。

ついでに、Seriaで以下を購入。
一応コンセントカバーは部屋に転がってるけど、小さいから引き抜くのが面倒で。その点今回購入したソレは比較的大きいので、引き抜く時に楽かなと。

セパレートボックスは、ブレッドボード用のジャンパーコードを入れるために購入したけど、長いコードは入らなかった。細長いケースが、どこかで売ってないものか…。筆記具を入れる時に便利だろうから、商品としてありそう、とは思うのだけど…。

REVEX X810のスペックについてメモ。 :

_リーベックス株式会社 Xシリーズカタログ
_X810・X800・X10共通 取扱説明書

送信機側の電源は、CR2032 x 2。受信機側は、単三電池 x 3。ただし受信機側は、5V 500mA のACアダプタがあれば、ACアダプタ駆動もできるらしい。

無線IDは、16段階のボリューム x 2 で設定する。16 x 16 = 256通りが選べるはず。他の御家庭と混線しないように選んでくれ、と説明書には書いてあった。

チャイム、音楽、効果音の種類は、16種類。なかなかイイ感じの音色が鳴る…。PSGっぽい音というか、ファミコンっぽい音というか…。

送信機側はネジを緩めないと裏蓋が外れない。防雨対策、なのかなと。

以上、1 日分です。

過去ログ表示

Prev - 2016/07 - Next
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project