Raspberry Piで使うカメラのパン・チルト制御用マウントの組み立て

th_pan_tilt_10

前回一応Raspberry Piで二つのサーボを動かせたので、それを発展させてパン-チルト対応のカメラを作ってみたいと思います。今回はそのためのマウントの作成です。

パン-チルトを可能にするマウントはこの2つを組み合わせるだけで出来上がりますが、その組み合わせるだけ、というのがなかなか厄介です。とりあえず、ニッパーと精密ドライバーは必須で、それ以外にあると良いものは以下です。

基本的にネジ穴が小さいし、また場合によっては新たにネジ穴を作ったりした方が楽なケースも多いので、1mm〜2mm程度の穴を開けられるドリルはあった方がよいです。

あと、こういうのもあるとなお良いです。

マウントについてくるネジは、安物なのかよくわかりませんが、とてもなめやすいです。穴を広げないまま無理やりネジを回すと、簡単にネジ山が潰れます。少し潰れたぐらいであればこれがあれば救済可能なので、一旦無理に回すのはやめて、ネジ穴を少し広げた方が安全です。

ではでは、作業に入ります。

th_pan_tilt_1

サーボに付属しているホーンは、長い方をニッパーとかでカットする必要があります。

th_pan_tilt_2

ホーンの各辺(?)にはそれぞれ2つずつ穴が開いている状態ですが、この状態でそれぞれ内側の穴に合わせて1mmドリルで下まで貫通する穴を開けておくと、

th_pan_tilt_3

こんな感じで、マウントに付属の一番小さいネジで固定できるようになります。左側のネジだけは、事前に穴を開けずに作業をしたせいでネジが進まなくなり、ネジ山が潰れてしまいました。

th_pan_tilt_4

続いて、サーボを挟む部品のネジ留めです。このまま力任せに締め込んでいくことも可能ですが、やはりネジ山が潰れる可能性が大なので、事前にちょっとだけ穴を広げておくのをオススメします。

th_pan_tilt_5

カメラマウント側にもサーボを取り付けます。これまた、穴を2mmぐらいまで広げないと止められません。また、サーボとマントの間にナットを一つ挟む形になるので注意です。

th_pan_tilt_6

それから、台の方にもサーボのホーンを短く切り落としたものをはめ込み、一番小さいネジでねじ止めします。はめ込むのにも結構力がいりました。

あとは、作ったプログラムでのサーボの初期位置を確認しながら、ホーンとモータを固定して、とりあえず完成です。

 

次はカメラの固定です。Raspberry Pi専用のカメラモジュールはラピロが使ってしまっているので、手持ちの別のWebカメラを使ってみます。

これのブラックバージョンです。

th_pan_tilt_7

。。。ちょっとデカイですが、まあ頑張ってくっつけてみましょう。

最初は後ろ側から穴を開けてねじ止めしてみたのですが、微妙に歪んでしまったので、

th_pan-tilt-10

改めて両サイドから穴を開けてネジ止めしました。エイヤでカメラ本体まで穴あけしてしまいましたが、後から中を開けてみると、この部分は予想どおり空洞だったので安心しました。

th_pan-tilt-12

最後に、適当なケースに穴を開けて、本体を固定しました。ただ、このままだとカメラを動かしたときに土台が動いてしまうので、ケースの中に重石をいれるか、ケースをしっかり固定するかしないといけません。

この状態で、前回作成したプログラムでWebIOPi経由で動かしてみたところ、最初に作ったコードだと右と左、上と下が見事に逆に動いてしまったので、Pythonのコードを次のように修正しました。

import webiopi

GPIO = webiopi.GPIO
SERVO_PAN  = 23
SERVO_TILT = 24

DEFAULT_PAN  = 0
DEFAULT_TILT = 0
CURRENT_PAN  = 0
CURRENT_TILT = 0

PAN_MAX  = 90
PAN_MIN  = -90
TILT_MAX = 90
TILT_MIN = -90

PAN_UNIT  = 10
TILT_UNIT = 10

def setup():
  GPIO.setFunction(SERVO_PAN,  GPIO.PWM)
  GPIO.setFunction(SERVO_TILT, GPIO.PWM)
  GPIO.pulseAngle(SERVO_PAN,  DEFAULT_PAN)
  GPIO.pulseAngle(SERVO_TILT, DEFAULT_TILT)
  webiopi.sleep(0.5)
  GPIO.pulseRatio(SERVO_PAN,  0)
  GPIO.pulseRatio(SERVO_TILT, 0)

def loop():
  webiopi.sleep(0.5)

@webiopi.macro
def defaultPosition():
  global CURRENT_PAN
  global CURRENT_TILT
  CURRENT_PAN  = DEFAULT_PAN
  CURRENT_TILT = DEFAULT_TILT
  GPIO.pulseRatio(SERVO_PAN,  0)
  GPIO.pulseRatio(SERVO_TILT, 0)
  GPIO.pulseAngle(SERVO_PAN,  DEFAULT_PAN)
  GPIO.pulseAngle(SERVO_TILT, DEFAULT_TILT)
  webiopi.sleep(0.5)
  GPIO.pulseRatio(SERVO_PAN,  0)
  GPIO.pulseRatio(SERVO_TILT, 0)

@webiopi.macro
def right():
  global CURRENT_PAN
  if CURRENT_PAN > PAN_MIN:
    CURRENT_PAN = CURRENT_PAN - PAN_UNIT
    GPIO.pulseRatio(SERVO_PAN, 1)
    GPIO.pulseAngle(SERVO_PAN, CURRENT_PAN)
    webiopi.sleep(0.5)
    GPIO.pulseRatio(SERVO_PAN, 0)

@webiopi.macro
def left():
  global CURRENT_PAN
  if CURRENT_PAN < PAN_MAX:
    GPIO.pulseRatio(SERVO_PAN, 1)
    CURRENT_PAN = CURRENT_PAN + PAN_UNIT
    GPIO.pulseAngle(SERVO_PAN, CURRENT_PAN)
    webiopi.sleep(0.5)
    GPIO.pulseRatio(SERVO_PAN, 0)

@webiopi.macro
def up():
  global CURRENT_TILT
  if CURRENT_TILT > TILT_MIN:
    GPIO.pulseRatio(SERVO_TILT, 1)
    CURRENT_TILT = CURRENT_TILT - TILT_UNIT
    GPIO.pulseAngle(SERVO_TILT, CURRENT_TILT)
    webiopi.sleep(0.5)
    GPIO.pulseRatio(SERVO_TILT, 0)

@webiopi.macro
def down():
  global CURRENT_TILT
  if CURRENT_TILT < TILT_MAX:
    GPIO.pulseRatio(SERVO_TILT, 1)
    CURRENT_TILT = CURRENT_TILT + TILT_UNIT
    GPIO.pulseAngle(SERVO_TILT, CURRENT_TILT)
    webiopi.sleep(0.5)
    GPIO.pulseRatio(SERVO_TILT, 0)

def destroy():
  GPIO.setup(SERVO_PAN,  GPIO.IN)
  GPIO.setup(SERVO_TILT, GPIO.IN)

この状態でブラウザから操作してみると、図体はデカイですがパン-チルトは一応機能します。カメラ部分は図体はデカイですが、空洞が多くて軽いのです。

ただ、今の所、動かすたびにサーボがガタガタ震えてしまい、とても落ち着きのない子になってしまっています。このままでは使いものにならないので、次回はもっとキビキビとサーボが動くように、プログラムを修正します。