スマホからパン・チルトをコントロールしてカメラ画像を得るのにArduinoでは少し重いと感じたので、Rspberry Piを使ってみました。
2018/8/15 PCA9685(モータードライバー)を使用しない方法も試し、末尾に追記しました。
パン・チルトカメラに使用した部材(写真の赤枠)
- Raspberry Pi Zero W (スイッチサイエンス ¥1,296)
- KKHMF PCA9685 16チャンネル 12-ビット PWM Servo モーター ドライバー (Amazon ¥494)
- PTZ(NOサーボ) カメラマウント(Amazon ¥396)
- サーボ SG90 2個 (既存)
- OV5647カメラモジュール・ケーブル付き (Amazon ¥1,321)
緑枠のモジュールは以前より使用しているリアルタイムクロック、降圧電源、OFFスイッチ、イーサネットで、パン・チルトカメラとは直接関係しません。
参考URL:https://learn.sparkfun.com/tutorials/setting-up-the-pi-zero-wireless-pan-tilt-camera
参考URLの通りにリモートカメラを設定していけば、とりあえずの動きが確認できますが、サーボドライバの周波数設定が200Hzと高いためサーボが追従しきれず電流が流れっ放しで唸ってしまいました。
ドライバーに使用しているPCA9685のデータシートの計算式によると、サーボ周波数を50Hzに変更するためには、プリスケール値を0x7a、パルス幅の設定値は 1.5msecにする場合 1.5msec/(20msec/4096)=307 になります。
PCA9685の使い方:https://rtc-fukushima.jp/wp/wp-content/uploads/2017/11/20171214_joukyuu_1.pdf
ここで、サーボドライバの設定値が記述されているファイルを編集しました。
File: /home/pi/RPi_PanTilt_Cam/pantilt.py
周波数設定が計算通りにはいかず、パルス幅のスケーリングも必要だったので以下のように修正しました。(スケーリングの値は適当です)
#!/usr/bin/env python
import smbus
import time
bus = smbus.SMBus(1)
addr = 0x40
def scale(x, in_min, in_max, out_min, out_max):
return (x – in_min)*(out_max – out_min)/(in_max – in_min) + out_min
## set frequency 50Hz
bus.write_byte_data(addr, 0, 0x10)
bus.write_byte_data(addr, 0xfe, 0x88)
bus.write_byte_data(addr, 0, 0)
## enable the PC9685 and enable autoincrement
bus.write_byte_data(addr, 0, 0x20)
bus.write_byte_data(addr, 0xfe, 0x1e)
bus.write_word_data(addr, 0x06, 0)
## set PAN plus width 1.5ms at 50Hz
## bus.write_word_data(addr, 0x08, 1250)
bus.write_word_data(addr, 0x08, 307)
bus.write_word_data(addr, 0x0a, 0)
## set TILT plus width 1.5ms at 50Hz
## bus.write_word_data(addr, 0x0c, 1250)
bus.write_word_data(addr, 0x0c, 307)
while True:
pipein = open(“/var/www/html/FIFO_pipan”, ‘r’)
line = pipein.readline()
line_array = line.split(‘ ‘)
if line_array[0] == “servo”:
## set PAN and TILT moving scale at 50Hz
## pan_setting = scale(int(line_array[1]), 80, 220, 833, 1667)
## tilt_setting = scale(int(line_array[2]), 50, 250, 833, 1667)
pan_setting = scale(int(line_array[1]), 80, 220, 220, 400)
tilt_setting = scale(int(line_array[2]), 50, 250, 220, 400)
bus.write_word_data(addr, 0x08, pan_setting)
bus.write_word_data(addr, 0x0c, tilt_setting)
pipein.close()
この設定で再起動した後のサーボドライバ出力波形です。
WiFiアクセスポイントモードの設定については次のURLを参考に設定しました。
2018/8/15追記
RPi-Cam-Web-InterfaceのサイトにServoblasterでの使用方法が書かれていましたので試してみました。サーボは1個づつしか動かさないので電源モジュールも外してシンプルな構成のリモートカメラになりました。
pipanからservoに切り替え
/var/www/htmlフォルダ 2つのファイルの名前(末尾のon/off)を変更
pi@raspberrypi:~ $ cd /var/www/html
pi@raspberrypi:/var/www/html $ mv pipan_on pipan_off
pi@raspberrypi:/var/www/html $ mv servo_off servo_on
pi@raspberrypi:/var/www/html $ cd
Servoblasterのインストール
pi@raspberrypi:~ $ git clone https://github.com/richardghirst/PiBits.git
Cloning into ‘PiBits’…
remote: Counting objects: 380, done.
remote: Total 380 (delta 0), reused 0 (delta 0), pack-reused 380
Receiving objects: 100% (380/380), 399.69 KiB | 261.00 KiB/s, done.
Resolving deltas: 100% (167/167), done.
pi@raspberrypi:~ $ cd PiBits/ServoBlaster/user/
pi@raspberrypi:~/PiBits/ServoBlaster/user $ make servod
gcc -Wall -g -O2 -L/opt/vc/lib -I/opt/vc/include -o servod servod.c mailbox.c -lm -lbcm_host
pi@raspberrypi:~/PiBits/ServoBlaster/user $ sudo make install
[ “`id -u`” = “0” ] || { echo “Must be run as root”; exit 1; }
cp -f servod /usr/local/sbin
cp -f init-script /etc/init.d/servoblaster
chmod 755 /etc/init.d/servoblaster
update-rc.d servoblaster defaults 92 08
/etc/init.d/servoblaster start
pi@raspberrypi:~/PiBits/ServoBlaster/user $ sudo ./servod
Board model: 2
GPIO configuration: P1 (40 pins)
Using hardware: PWM
Using DMA channel: 14
Idle timeout: Disabled
Number of servos: 8
Servo cycle time: 20000us
Pulse increment step size: 10us
Minimum width value: 50 (500us)
Maximum width value: 250 (2500us)
Output levels: Normal
Using P1 pins: 7,11,12,13,15,16,18,22
Servo mapping:
0 on P1-7 GPIO-4
1 on P1-11 GPIO-17
2 on P1-12 GPIO-18
3 on P1-13 GPIO-27
4 on P1-15 GPIO-22
5 on P1-16 GPIO-23
6 on P1-18 GPIO-24
7 on P1-22 GPIO-25
pi@raspberrypi:~/PiBits/ServoBlaster/user $
再起動
/var/www/html/servo_onファイルを変更してサーボの動作範囲を調整
初期値:{“x”:158,”y”:186,”left”:”Xplus”,”right”:”Xminus”,”up”:”Yminus”,”down”:”Yplus”,”XMax”:235,”XMin”:95,”XStep”:7,”YMax”:235,”YMin”:95,”YStep”:7}
変更後:
{“x”:150,”y”:150,”left”:”Xplus”,”right”:”Xminus”,”up”:”Yminus”,”down”:”Yplus”,”XMax”:220,”XMin”:80,”XStep”:7,”YMax”:200,”YMin”:100,”YStep”:5}
サーボの周波数設定も初期値が20msec(50Hz)でしたので、これだけの設定で一応安定に動作しました。