ラズパイ WiringPi 連続回転サーボ


20160505_raspi_servo

LED明暗 に続いて、ラズパイで WiringPi を使って、連続回転サーボを制御します。
LED明暗と同様に、ハードウェア PWM を使います。

設定
設定には、5つの関数を使用します。
それぞれ、ラズパイの BCM2835 / BCM2836 のレジスタと関連しています。

pinMode
pin のモードとして、PWM_OUTPUT を設定します。
これを最初に設定しないと、以降の関数が効かなかったです。

pwmSetMode
PWMのモードを設定します。
PWM には、2つのモードがあります。
バランスド (balanced) と マーク・スペース (mark:space) です。
スペースは周期で、マークはパルス幅です。
バランスドは、デューティ比 50% です。
20160530_wiringpi_pwm_mode

サーボに必要なのは、下記のような信号なので、マーク・スペースに設定します。
20160425_servo_control_2

pwmSetClock
クロックの分周比を設定します。
PWMのクロックは、19.2 MHz です。
サーボでは、パルス幅 ±0.5ms で制御します。
制御の刻みを 100 とすると、分周比は 96 です。
0.5ms / 100 = 5μs (200 KHz)
19.2 MHz / 200 KHz = 96

pwmSetRange
PWMの周期となるクロック数を設定します。
サーボのパルス周期は、20ms なので、クロック数は 400 です。
20ms / 5μs = 4000

pwmWrite
パルス幅となるクロック数を設定します。
1.5ms のときは、300 です。
1.5ms / 5μs = 300

動作確認
サーボには3本の線があります。
赤を Pin4 (+5v)、黒を Pin6 (GND)、白を Pin12 (GPIO18) に接続します。

wiringpi_servo_pulse.py (github)
パルス幅のクロック数 を 200、290、300、310、400 と変化させて、
時計周り(高速)、時計周り(低速)、停止、反時計周り(低速)、 反時計周り(高速) となることを確認します。

wiringpi_servo_speed.py (github)
パルス幅で指定するのは使い難いので、速度で指定するようにしました。
速度の範囲は、−100 から 100 です。

オシロでの測定
周期 20ms、パルス幅 1.5ms となっています。
RPi.GPIO では、ジッタ が見られましたが、今回は綺麗です。

周期 20ms
20160530_wiringpi_pwm_20ms

パルス幅 1.5ms
20160530_wiringpi_pwm_1_5ms

参考
Raspberry Pi Specifics – Wiring Pi
・void pinMode (int pin, int mode)
pin に対して、mode として、INPUT、 OUTPUT、 PWM_OUTPUT、または GPIO_CLOCK のいずれかを設定します。

・pwmSetMode (int mode)
PWMジェネレータは、 2つのモードで実行することができます。
バランスド (balanced) と マーク・スペース (mark:space) です。
マーク・スペースが伝統的な方式ですが、ラズパイのデフォルトのモードはバランスドです。
mode にパラメータを設定することで、モードを切り替えることができます。
PWM_MODE_BAL か PWM_MODE_MS です。

・pwmSetRange (unsigned int range)
PWMジェネレータ内のレンジ・レジスタを設定します。
デフォルトは1024です。

・pwmSetClock (int divisor)
PWMクロックの分周比を設定します。

・void pwmWrite (int pin, int value)
指定されたピンのPWMレジスタに値を書き込みます。

Control Hardware PWM frequency – Raspberry Pi
PWMクロックは19.2 MHz です。
pwmSetClock の値で分周されます。
分周された周波数で、PWMカウンタが増加します。


ラズパイ WiringPi LED明暗


20160510_raspi_led

LED点滅 に続いて、ラズパイで WiringPi を使ってLEDを徐々に明くしたり暗くしたりします。

WiringPi では、ハードウェア PWM が使えます。
ラズパイ2では、2チャネルあり、1つは P32 (GPIO12) か P12 (GPIO18)、もう1つは P33 (GPIO13) か P35 (GPIO19) です。

P12(GPIO18) と P6(GND) の間に、LEDと1KΩの抵抗を直列に入れます。
20160510_raspi_led_gpio17

wiringpi_led_fade.py

import wiringpi
import time
PIN = 18 
INTERVAL = 0.05
MIN_BRIGHTNESS = 0
MAX_BRIGHTNESS = 1023
bright = 0
amount = 16
wiringpi.wiringPiSetupGpio()
wiringpi.pinMode(PIN, wiringpi.PWM_OUTPUT)
try:
	# endless loop
	while True:
		print bright
		wiringpi.pwmWrite(PIN, bright)
		bright = bright + amount;
		if bright <= MIN_BRIGHTNESS:
			bright = MIN_BRIGHTNESS
			amount = -amount
		elif bright >= MAX_BRIGHTNESS:
			bright = MAX_BRIGHTNESS
			amount = -amount
		time.sleep(INTERVAL)
except KeyboardInterrupt:
	# exit the loop, if key interrupt
	pass

参考
Core Functions – Wiring Pi
・void pinMode (int pin, int mode)
pin に対して、mode として、INPUT、 OUTPUT、 PWM_OUTPUT、または GPIO_CLOCK のいずれかを設定します。
PWM_OUTPUT は、WiringPi 1ピン (BCM_GPIO 18) のみサポートされています。
GPIO_CLOCK は、WiringPi 7ピン (BCM_GPIO 4) のみサポートされています。

・void pwmWrite (int pin, int value) ;
指定されたピンのPWMレジスタに値を書き込みます。
ラズパイ1はオンボードPWMピンを1つ持っています。
Wiring Pi 1ピン (BMC_GPIO 18、物理ピン12) です。
value の範囲は0〜1024です。
他のPWMデバイスは、他のPWM範囲を有することができます。

Raspberry Piで学ぶ電子工作
wiringPiを用いたハードウェアPWM信号によるサーボモーターの制御
Raspberry Pi Model B ではハードウェアPWM信号はGPIO 18からの1つのみしか出力できなかったのですが、Raspberry Pi Model B+以降(Raspberry Pi 2 Model B含む)では、ハードウェアPWM信号を2つ出力できます。
1つ目のPWM0はGPIO 18かGPIO 12のどちらかから、2つ目のPWM1はGPIO 13かGPIO 19のどちらかから出力できます。


ラズパイ WiringPi LED点滅


20160510_raspi_led

ラズパイで WiringPi を使ってLEDを点滅する。
ラズパイの GPIO 制御は RPI.GPIO が定番ですが。
今回は WiringPi を使います。

WiringPi はラズパイ1の BCM2835 のために、C言語で書かれた GPIO のライブラリです。
適切なラッパーにより Python などの言語に対応しています。
Arduino のライブラリに似せて設計されています。
ラズパイ2の BCM2836 にも対応しています。

インストール

(Python 開発ライブラリ)
$ sudo apt-get install python-dev
(WiringPi 本体)
$ sudo apt-get install wiringpi
(Python ラッパー)
$ sudo pip install wiringpi2

確認
バージョンの確認

$ gpio -v

gpio version: 2.32

WiringPi のピン番号には、(1) 物理ピン (2) BCM GPIO ピン (3) wiringPi ピンの3種類があり、ちと面倒です。
デフォルトは wiringPi ピンです。
このへんの対応は、下記のコマンドで表示できます。

$ gpio readall

20160525_wiringpi_readall

gpio コマンドでLED点滅
11番ピン(GPIO 17、wPi 0)と6番ピン(GND)の間に、LEDと1KΩの抵抗を直列に入れます。
20160510_raspi_led_gpio17

$ gpio mode 0 out
(点灯)
$ gpio write 0 1
(消灯)
$ gpio write 0 0

Python でLED点滅 (1)

$ sudo python
>> import wiringpi
>> wiringpi.wiringPiSetup()
>> wiringpi.pinMode(0, wiringpi.OUTPUT)
(点灯)
>> wiringpi.digitalWrite(0, wiringpi.HIGH)
(消灯)
>> wiringpi.digitalWrite(0, wiringpi.LOW)
>>> exit()

Python LED点滅 (2)
1秒間隔で点滅する
wiringpi_led_blink.py

import wiringpi
import time
wiringpi.wiringPiSetupGpio()
wiringpi.pinMode(17, wiringpi.OUTPUT)
while True:
	wiringpi.digitalWrite(17, wiringpi.HIGH)                 
	time.sleep(1)
	wiringpi.digitalWrite(17, wiringpi.LOW)            
	time.sleep(1)

参考
Setup – Wiring Pi
・wiringPiSetup (void)
WiringPi 方式のピン番号を使用して、WiringPi を初期化します。
これは、Broadcom の GPIO のピン番号 16 に対して、仮想のピン番号 0 をマッピングする方式です。
この関数は、 root権限で呼び出す必要があります。

・wiringPiSetupGpio (void)
Broadcom の GPIO のピン番号を使用して、WiringPi を初期化します。
この関数は、 root権限で呼び出す必要があります。

Core Functions – Wiring Pi
・void pinMode (int pin, int mode)
pin に対して、mode として、INPUT、 OUTPUT、 PWM_OUTPUT、または GPIO_CLOCK のいずれかを設定します。
PWM_OUTPUT は、WiringPi 1ピン (BCM_GPIO 18) のみサポートされています。
GPIO_CLOCK は、WiringPi 7ピン (BCM_GPIO 4) のみサポートされています。

・void digitalWrite (int pin, int value)
pin は OUTPUT として設定されている必要があります
pin に value として、HIGH (1) または LOW (0) の値を書き込みます。
WiringPi では、0(ゼロ) は LOW となり、0(ゼロ) 以外の数値は HIGH として扱います。


ラズパイで weaved を試す (web)


weaved は、ラズパイなどの小型コンピュータボードを IoT化するためのサービスです。

ラズパイでは下記のインターネット・ポートを利用できます。
– SSH on port 22
– Web (http) on port 80
– VNC on port 5901
– A custom TCP service on your port of choice

ラズパイで weaved を試す (ssh) に続いて、Web (http) on port 80 を試してみます。

技術的には ポートフォワード を使っているものと思われます。

設定
ssh と同じです。
Protocol Selection Menu で 2 を選択します。

$ sudo weavedinstaller

*********** Protocol Selection Menu ***********                                         
*    1) SSH on default port 22                
*    2) Web (HTTP) on default port 80         
*    3) VNC on default port 5901              
*    4) Custom (TCP)                          
*    5) Return to previous menu               
***********************************************
Please select from the above options (1-5): <== 2

動作確認
ssh とほぼ同じです。
(1) 利用可能なサービスの一覧から、サービス名をクリックします。
20160520_weaved_web_service_list

(2) web 画面が表示されれば、OKです。
この例では、OctoPrint を表示しています。
20160520_weaved_web_pi


ラズパイで weaved を試す (ssh)


weaved は、ラズパイなどの小型コンピュータボードを IoT化するためのサービスです。
インターネット上のサーバーから、ローカルネット内のラズパイにアクセスすることができます。
ラズパイの他には、BeagleBone Black や Intel Edison などに対応しています。
有償のサービスですが、無料で利用できるプランも用意されています。

ラズパイでは下記のインターネット・ポートを利用できます。
– SSH on port 22
– Web (http) on port 80
– VNC on port 5901
– A custom TCP service on your port of choice
Installation Instructions for Raspberry Pi

技術的には ポートフォワード を使っているものと思われます。

アカウントの取得
weaved のサイト にて、メールアドレスとパスワードを登録します。

インストール
(1) ラズパイにログインする
(2) weaved をインストールする

$ sudo apt-get update
$ sudo apt-get install weavedconnectd

設定

$ sudo weavedinstaller

Please enter your Weaved Username (email address): <== メールアドレス
Please enter your password: <== パスワード

********************** Main Menu ************************                                                    
*       1) Attach/reinstall Weaved to a Service         
*       2) Remove Weaved attachment from a Service      
*       3) Exit                                         
*********************************************************
Please select from the above options (1-3): <== 1

*********** Protocol Selection Menu ***********                                         
*    1) SSH on default port 22                
*    2) Web (HTTP) on default port 80         
*    3) VNC on default port 5901              
*    4) Custom (TCP)                          
*    5) Return to previous menu               
***********************************************
Please select from the above options (1-5): <== 1

You have selected: 1. 
Would you like to continue with the default port assignment? [y/n]  <== y

Enter a name for this Service Attachment (e.g. SSH-Pi). 
This name will be shown in your Weaved Device List.
<== ssh-pi

(下記のように一覧に表示されます)
Protocol	Port	Service		Weaved Name
=================================
SSH		22	sshd       	ssh-pi

********************** Main Menu ************************                                                    
*       1) Attach/reinstall Weaved to a Service         
*       2) Remove Weaved attachment from a Service      
*       3) Exit                                         
*********************************************************
Please select from the above options (1-3): <== 3

動作確認
(1) weaved のサイトに、ログインします。
(2) 利用可能なサービスの一覧が表示されます。上記で設定した ssh−pi が表示されれば、OKです。
20160520_weaved_service_list

(3) サービス名の ssh−pi をクリックします。
(4) ssh の情報が表示されます。
20160520_weaved_ssh

(5) MACにて、下記のように ssh コマンドを実行します。

$ ssh -l pi *** -p 30493

(6) ターミナルに、ログイン画面が表示されれば、OKです。
20160520_weaved_ssh_login

参考
Installation Instructions for Raspberry Pi – weaved
ACCESS YOUR RASPBERRY PI OVER THE INTERNET – raspberrypi.org
Raspberry Piの設定【Weaved – IoT Kit による外部ネットークからのSSH接続】
ルーターを超えてリモートホストに接続できる Weaved を使って Raspberry Pi、Intel Edison を IoT エッジにする方法


Linux: ポートフォワード (web)


ポートフォワード ssh に引き続いて、web のポートフォワードを設定します。
ポートフォワードは、本来はポート22の ssh 用ですが、ポートやプロトコルに関係なく、何でも転送できます。

ラズパイの設定
リモートホストのポート 10080 をラズパイの http ポート 80 に接続します。

$ autossh -M 0 -N -f -R 10080:127.0.0.1:80 foobar@example.com

ブート時にコマンドを実行するには、
テンプレート を元に /etc/init.d/autossh を作成します。

$ sudo chmod 755 /etc/init.d/autossh

パソコンから
WEBブラウザから、リモートホストを経由して、ラズパイに接続します。

http://example.com:10080

ラズパイのWEB画面が表示されれば、OKです。


Linux: ポートフォワード (autossh )


ポートフォワード ssh に続いて、ポートフォワードを設定します。
前回の設定では、不便なことがあります。
(1) いったんリモートホストにログインしてから、ラズパイにログインするという、2段階になる。
(2) 毎回ラズパイから手動で設定する必要がある。

リモートホストの設定
(1) ポートフォワード用のユーザを設定します。

# useradd -m foobar
# passwd foobar

(2) 直接 ラズパイにログインできるようにする
/etc/ssh/sshd_config を編集して、GatewayPorts yes にします。

# vi /etc/ssh/sshd_config

#GatewayPorts  no
GatewayPorts  yes

sshd を再起動する

# /etc/init.d/sshd restart

ラズパイの設定
(1) ユーザ
リモートホストと同様に、ポートフォワード用のユーザを設定した方が望ましいのですが。
今回は、用途が限定されているので、デフォルトの pi を使います。

(2) パスフレーズなしの暗号鍵を作る

$ ssh-keygen -t rsa

Enter file in which to save the key (/home/pi/.ssh/id_rsa): <== このままリターン
Enter passphrase (empty for no passphrase):  <== このままリターン
Enter same passphrase again:  <== このままリターン

(3) 暗号鍵をリモートホストに転送する

$ ssh-copy-id -i ~/.ssh/id_rsa.pub foobar@example.com 

(4) ssh セッションの監視をする
.ssh/config を作成して、30秒毎にアライブを送って、3回でタイムアウトするようにします。

$ cd ~/.ssh/
$ vi config

ServerAliveInterval   30
ServerAliveCountMax   3

(5) autossh をインストールする
ssh は、いったんセッションが切れると、終了します。
autossh は、自動的にセッションをつなぎ直します。

$ sudo apt-get install autossh

(6) リモートホストに接続する

$ autossh -M 0 -N -f -R 10022:127.0.0.1:22 foobar@example.com 

パソコンから
リモートホストを経由して、ラズパイにログインします。
ホスト名はリモートホスト (example.com) ですが、ユーザ名はラズパイ (pi) です。
前回は、いったんリモートホストにログインしてから、ラズパイにログインするという、2段階になりましたが。
今回は、リモートホストに接続すると、そのままラズパイに転送され、ラズパイのログイン画面になります。

$ ssh pi@example.com -p 10022

pi@example.com's password: <== ラズパイのパスワード(raspberry)
pi@rapberrypi ~ $ 

ログイン出来れば、OK

ラズパイの設定
ブート時に自動的にコマンドを実行するようにします。
テンプレート を元に /etc/init.d/autossh を作成します。

$ sudo chmod 755 /etc/init.d/autossh
$ sudo insserv autossh

これで、電源投入時、あるいはリブート時に、自動的にラズパイからリモートホストに接続します。

参考
autossh
Automatically restart SSH sessions and tunnels

SSHD_CONFIG – 日本語マニュアルページ
GatewayPorts (ポート中継の許可)
リモートホストがクライアント側に転送されたポートに接続することを許可するかどうか指定します。
いかなるアドレスからも利用可能にしたい場合は”yes”に。

SSH_CONFIG – 日本語マニュアルページ
ServerAliveInterval (サーバ生存確認の間隔)
一定期間サーバからデータが送られてこないときに、タイムアウトする秒数を設定します。

ServerAliveCountMax (サーバ生存カウント最大値)
ssh がサーバからの返答を確認するまでに、サーバ生存確認メッセージ を何回まで送るかを指定します。

ssh – 日本語マニュアルページ
-f
ssh がコマンドを実行する直前に、バックグラウンドに移行するよう指示します。

-N
リモートコマンドを実行しません。これはポート転送のみをおこないたい場合に便利です。

-p ポート
リモートホストに接続するポートを指定します。


Linux: ポートフォワード (ssh)


ポートフォワード (port forward) とは、ローカルコンピュータの特定のポートに送られてきたデータを、別に用意した通信経路を用いてリモートコンピュータの特定ポートに送信する技術手法です。
インターネット上のサーバー(リモートホスト)から、ローカルネット内のコンピュータにアクセスすることができます。

リモートホストを example.com、ユーザ名を user とします。
今回は、ローカルネット内のコンピュータとして、Raspberry Pi (以下、ラズパイと称す) を使用します。
デフォルトのユーザ名は pi で、パスワードは raspberry です。

ラズパイの設定
リモートホストのポート 10022 をラズパイの ssh ポート 22 に接続します。
直接 ラズパイにログインします。

$ ssh pi@rapberrypi.local

ラズパイにログインしたら、リモートホストに接続します。

$ ssh user@example.com -R 10022:127.0.0.1:22 

user@example.com's password: <== リモートのパスワード
~ $ 

プロンプトが表示されたら、そのままにします。

リモートホストの設定
リモートホストにログインする

$ ssh user@example.com 

リモートホストにログインしたら、ラズパイにログインする

$ ssh pi@localhost -p 10022 

pi@localhost's password: <== ラズパイのパスワード(raspberry)
pi@rapberrypi ~ $ 

ログイン出来れば、OK

参考
ssh – 日本語マニュアルページ
-p ポート
リモートホストに接続するポートを指定します。

-R リモートポート:リモートホスト:ホスト側ポート
与えられたリモートホスト上のポートが、与えられたローカルホスト上のポートに転送されるよう指定します。リモート→ローカルのポート転送。


ラズパイ ブート時にコマンドを実行する ( .bashrc )


ラズパイ(Linux)で、ブート時にコマンドを実行するには、大きく3つ方法があります。
1. サービスデーモンを記述する
2. /etc/rc.local に記述する
3. ユーザ毎の .bashrc を記述する

今回は、3. ユーザ毎の .bashrc を記述する 方法です。

注意
ブート時以外にも、ログインすると、実行されます。
複数回実行されると、不都合なものには、適しません。

/etc/inittab を編集して、ブート時に特定のユーザ (pi) にログインするようにします。

$ sudo nano /etc/inittab

(この行をコメントにして)
# 1:2345:respawn:/sbin/getty --noclear 38400 tty1
(この行を追加する)
1:2345:respawn:/bin/login -f pi tty1 </dev/tty1>/dev/tty1 2>&1

.bashrc を編集して、ログイン時に特定にコマンドを実行するようにします。

$ cd ~
$ nano  .bashrc
(一番最後に実行するコマンドを記述する)
*** &

これで、電源投入時、あるいはリブート時に、特定のコマンドを実行します。

参考
.BASHRC AND .BASH_ALIASES – raspberrypi
ドットファイル


ラズパイ pip


ラズパイで pip コマンドで pip 自身を更新しても、バージョンが変わらない。

現象
更新前

$ pip -V
pip 1.5.6 from /usr/lib/python2.7/dist-packages (python 2.7)

更新

$ sudo pip install --upgrade pip
Downloading pip-8.1.1-py2.py3-none-any.whl (1.2MB): 1.2MB downloaded

更新後
あれっ! 変わらないぞ。

$ pip -V
pip 1.5.6 from /usr/lib/python2.7/dist-packages (python 2.7)

対応
実は pip は2つインストールされてます。

$ which pip
/usr/bin/pip /usr/local/bin/pip

(1) /usr/bin/pip は apt-get でインストールされたもの

$ dpkg -S /usr/bin/pip
python-pip: /usr/bin/pip

$ dpkg -L python-pip
/usr/lib/python2.7/dist-packages/pip
/usr/bin/pip

(2) /usr/local/bin/pip は今回の更新でインストールされたもの

python-pip を削除します。

$ sudo apt-get remove python-pip
Removing python-pip (1.5.6-5) ...

無事、新しいバージョンが表示されました。

$ pip -V
pip 8.1.1 from /usr/local/lib/python2.7/dist-packages (python 2.7)