Raspberry Piとは、ラズベリーパイ財団が英国で開発したARMプロセッサを搭載したシングルボードコンピューターです。
Raspberry Piは組込みボードサイズにも関わらず、ARM用の通常のLinux (Debian、Fedora、Arch Linux)やFreeBSDが動作し、ボード上でセルフコンパイルも行えるため大変使いやすいです。 ディスクも現在は安価で大容量なSDカードを利用でき、本体価格も3000円程度と非常に安価です。 また、基本的なI/Oが提供されており、外部のいろいろなデバイスとも接続できるため、ロボット制御やセンサーによる計測など、いろいろな応用が考えられます。
Raspberry Piの外観を以下に示します。
Raspberry Piには3つの基本タイプ(Model A、Model B、Model Zero)があり、また基本タイプごとに複数のモデルがあります。詳細については下記Wikipediaのリンクなどを参照してください。
以下に代表的なモデルの仕様を表示します。
仕様 | |||
3 Model B | 3 Model B+ | 4 Model B (4G) | |
ターゲット価格 | $35 | $35 | $55 |
SoC | Broadcom BCM2837 | Broadcom BCM2837B0 | Broadcom BCM2711 |
CPU | ARM Cortex-A53 1.2GHz | ARM Coretex-A53 1.4GHz | ARM Coretex-A72 1.5GHz |
GPU | Broadcom VideoCore IV | Broadcom VideoCore VI | |
メモリ(SDRAM) | 1GB(GPU共有) | 4GB(GPU共有) | |
USB 2.0ポート | 4(統合USBハブ) | 4 | 2 |
USB 3.0ポート | - | 2 | |
映像出力 | コンポジット RCA(PAL&NTSC)、HDMI(rev 1.3 & 1.4)、MIPI DSI | コンポジットRCA(PAL/NTSC)、micro-HDMI(up to 4kp60) 2.0 x 2、MIPI DSI | |
音声出力 | 3.5 mm ジャック、I2S、HDMI | 3.5 mmジャック、I2S、micro HDMI | |
ストレージ | SDメモリーカード/MMC/SDIOカードスロット | ||
ネットワーク | 10/100 Mbpsイーサネット(RJ45) | Gigabit Ethernet over USB 2.0 (maximum throughput 300Mbps) (RJ45) | Gigabit Ethernet (RJ45) |
低レベル周辺機器 | 8 × GPIO、UART、I2C、SPIと2つのチップセレクト、+3.3V、+5V、接地 | ||
電源 | 2.5A(12.5W) | 3A(15 W) | |
電源ソース | 5V/microUSBまたはGPIO | 5V/USB Type-CまたはGPIO | |
大きさ | 85.0mm × 56.5mm | 85.0mm x 56.0mm |
より詳しくは上記Wikiなどを参照してください。
産総研が開発したI/O拡張基盤PiRT-Unitを利用すれば、比較的簡単にI/Oを利用することが可能です。
OpenRTM-aist(C++、Python、Java)もボード上でコンパイル・実行可能ですので、組込みボードでありながら、通常のLinux PC上での開発プロセスとほぼ同様の使い方が可能です。
ここではOpenRTM-aistでRTコンポーネントを開発・実行するための環境構築方法、便利に使うためのノウハウ、移動ロボットの制御やI/Oの利用方法などを解説します。
ここでは、Raspberry Pi用 RTC(以下、RPI RTC)を動作させるための実行環境のインストールについて説明します。
なお、以下のインストール手順は、Windows 環境を前提としています。 Windows 環境以外をご使用の方は以下のサイトなどをご参照ください。
ここでは、Raspberry Pi オフィシャルサイトから OSイメージをダウンロードし、各種セットアップについて説明します。 Raspberry Pi上で OpenRTM を使用できるようにするまでの大まかな手順は以下の通りです。
なお、OpenRTM-aist のインストールや、Kobuki コンポーネントがすでにインストールされたイメージをこちらに用意していますので、以下の手順はスキップすることができます。
使用する SDカードは最低 2GB 必要ですが、実際の使用では 4GB以上が必要 になります。必ず4GB以上の SDカードを用意してください。
以下のサイトから、Raspberry Pi用 OS Raspbian “wheezy”をダウンロードします。 Raspbian は Debian ベースのRaspberryPi用 Linux ディストリビューションです。
ダウンロードしたファイル YYYY-MM-DD-wheezy-raspbian.zip を展開してください。 YYYY-MM-DD-wheezy-raspbian.img という2GB位のファイルが展開されているはずです。
$ ls -al total 4752840 drwxr-xr-x 4 n-ando staff 136 5 18 13:30 . drwxr-xr-x 9 n-ando staff 306 5 18 13:30 .. -rw-r--r-- 1 n-ando staff 1939865600 2 9 12:44 2013-02-09-wheezy-raspbian.img -rwxr-xr-x 1 n-ando staff 493587826 5 7 21:08 2013-02-09-wheezy-raspbian.zip
うまく展開できない場合、ダウンロードに失敗しファイルが壊れている可能性があります。壊れたファイルを削除して、再度ダウンロードしてみてください。
展開された yyyy-mm-dd-hweezy-raspbian.img はイメージファイルといい、Raspbian が起動するディスクの状態をディスクの最初から最後まで1バイトづつ抜き出したものです。 このファイルをSDカードに単純にコピーしても使用することはできません!!
以下に説明する方法で SDカードに書き込んでください。
Windows では Win32DiskImager というツールを使用することでイメージの書き込みができます。 以下のサイトからイメージデータ書き込みツール Win32DiskImager のバイナリをダウンロードします。
ダウンロードしたファイル (win32diskimager-vX.X-binary.zip ) を解凍します。
※Win32DiskImager は、2バイト文字に対応していないため、YYYY-MM-DD-wheezy-raspbian.zip は途中のパス名に全角文字や空白が含まれていない場所に解凍してください。
Raspberry Pi で使用する SDカードをPCに挿入し、Win32DiskImager を起動します。
※SDカードはドライブとして認識されている必要があるので、事前に FAT32 形式でフォーマットしておいてください。
「Image File」に解凍したRaspbian のイメージファイル (YYYY-MM-DD-wheezy-raspbian.img)、「Drive」に SDカードのドライブを指定し、「Write」 ボタンをクリックします。
以上で SDカードの準備は終了です。 書き込みが終了したら、SDカードを Raspberry Pi に設置し、電源を投入します。
Linux では ddコマンドを利用してイメージの読み書きができます。 ddコマンドは UNIX系の OSなら大抵デフォルトでインストールされています。
SDカードを差し込んでから、 dmesg コマンドでカーネルのメッセージを確認します。
$ dmesg : 中略 [333478.822170] sd 3:0:0:0: [sdb] Assuming drive cache: write through [333478.822174] sdb: sdb1 sdb2 [333478.839563] sd 3:0:0:0: [sdb] Assuming drive cache: write through [333478.839567] sd 3:0:0:0: [sdb] Attached SCSI removable disk [333479.094873] EXT4-fs (sdb2): mounted filesystem with ordered data mode [333527.658195] usb 1-1: USB disconnect, address 2
このメッセージから SDカードのデバイス名を確認します。この例では sdb が SDカードのデバイス名のようです。/dev/ の下を見てみます。
ls -al /dev/sd* brw-rw---- 1 root disk 8, 0 May 7 17:28 /dev/sda brw-rw---- 1 root disk 8, 1 May 7 17:28 /dev/sda1 brw-rw---- 1 root disk 8, 2 May 7 17:28 /dev/sda2 brw-rw---- 1 root disk 8, 5 May 7 17:28 /dev/sda5 brw-rw---- 1 root disk 8, 16 May 18 14:19 /dev/sdb brw-rw---- 1 root disk 8, 17 May 18 14:19 /dev/sdb1 brw-rw---- 1 root disk 8, 32 May 18 14:19 /dev/sdc
sda は大抵システムディスクなので、絶対に触ってはいけません。
ディストリビューションによっては、SDカード内にマウント可能なファイルシステムがある場合自動でマウントするケースもあるようです。 その場合、ディスクをアンマウントしてください。(Ubuntuではデスクトップにマウントしたファイルシステムのフォルダーが現れるので右クリックで取り外してください。それ以外は umount コマンドでアンマウントします。)
dd if=イメージファイル of=SDカードのデバイスファイル bs=1M のようにコマンドを入力し実行します。 ただし、デバイスファイルへの書き込みは管理者(root)権限が必要ですので、sudo を使用してください。
$ unzip 2013-02-09-wheezy-raspbian.zip Archive: 2013-02-09-wheezy-raspbian.zip inflating: 2013-02-09-wheezy-raspbian.img $ sudo dd if=2013-02-09-wheezy-raspbian.img of=/dev/sdb bs=1M 1850+0 records in 1850+0 records out 1939865600 bytes (1.9 GB) copied, 201.543 s, 9.6 MB/s
実行中は別のターミナルなどで、iostat コマンドを実行して書き込みが正しく行われているかどうか見ることができます。 (最近のディストリビューションではデフォルトでインストールされていないことがあります。debian/ubuntu では apt-get install sysstat で iostat コマンドが使えるようになります。)
$ iostat -mx 1 avg-cpu: %user %nice %system %iowait %steal %idle 0.00 0.00 0.00 50.25 0.00 49.75 Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await svctm %util sda 0.00 0.00 0.00 1.00 0.00 0.00 8.00 0.00 0.00 0.00 0.00 sdb 0.00 1856.00 0.00 78.00 0.00 9.14 240.00 143.40 1855.85 12.82 100.00
sdb の項目を見ると 9.14MB/sの書き込み速度が出ていることがわかります。 class 6 の SDカードなら 6MB/sec, class 10の SDカードなら 10MB/sec 程度の速度が出ていれば、問題なく書き込まれていると考えてよいでしょう。 書き込みが終了すると、ディストリビューションによっては自動でマウントされる場合があります。その場合、アンマウントしてからSDカードを抜いてください。
Mac OS Xも Linux と同様 ddコマンドを利用して書き込みます。 ただし、Mac では SDカードを挿入すると自動的にマウントされてしまい、マウント中は ddコマンドで SDカードに書き込むことができないので、アンマウント (OSから取り外す) する必要があります。
SDカードを差し込むと Finder に図のように SDカードのアイコンが現れます。 アンマウントするつもりでイジェクトボタンを押さないよう気を付けてください。
SDカードのボリューム名はここでは Untitled です。ボリューム名を覚えておきます。 コマンドプロンプトから df コマンドを入力すると以下のように表示されます。
$ df -k Filesystem 1024-blocks Used Available Capacity iused ifree %iused Mounted on /dev/disk0s2 500000000 437664508 62079492 88% 109480125 15519873 88% / devfs 194 194 0 100% 679 0 100% /dev map -hosts 0 0 0 100% 0 0 100% /net map auto_home 0 0 0 100% 0 0 100% /home /dev/disk1s1 57288 18992 38296 34% 512 0 100% /Volumes/Untitled
一番下 ''/Volumes/Untitled'' とあるのが先ほどの SDカードのマウントポイントです。一番左の SDカードのデバイス名 /dev/disk1s1 を覚えておきます。
$ diskutil umount /Volumes/Untitled Volume (null) on disk1s1 unmounted $ df -k Filesystem 1024-blocks Used Available Capacity iused ifree %iused Mounted on /dev/disk0s2 500000000 437664716 62079284 88% 109480177 15519821 88% / devfs 194 194 0 100% 679 0 100% /dev map -hosts 0 0 0 100% 0 0 100% /net map auto_home 0 0 0 100% 0 0 100% /home
先ほどの /Volumes/Untitled が消えて、SDカードがアンマウントされていることがわかります。 次にddコマンドを使用してイメージを書き込みます。 dd if=イメージファイル of=/dev/rdisk1 bs=1m のように入力します。 of=/dev/rdisk1 は先ほど覚えたデバイスファイル /dev/disk1s1 のうち後ろの s1 を取り、さらにdiskの前に raw deviceであることを示す r を付けたデバイス名です。
このコマンドはデバイスファイルにアクセスするので管理者 (root) でなければ実行できません。sudoを使用して以下のように実行します。
$ sudo dd if=2013-02-09-wheezy-raspbian.img of=/dev/rdisk1 bs=1m 1850+0 records in 1850+0 records out 1939865600 bytes transferred in 302.377337 secs (6415380 bytes/sec) $
書き込み中は、「アクティビティモニタ」で「ディスクの動作」を見ることで書き込みが正しく行われているかどうかわかります。 class 6 の SDカードなら 6MB/sec, class 10の SDカードなら 10MB/sec 程度の速度が出ていれば、問題なく書き込まれていると考えてよいでしょう。
書き込みが終了すると、自動的に再度マウントされますので、今度は Finder のイジェクトボタンを押して SDカードを抜きます。
Raspberry Pi に HDMIモニター、キーボード、ネットワークを接続してください。
SDカードを挿入し Raspberry Pi に始めて電源を投入すると、各種ドライバの読み込み画面が表示された後、以下の設定画面 (raspi-config) が表示されます。
なお、後述の PiRT-Unit のシリアルコンソールから操作する場合、raspi-config は表示されません。 以下のユーザー名、パスワードでログインして raspi-config コマンドを実行することで初期設定を行うことができます。
Debian GNU/Linux 7.0 rtunit0 ttyAMA0 rtunit0 login: pi Password: Last login: Sat Feb 9 03:40:44 UTC 2013 on ttyAMA0 Linux rtunit0 3.6.11+ #371 PREEMPT Thu Feb 7 16:31:35 GMT 2013 armv6l The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. NOTICE: the software on this Raspberry Pi has not been fully configured. Please run 'sudo raspi-config' $ raspi-config
各項目の内容を以下に示します。 必要に応じて各項目の設定を行ってください。
1 Expand Filesystem | 使用する SD カードのパーティションを拡張します。初期状態では、SD カードの全体を使用していないので、特に理由がなければ拡張を行ってください。 |
2 Change User Password | 初期設定ユーザー 「pi」 のパスワードを変更します。 利用者のわかりやすいパスワードに変更してください。 |
3 Enable Boot to Desktop/Scratch | 起動時の画面の設定で、デフォルトはコンソール利用となっています。GUI 利用に変更したい場合には設定します。 |
4 Internationalisation Options | 「ロケール」、「タイムゾーン」、「キーボード配列」の設定です。 |
I1 Change Locale | ロケール設定を行います。キーボード配列は必要に応じて [ja_JP.ECU-JP ECU-JP] などに設定してください。 その際は日本語フォントのインストールが必要となるようです。 |
I2 Change Timezone | タイムゾーンの設定を行います。日本国内で使用する場合は [Asia]-[Tokyo] を設定してください。 |
I3 Change Keyboard Layout Set the keyboard layout to match your keyboard | キーボードの設定を行います。必要に応じて日本語キーボード等に設定して下さい。 |
5 Enable Camera | カメラモジュールを接続している場合に設定してください。 |
6 Add to Rastrack | Rastrack への登録 |
7 Overclock | オーバークロック |
8 Advanced Options | その他のオプション。ここでは PiRT-Unit の環境で必要な項目のみ取り上げます。 |
A6 SPI | SPIを利用する場合は、Enable に設定します。(デフォルトはDisable) |
A7 I2C | I2Cを利用する場合は、Enable に設定します。(デフォルトはDisable) |
9 About raspi-config | 本ツールに関する情報を表示します。 |
上記の各項目を設定した後は、[Tab] キーにて [Finish] を選択して実行してください。 Raspberry Pi 本体が再起動し、各種設定が有効となります。
再起動後、コマンド入力待ち状態で、「startx」を実行すると Raspbian のデスクトップ画面が表示されます。
終了する場合は、以下のコマンドで停止した後、本体から電源を抜いてください。
$ sudo halt
Raspberry Pi の USB に無線LANドングルを挿入し設定することで、Raspberry Pi を無線化できます。 移動ロボットなどに搭載する際には便利です。
まず、/etc/network/interfaces を以下のように編集します。
$ sudo vi /etc/network/interfaces
以下の2か所を書き換えます。
iface wlan0 inet manual ↓ iface wlan0 inet dhcp
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf ↓ wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
次に、無線LANの ESSID とキーを登録します。
$ sudo bash # cd /etc/wpa_supplicant # wpa_passphrase ESSID pass >> wpa_supplicant.conf
SSID には無線LANの ESSID、pass には無線LANのキーを入力します。リダイレクトの際、> ではなく >> (追記)を使用するよう注意してください。 結果は以下のようになっていると思います。
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 network={ ssid="OpenRTM" #psk="4332221111" psk=142914b76be167767055ff945898baaaf83c42b3ad3b99afb0ae531e8fb15e5e }
無線LAN アクセスポイントの設定によっては、追加の設定が必要になるかもしれません。 以下に、一例を示します。
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 network={ ssid="OpenRTM" proto=WPA2 key_mgmt=WPA-PSK pairwise=TKIP CCMP group=TKIP CCMP #psk="4332221111" psk=142914b76be167767055ff945898baaaf83c42b3ad3b99afb0ae531e8fb15e5e }
最後に、インターフェースを初期化します。
# ifdown wlan0 # ifup wlan0 Internet Systems Consortium DHCP Client 4.2.2 Copyright 2004-2011 Internet Systems Consortium. All rights reserved. For info, please visit https://www.isc.org/software/dhcp/ : 中略 DHCPREQUEST on wlan0 to 255.255.255.255 port 67 DHCPOFFER from 192.168.11.1 DHCPACK from 192.168.11.1 bound to 192.168.11.26 -- renewal in 34810 seconds.
ここで、無線LAN に接続できない場合、/etc/network/interfaces, /etc/wpa_supplicant/wpa_supplicant.conf の設定を見直してください。
# ifconfig wlan0 wlan0 Link encap:Ethernet HWaddr XX:XX:XX:XX:XX:XX inet addr:192.168.11.26 Bcast:192.168.11.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:1218 errors:0 dropped:0 overruns:0 frame:0 TX packets:21 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:250608 (244.7 KiB) TX bytes:4506 (4.4 KiB)
無事、無線LAN wlan0 に IPアドレスが割り振られました。
Raspberry Pi に ssh でリモートログインで操作する場合、固定IPアドレスを割り振っていなければ、通常 Raspberry Pi の IPアドレスをコンソールで調べて接続する必要があります。
そこで Bonjour互換の avahi というサービスをインストールします。 Bonjour は Apple が提唱するネットワーク上のサービスを自動的に検索して利用できるようにするためのサービスです。 avahi を使うと、DHCP で IPアドレスを割り振っている Raspberry Pi に対してもホスト名でアクセスすることができるようになります。
他のホスト名と衝突しないホスト名を選び設定します。
$ sudo vi /etc/hostname
/etc/hostname に1行目にホスト名を記載します。初期値は raspberrypi となっています。 さらに、/etc/hosts の 127.0.1.1 raspberrypi となっている部分を上で決めた自分のホスト名に書き換えます。
$ sudo vi /etc/hosts
以下のコマンドで avahi デーモンをインストールします。
$ sudo apt-get update $ sudo apt-get install avahi-daemon
自ホストに対してping を打ってみます。ホスト名の後に .local を付けた名前を使います。
$ ping myhost.local
これで ping が返ってくれば、avahi がほぼ正しく設定されていることになります。
PC から avahi が設定された RaspberryPi にアクセスするためには、PC側にも avahi か Bonjour がインストールされている必要があります。
Linux では、RaspberryPi と同様に avahi-daemon をインストールすれば使用できます。また Mac はデフォルトで Bonjour がインストールされているので、特に何もする必要がありません。
Windows ではデフォルトでは Bonjour はインストールされていません。 最も簡単に Bonjour を導入する方法は iTunes をインストールすることです。
どうしても iTunes をインストールしたくない場合は、アーカイバアプリケーションなどで、ダウンロードした iTunesSetup.exe を展開すると BonjourSetup.exe を抽出することもできます。
また、以下の Apple Bonjour 印刷サービスにも Bonjour が同梱されています。(iTunesに同梱されているものよりバージョンが若干古いようです。)
現在 Applie では Bonjour for Windows 単体としては配布は行なっていませんが、かつて配布していたものを再配布しているサイトも幾つかあります。(ただし、古いバージョンしか入手できないようです。) 以下は Appleサイト以外の Bonjour ダウンロードサイトです。自己責任でご利用ください。
ファイヤウォールが動作している場合、Bonjour がうまく機能しないことがあります。 その場合、UDPポート5353を開放するかファイヤウォールを OFF にしてください。
Windows から RaspberryPi に ssh 経由でログインするためには、ssh クライアントをインストールする必要があります。 Windows で利用可能なクライアントは多数ありますが、ここでは Tera Term を紹介します。
TeraTerm をインストール後、起動すると接続ダイアログが現れるので、先ほど設定したホスト名+.local を「ホスト」のテキストボックスに入力しOKを押します。 パスワードが変更されていなければ、
でログインできます。
なお、Linux や Mac はターミナルウインドウを開いて
$ ssh pi@myhost.local
のようにして接続します。
Raspberry Pi はヘッドレス状態 (モニタ、キーボードを接続しない状態) では IPアドレスなどを知る術がないため初期設定を行うのは少々困難です。 最初にモニタとキーボードを接続して、ホスト名を設定し前述のように Avahi経由で IPアドレスをホスト名から知ることも可能ですが、全く設定していない Raspberry Pi についてはこの方法も使えません。
xfinder は Raspberry Pi や BeagleBone などのCPUボードに搭載されている Ethernet インターフェースの MAC (Media Access Control) アドレスからIPアドレスを割出しログインするためのツールです。
Ethernet のインターフェースには48ビットの固有のアドレス(MAC (Media Access Control) アドレス)が割り振られており、その上位24ビットはベンダ(ネットワーク機器を開発する企業など)の固有のアドレスとなっています。 Ethernet ではパケットの送受信をするために相互に MACアドレスを知る必要があり、IPアドレスから MACアドレスを調べるための ARP(Address Resolution Protocol) と呼ばれるプロトコルが利用できます。 xfinderでは、ネットワーク上に接続されている特定の MACアドレスのパターンを見つけることにより、Raspberry Pi などのヘッドレスシステムの IPアドレスを調べ、ssh 等でログインし設定・開発を容易に行えるようにサポートします。
xfinder は一つの実行ファイルでコマンドラインツール (CUI モード) とグラフィカルユーザインターフェースツール (GUI モード) の2通りとして利用することができます。 ここでは、GUIモードの xfinder の使い方について説明します。
xfinder は以下の場所からダウンロードできます。
xfinder の使い方は以下の3ステップです。
xfinder.exeを起動すると、以下の様な画面が表示されます。
まず、①左上のペインにてスキャンする条件(インターフェース、ボード、MACアドレスパターン等)を指定しスキャンを開始、②次にスキャンして見つかった Raspberry Pi 等のリストが表示されるので選択、③の左下のペインにてログイン条件を指定してターミナルアプリケーションを起動します。 ターミナルアプリケーションが起動後は、対象となる Raspberry Pi にログインして設定やプログラムの開発などを行うことができます。
なお、右のペインに表示されたボードのリストをダブルクリックすることでターミナルアプリケーションの起動とログインを行うことも可能です。
左上の Scan settings では、ネットワークをスキャンするための条件を設定します。
現在の PC のどのネットワークインターフェースから Raspberry Pi を探すかを選択します。複数のネットワークインターフェースがある場合、複数のIPアドレスが表示されるので、どのネットワーク(例えば、一つはグローバル側、もう一つがプライベート側のネットワークにつながっており、プライベート側のネットワークにある Raspberry Pi を探したい場合はここでプライベートアドレスを選択します。)をスキャンするかを選択します。
全てのネットワークインターフェースに対してスキャンを行う場合はALLを選択してください。 どの IPアドレスがどのネットワークインターフェースと対応しているかわからない場合は、コントロールパネル→ネットワークとインターネット→ネットワークと共有センター→アダプターの設定の変更からアダプタのアイコンをクリックしてどのようなIPアドレスが割り当てられているか確認してください。
また、コマンドプロンプトを開いて ipconfig コマンドを実行しインターフェースと割り当てられているIPアドレスを確認することもできます。
どのボードを探すかコンボボックスから選択します。Raspberry Pi か BeagleBone を選択でき、デフォルトでは Raspberry Pi が選択されています。
この一覧に探したいボードがない場合は、該当するボードのネットワークインターフェースの MACアドレスの上6ケタを調べ、次の Match Pattern のテキストボックスに入力しスキャンする必要があります。
Raspberry Pi にUSB 無線LANアダプタを付け、無線LANのみで接続している場合はここで Raspberry Pi を選択しても探すことはできません。 無線LANアダプタの MACアドレスの MACアドレスの上6ケタ (例えば Buffaroの場合10:6f:3f) を Match Pattern に入力して探します。
Raspberry Pi や BeagleBone 以外のボードを探す場合、ここに探したい MACアドレスのパターンを入力します。
また Raspberry Piに無線LANアダプタなどを装着している場合も、メーカー固有の MACアドレス上6ケタを入力することで探し出すことが可能です。 ただし、メジャーなメーカーの無線LANアダプタなどはスキャンすると多数発見されることもあります。
Scan ボタンはスキャンを実行する際に押します。スキャン中は押すことができません。 Abortボタンはスキャン実行中に途中でやめたい場合に押します。スキャン実行中のみ押すことができます。 ボタンの下のプログレスバーはスキャンの進捗状況を表示します。
右側の Found nodes のペインはスキャンして見つかったボードのIPアドレス、MACアドレスおよびホスト名を表示します。
なお、ここに表示されたリストをダブルクリックすると、左の Terminal launcher の設定に従ってターミナルアプリケーションが起動しログインできます。
左側の Terminal launcher のペインは見つかったホストに対してターミナルアプリケーションを利用してログインする際に使用します。
ボードタイプ | User name | Password |
RaspberryPi | pi | raspberry |
BeagleBone | root | (パスワード無し) |
Raspberry Pi に開発環境をインストールすれば、Raspberry Pi上でのセルフコンパイルによる開発が可能です。(このサイズの組込み Linux ボードでは、通常クロスコンパイルによる開発が普通です。)
従って、PC上の RTCBuilder で生成した RTコンポーネントのコードを、Raspberry Pi上でコンパイル、実行することができます。 残念ながら Eclipse をインストールして実用的な速度で使用することは難しいようです。
この節では RTコンポーネントを開発するために必要なパッケージをインストールしていきます。
OpenRTM-aist は、apt-get を使用してインストールすることが可能です。 まず sources.list を修正します。
$ sudo vi /etc/apt/sources.list
sourcelist に以下の1行を加えてください。
deb http://openrtm.org/pub/Linux/raspbian/ wheezy main
次に、以下の手順でインストールを行います。
# apt-get update # apt-get -y --force-yes install gcc g++ make uuid-dev # apt-get -y --force-yes install libomniorb4-dev omniidl omniorb-nameserver # apt-get -y --force-yes install openrtm-aist openrtm-aist-dev openrtm-aist-example # apt-get -y --force-yes install openrtm-aist-python openrtm-aist-python-example
OpenRTM-aist のインストール後、サンプルコンポーネントを起動してOpenRTM-aist が正しくインストールされたかどうか確認します。
下図のように、PC側でネームサーバと ConsoleIn コンポーネント、Raspberry Pi側でネームサーバと ConsoleOut コンポーネントを実行します。 コンポーネントはデフォルトで localhost のネームサーバに接続しますので、これを利用して rtc.conf に特定のネームサーバを設定することなく簡単にコンポーネントにアクセスします。 PC上の RTSystemEditor で、PC のネームサーバと Raspberry Pi上のネームサーバに接続し、ConsoleIn コンポーネントと ConsoleOut コンポーネントを接続します。
Raspberry Pi に TeraTerm などで接続後、コンポーネントを起動します。 ネーミングサービスを起動してから ConsoleOut を起動します。
$ rtm-naming $ /usr/share/OpenRTM-x.y/examples/ConsoleOutComp または $ python /usr/share/OpenRTM-x.y/examples/python/SimpleIO/ConsoleOutComp.py
上の omniorb-nameserver のインストール時に、システム起動時に自動的に omniORB のネームサービスが起動するようになっています。 しかし、ネームサービスの起動タイミングとネットワークインターフェースの起動タイミングによっては、外部からネームサーバに正しくアクセスできない場合があります。 その場合は、rtm-naming コマンドによりネームサーバを再起動することで、問題に対処できる場合があります。
まず、ネームサーバを起動します。 Windows の場合、スタートメニューから 「OpenRTM-aist x.y」→「C++」→「tools」の下のStart Naming Service から起動します。 ついでに、RTSystemEditor も起動しておきます。
続いて、ConsoleIn を起動します。 「OpenRTM-aist x.y」→「C++」→「examples」の下の ConsoleOut をクリックして ConsoleOut コンポーネントを起動します。
RTSystemEditor の左側の NameService View のコンセントアイコンをクリックし、ネームサーバに接続します。 まず、自ホストのネームサーバに接続します。接続ダイアログに localhost と入力します。
次に、Raspberry Pi のネームサーバへ接続します。再度 NameService View の接続アイコンをクリックし、Raspberry Pi のホスト名+.localををダイアログに入力します。
ネームサービスビューには2つのネームサーバの状態が表示され、それぞれのネームサーバの下に ConsoleIn0、ConsoleOut0 という2つのコンポーネントが見えているはずです。 RTSystemEditor のメニューバーのonlineエディタアイコン(ONと書かれたアイコン)をクリックし、SystemEditor を開きます。 NameService View から ConsoleIn0 と ConsoleOut0 をそれぞれ SystemEditor 上にドラッグアンドドロップし、InPort と OutPort を接続します。
メニューバーの緑の再生ボタンをクリックすると、2つのコンポーネントがアクティベートされ上図のような状態になります。
PC側の ConsoleIn コンポーネントのウインドウから適当な数字を入力します。
すると、下図のように Raspberry Pi側の ConsoleOut の表示に ConsoleIn で入力した数値が現れます。
ネットワーク環境や PC の設定により、上記の手順でうまくいかないことがあります。以下のトラブルシューティングを参考に問題を解決してください。
このほか、Raspberry Pi の有線LANと無線LAN等2つ以上のネットワークインターフェースがある場合、PCとの接続に使用するどちらかのネットワークのみを使うように設定することで解決するケースもあります。
また、Raspberry Pi の有線LANと無線LAN等2つ以上のネットワークインターフェースがある場合、PCとの接続に使用するどちらかのネットワークのみを使うように設定することで解決するケースもあります。
コマンドプロンプトから ipconfig で PC の IPアドレスを調べる等して、rtc.conf に使用する方の IPアドレスを以下のように設定します。
corba.endpoints: 192.168.11.20
ただし、Vista 以降の Windows では、C:\Program Files 以下のファイルは簡単には編集ができなくなっています。c:\tmp など適当なディレクトリーに ConsoleIn.exe と rtc.conf をコピー(あるいは新たに作成)するなどして、対処してください。
corba.endpoints: 192.168.11.21
cmake は apt-get を利用してインストールする事が可能です。root 権限を持つユーザでインストールを行います。
$ sudo apt-get update $ sudo apt-get install cmake
CMake ベースの RTコンポーネントプロジェクトでは、デフォルトで doxygen を利用してドキュメントを生成するように設定されています。 しかしながら、doxygen をインストールすると、LaTeX等も同時にインストールされてしまい、SDカードの容量を圧迫しますのでこのチュートリアルでは Doxygen をインストールしません。
CMake ベースの RTCプロジェクトにおいて doxygen でのドキュメント生成を抑制するには、トップレベルの CMakeLists.txt で、
option(BUILD_DOCUMENTATION "Build the documentation" ON) ↓ option(BUILD_DOCUMENTATION "Build the documentation" OFF)
のように変更します。
SDカードの容量が十分ある場合 doxygen を apt-get で以下のようにインストールすることができます。
$ sudo apt-get install doxygen
※Doxygen のインストールが完了するまでには、十数分程度かかります。
ソースコードを外部から取得する際にたびたび使用するので subversion/git をインストールすることをお勧めします。
$ sudo apt-get install subversion git
コンポーネントのコンパイルが行えるかテストしてみます。 以下のリポジトリに移動ロボット Kobuki用コンポーネントがありますので、チェックアウトしてコンパイルしてみます。
ソースコードをチェックアウトしてみます。
$ svn co http://svn.openrtm.org/components/trunk/mobile_robots/kobuki : 中略 A kobuki/libkobuki/doc/CMakeLists.txt A kobuki/libkobuki/License.rtf A kobuki/libkobuki/CMakeLists.txt A kobuki/rtc.conf A kobuki/CMakeLists.txt Checked out revision 2. $
kobuki ディレクトリーいかにソースコードがチェックアウトされましたので、build ディレクトリーを作成しその中でビルド、インストールします。
$ cd kobuki $ mkdir build $ cd build $ cmake -DCMAKE_INSTALL_PREFIX=/usr .. $ make $ cd src $ make install
このソースコードはデフォルトで Doxygenに よるドキュメント生成が OFF になっていますので、Doxygen がインストールされていなくてもビルドできるでしょう。
以下の例では、GPIO を用いて、スイッチの ON/OFF の検出と、LED の点灯を行うコンポーネント (DigitalIn-RTC、DigitalOut-RTC) を作成して Raspberry Pi の特徴である GPIO の利用について理解を深めます。 サンプルコンポーネントのソースコードは以下からダウンロードできます。
Raspberry Pi には GPIO端子があり、これを利用することで様々な外部デバイスを利用することができます。
Raspberry Pi 本体に付属している GPIO のピンアサインを以下に示します。
GPIO を使用する場合には、各ピンの位置に注意してください。特に5V 端子を使用する場合、配線を誤ると Raspberry Pi 本体および SD カードを破壊してしまう危険がありますので、十分に注意してください。
LED を点灯させる回路と、スイッチの ON/OFF を検出する回路を作成します。 ブレッドボード等があれば簡単に回路を組めますが、ない場合でも部品点数が少ないのでリード線をはんだ付けするなどすれば比較的容易に回路を組むことができるでしょう。 以下に、必要な部品のリストを示します。
部品表 | |
LED回路 | |
LED | 1個 |
抵抗 | 100Ω (茶黒茶金) ~330Ω (橙橙茶金) |
リード線 | 若干 |
スイッチLED回路 | |
LED | 1個 |
抵抗 | 330Ω (橙橙茶金) ~1kΩ (茶黒赤金) |
リード線 | 若干 |
Raspberry Pi が1台の場合は、以下の LEDとスイッチ回路を同じ Raspberry Pi に接続します。 もし、Raspberry Pi が2台あるなら、それぞれの Raspberry Pi に LED とスイッチを取り付けると面白いかもしれません。
DigitalIn-RTC は、データポートに入力された bool 値 (true/false) を指定された GPIO ポートに出力するコンポーネントです。GPIO ポートの出力値を観測するために、GroundピンとGPIO 18ピンに LED と抵抗を接続し下図のような回路を作成します。
ブレッドボードでこの回路を作成する場合はこのようになります。
DigitalOut-RTC は、GPIO ポートに入力された bool 値 (true/false) をデータポートから出力するコンポーネントです。 GPIO に値を入力するために、Ground, 3.3V Power, GPIO 17に抵抗とスイッチを接続して下図のような回路を作成します。
ブレッドボードでこの回路を作成する場合はこのようになります。
ソースコードを以下から Raspberry Pi にダウンロードして、DigitalIn-RTC/DigitalOut-RTC コンポーネントをコンパイルします。
$ unzip RaspberryPi_sample.zip $ cd RaspberryPi_sample/DigitalInRPI/ $ vi CMakeLists.txt
ここで、CMakeLists.txt を書き換えて、ドキュメントの生成を抑制するよう設定します。
option(BUILD_DOCUMENTATION "Build the documentation" OFF) ↓ option(BUILD_DOCUMENTATION "Build the documentation" ON) $ mkdir build $ cd build $ cmake .. -- The C compiler identification is GNU 4.6.3 -- The CXX compiler identification is GNU 4.6.3 : 中略 -- Configuring done -- Generating done -- Build files have been written to: /home/pi/RaspberryPi_sample/DigitalInRPI/build
OpenRTM-aist が正しくインストールされていれば、問題なく configure が終了します。 もし、OpenRTM や coil が無いなどでエラーが出た場合、OpenRTM-aist (C++版) が正しくインストールされていることを確認 (dpkg -l |grep openrtm 等) してください。
$ make : 中略 Scanning dependencies of target DigitalInComp [ 66%] Building CXX object src/CMakeFiles/DigitalInComp.dir/DigitalInComp.cpp.o [100%] Building CXX object src/CMakeFiles/DigitalInComp.dir/DigitalIn.cpp.o Linking CXX executable DigitalInComp [100%] Built target DigitalInComp $
コンパイルされたコンポーネント DigitalInComp は src の下にあります。
$ ls src/ CMakeFiles cmake_install.cmake DigitalInComp DigitalIn.so Makefile
DigitalIn-RTC と同様にコンパイルします。
$ cd RaspberryPi_sample/DigitalOutRPI/ $ mkdir build $ vi CMakeLists.txt
ここで、CMakeLists.txt を書き換えて、ドキュメントの生成を抑制するよう設定します。
option(BUILD_DOCUMENTATION "Build the documentation" OFF) ↓ option(BUILD_DOCUMENTATION "Build the documentation" ON) $ mkdir build $ cd build $ cmake .. -- The C compiler identification is GNU 4.6.3 -- The CXX compiler identification is GNU 4.6.3 : 中略 -- Configuring done -- Generating done -- Build files have been written to: /home/pi/RaspberryPi_sample/DigitalOutRPI/build
$ make -- OpenRTMConfig.cmake found. -- Configrued by configuration mode. : 中略 Scanning dependencies of target DigitalOutComp [ 66%] Building CXX object src/CMakeFiles/DigitalOutComp.dir/DigitalOutComp.cpp.o [100%] Building CXX object src/CMakeFiles/DigitalOutComp.dir/DigitalOut.cpp.o Linking CXX executable DigitalOutComp [100%] Built target DigitalOutComp $
コンパイルされたコンポーネント DigitalOutComp は src の下にあります。
$ ls src/ CMakeFiles cmake_install.cmake DigitalOutComp DigitalOut.so Makefile
各RTC が正常にコンパイルできたら、NameServer を起動後、各RTC を起動します。
$ rtm-naming $ sudo /home/pi/RaspberryPi_sample/DigitalOutRPI/build/src/DigitalOutComp & $ sudo /home/pi/RaspberryPi_sample/DigitalInRPI/build/src/DigitalInComp &
&color(red){※サンプルコンポーネントは GPIO を利用するので root 権限で実行する必要があります。}
PC上で RTSystemEditor を起動し、Raspberry Pi上の NameServewr に接続します。 各RTC を配置し、ポート間の接続を行った後、活性化(Activate)します。
各RTC が正常に起動すると、タクトスイッチの状態に応じて、LED が点灯/消灯するようになります。
この Book では、Raspberry Pi と PiRT-Unit を組み合わせてOpenRTM-aist から利用する方法を解説します。
PiRT-Unit は産総研で開発された、Raspberry Pi用 IO拡張ボードです。 ウィン電子工業から発売中です。
PiRT-Unit からは、AD (4ch)、DA (2ch)、PWM (1ch)、I2C (1ch)、RS232C/XBee (1ch) がそれぞれ利用できます。
Raspberry Pi拡張IOボード | |
ADコンバータ | 10bit, 4ch チップ: ADC104S021 サンプリング 200kHz |
DAコンバータ | 12bit, 2ch チップ MCP4822 |
PWM出力 | 1ch, RCサーボモータードライブ用 フォトカプラ絶縁 |
RS232C | D-SUB 9pinコネクタ XBee とジャンパにて切り替え |
XBee | XBee接続コネクタ XBee: Digi International 製 Zigbeeモジュール XBee とジャンパにて切り替え |
電源入力 | 5V DC入力 Raspberry Piに電源供給可能 Raspberry Piからの電源供給でも動作 |
Raspberry Pi のデフォルトの設定 (raspbian armhf) では、SPI デバイスなどは利用できません。 ここで、PiRT-Unit を利用するために必要なデバイスの設定やプログラミング環境の構築を行います。
以下の内容をスクリプト化したものがこちらにあります。
Raspberry Pi のサイトからダウンロードしたイメージの適当な場所にダウンロードして以下のように実行します。
$ wget http://svn.openrtm.org/Embedded/trunk/RaspberryPi/tools/rpi.sh $ chmod 755 rpi.sh $ sudo rpi.sh rtunit0 --type rtunit $ sudo rpi.sh rtunit0 --type rtunit_examples
以上で、以下の PiRT-Unit を利用するために行っている設定、パッケージのインストール、サンプルのインストールが自動で行われます。 バージョンアップ、ファイル配置の変更などによってエラーが出た場合にはメーリングリストなどへお知らせください。
Usage: rpi.sh hostname --type <TYPE> TYPE are: basic kobuki kobuki_only rtunit rtunit_only basic: Installing avahi, cmake, subversion/git and OpenRTM kobuki: Installing basic + Kobuki RTC kobuki_only: Installing Kobuki RTC only rtunit: Installing basic + spi/i2c tools and modules rtunit_only: Installing spi/i2c tools and modules only rtunit_examples: Installing basic + PiRT-Unit examples EXAMPLE: 1) Just change hostname # rpi.sh kobuki0 2) Basic setup: Installing OpenRTM-aist (C++/Python) # rpi.sh kobuki --type basic " 3) Kobuki setup: Installing OpenRTM-aist (C++/Python) and Kobuki RTC # rpi.sh kobuki --type kobuki
spi と i2c のデバイスモジュールをロードする方法は、カーネルの3.18から変更になりました。Raspberry Pi用 OS Raspbian が2015年のバージョンから該当するようですが、カーネルのバージョンを確認して判断してください。
spi と i2c を利用するためには、raspi-config で Enable に設定します。Raspberry Pi の初期設定 のページをご覧ください。
これより古いバージョンでは、以下のファイルを設定します。
/etc/modprobe.d/raspi-blacklist.conf に
blacklist spi-bcm2708 blacklist i2c-bcm2708
という2行が設定されていますが、これをコメントアウトします。
# blacklist spi and i2c by default (many users don't need them) #blacklist spi-bcm2708 #blacklist i2c-bcm2708
これで、spi と i2c のデバイスモジュールがロードされるようになります。
spi や i2c デバイスモジュールがロードされても、デフォルトでは一般ユーザーからアクセスできないようなパーミッションに設定されています。 少々不便なので、デバイス作成時に誰でもアクセスできるように設定しておきます。 新たに、/etc/udev/rules.d/50-udev.rules というファイルを作成し、中に以下の1行を追記します。
KERNEL=="spidev*", SUBSYSTEM=="spidev", GROUP="spi", MODE="0666"
以上で準備は終了です。
PiRT-Unit では AD および DA は SPI経由で接続されており、SPI デバイスを制御する Python モジュールをインストールすることで、Python から手軽に AD および DA を利用することができます。
Python から SPI経由で AD、DA を利用するには、以下の拡張モジュールをインストールします。
下準備のため、以下のパッケージをインストールします。
sudo apt-get update sudo apt-get upgrade sudo apt-get install python-dev git-core i2c-tools python-smbus
py-spidev は github https://raw.github.com/doceme/py-spidev にあります。以下のようにしてインストールします。
$ cd ~ (or 適当なディレクトリー) $ git clone git://github.com/doceme/py-spidev $ cd py-spidev $ chmod 755 setup.py $ sudo ./setup.py install
これで、Python モジュール py-spidev が利用できるようになります。 試しに、spidev モジュールを利用してみます。
$ sudo python sudo: unable to resolve host raspbian-armhf Python 2.7.3 (default, Jan 13 2013, 11:20:46) [GCC 4.6.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import spidev >>> spi = spidev.SpiDev() >>> spi.open(0,0) >>> print spi.xfer2([0x00,0,0,0])
これで、CN2のAD変換器の値を読みだしてプリントしています。AD変換器 (ADC104S021) は10bitのシングルエンド型で、サンプリングレートは最大200kHzです。(Linux上で200kHzのサンプリングレートを保証するものではありません。) 実際には、"spi.xfer2([0x00],0,0,0])" で出力される値を 1024 (bit) で割って、5.0 (V) を掛けた値が計測された電圧になります。
>>> r = spi.xfer2([0x00,0,0,0]) >>> print r[0] * 5.0 / 1024.0, " [V]"
ここまで、エラーなく実行できれば、spidev モジュールが正しくインストールされています。
WiringPi-Python は GPIO を制御するツール: WiringPi を Python から利用するためのモジュールです。 まずは WiringPi をインストールします。
$ git clone git://git.drogon.net/wiringPi $ cd cd wiringPi $ git pull origin $ ./build
次に、WiringPi-Python 本体を以下のようにインストールします。
$ sudo apt-get install python-dev $ git clone https://github.com/WiringPi/WiringPi-Python.git $ cd WiringPi-Python $ git submodule update --init $ sudo python setup.py install
以上で、必要なモジュールのインストールは終了です。
ここでは、PiRT-Unitの入出力をそれぞれ簡単にテストしてみます。
PiRT-Unit の CN2-CN5 がADコンバータのピンです。 ピンアサインは以下の図のようになっており、GND-5V間を分圧したものを入力ピンに加えることでセンサ値などを読み取ることができるようになっています。
ADコンバータをテストするもっとも簡単な方法は、Phidgetsのセンサを接続することです。 Phidgets は Phidgets Inc. から発売されている、IO拡張ボードとセンサ群製品です。 日本では、ぷらっとほーむなどで購入することができます。
PCにUSB接続の拡張IOボードを接続し、様々なセンサ、アクチュエータユニットを追加して、プログラム等から計測・制御することができるキットです。
PCと接続する場合は、Interface Kitが必要ですが、PiRT-Unitでのみ使用する場合は、Sensor Kitのみでよいでしょう。
PIRT-UnitのADピンは、Phidgetのセンサが接続可能なピンアサインとなっており、Phidgetデバイスを接続することで、容易に拡張することができるようになっています。
adc_test.py
#!/usr/bin/env python # -*- coding: euc-jp -*- import sys import time import spidev class ADC: def __init__(self): self.spi = spidev.SpiDev() self.spi.open(0, 0) def get_value(self, channel): sned_ch = [0x00,0x08,0x10,0x18] if ((channel > 3) or (channel < 0)): return -1 r = self.spi.xfer2([sned_ch[channel],0,0,0]) ret = ((r[2] << 6 ) & 0x300) | ((r[2] << 6) & 0xc0) | ((r[3] >> 2) & 0x3f) return ret def get_voltage(self, channel): ret = self.get_value(channel) * 5.0 / 1024 return ret def main(): adc = ADC() while 1: adc1 = adc.get_value(0) msg1 = "%1.5fV(%04x)" % ((float(adc1)*5/1024),adc1) print msg1, adc1 = adc.get_value(1) msg1 = "%1.5fV(%04x)" % ((float(adc1)*5/1024),adc1) print msg1, adc2 = adc.get_value(2) msg2 = "%1.5fV(%04x)" % ((float(adc2)*5/1024),adc2) print msg2, adc3 = adc.get_value(3) msg3 = "%1.5fV(%04x)" % ((float(adc3)*5/1024),adc3) print msg3, sys.stdout.write("\n") time.sleep(0.5) if __name__ == '__main__': main()
ADコンバータにピンに適当な可変抵抗やPhidgetセンサなどを接続して、adc_test.py を実行すると、下図のようにセンサ値を読み取ることができます。
dac_test.py
#!/usr/bin/env python # -*- coding: euc-jp -*- import spidev from time import sleep spi = spidev.SpiDev() spi.open(0,1) def changeLevel(ch, onOff, percent): bit7 = ch << 7 bit6 = 0 << 6 bit5 = 1 << 5 bit4 = onOff << 4 size=12 number=(2**size-1)*percent/100 number= number<<(12-size) number= number<<(12-size) bottomPart= number % 256 topPart=(number-bottomPart)>>8 firstByte=bit7+bit6+bit5+bit4+topPart secondByte=bottomPart return spi.xfer2([firstByte,secondByte]) def which_channel(): channel = raw_input("Which channel do you want to test? Type 0 or 1.\n") while not channel.isdigit(): channel = raw_input("Try again - just numbers 0 or 1 please!\n") return channel def main(): channel = 3 while not (channel == 1 or channel == 0): channel = int(which_channel()) print "These are the connections for the digital to analogue test:" print "jumper connecting GP11 to SCLK" print "jumper connecting GP10 to MOSI" print "jumper connecting GP9 to MISO" print "jumper connecting GP7 to CSnB" print "Multimeter connections (set your meter to read V DC):" print " connect black probe to GND" print " connect red probe to DA%d on J29" % channel raw_input("When ready hit enter.\n") percent=[0,25,75,100] for p in percent: r = changeLevel(channel,1,p) print "Your meter should read about {0:.2f}V".format(p*2.048/100.0) raw_input("When ready hit enter.\n") r = changeLevel(0,0,0) r = changeLevel(1,0,0) if __name__ == '__main__': main()
i2c_test.py
#!/usr/bin/env python # -*- coding: euc-jp -*- import smbus import time def main(): # LCD initialize i2c = smbus.SMBus(1) addr = 0x3e contrast = 42 # 0-63 i2c.write_byte_data(addr, 0, 0x38) # function set(IS=0) i2c.write_byte_data(addr, 0, 0x39) # function set(IS=1) i2c.write_byte_data(addr, 0, 0x14) # internal osc i2c.write_byte_data(addr, 0,(0x70 | (contrast & 0x0f))) # contrast i2c.write_byte_data(addr, 0,(0x54 | ((contrast >> 4) & 0x03))) # contrast/icon/power i2c.write_byte_data(addr, 0, 0x6c) # follower control time.sleep(0.2) i2c.write_byte_data(addr, 0, 0x38) # function set(IS=0) i2c.write_byte_data(addr, 0, 0x0C) # Display On i2c.write_byte_data(addr, 0, 0x01) # Clear Display i2c.write_byte_data(addr, 0, 0x06) # Entry Mode Set time.sleep(0.2) # LCD Clear i2c.write_byte_data(addr, 0, 0x38) # function set(IS=0) i2c.write_byte_data(addr, 0, 0x0C) # Display On i2c.write_byte_data(addr, 0, 0x01) # Clear Display i2c.write_byte_data(addr, 0, 0x06) # Entry Mode Set time.sleep(0.2) # Send to LCD line1 = '__test__' for c in line1: i2c.write_byte_data(addr, 0x40, ord(c)) i2c.write_byte_data(addr, 0, 0xc0) # 2nd line line2 = '__!(^^)!__' for c in line2: i2c.write_byte_data(addr, 0x40, ord(c)) if __name__ == '__main__': main()
Phidgets は Phidgets Inc. から発売されている、IO拡張ボードとセンサ群製品です。 日本では、ぷらっとほーむなどで購入することができます。
PCにUSB接続の拡張IOボードを接続し、様々なセンサ、アクチュエータユニットを追加して、プログラム等から計測・制御することができるキットです。
PCと接続する場合は、Interface Kitが必要ですが、PiRT-Unitでのみ使用する場合は、Sensor Kitのみでよいでしょう。
PIRT-UnitのADピンは、Phidgetのセンサが接続可能なピンアサインとなっており、Phidgetデバイスを接続することで、容易に拡張することができるようになっています。
ここでは、Phidget の Ministick sensorを利用して、移動ロボットを制御してみます。 Ministick sensor は Phidget Sensor Kit #2 に含まれています。
Ministick sensorの出力ピンとPiRT-Unitを以下のように接続します。
X軸方向 (横向き) がADのCH0に、Y軸方向 (縦向き) がADのCH1に対応します。
このデータを読むプログラムをPythonで書いてみます。
#!/usr/bin/env python # -*- coding: euc-jp -*- import sys import time import spidev class ADC: def __init__(self): self.spi = spidev.SpiDev() self.spi.open(0, 0) def get_value(self, channel): sned_ch = [0x00,0x08,0x10,0x18] if ((channel > 3) or (channel < 0)): return -1 r = self.spi.xfer2([sned_ch[channel],0,0,0]) ret = ((r[2] << 6 ) & 0x300) | ((r[2] << 6) & 0xc0) | ((r[3] >> 2) & 0x3f) return ret def get_voltage(self, channel): ret = self.get_value(channel) * 5.0 / 1024 return ret def main(): adc = ADC() while 1: adc1 = adc.get_value(0) msg1 = "%1.5fV(%04x)" % ((float(adc1)*5/1024),adc1) print msg1, adc1 = adc.get_value(1) msg1 = "%1.5fV(%04x)" % ((float(adc1)*5/1024),adc1) print msg1, adc2 = adc.get_value(2) msg2 = "%1.5fV(%04x)" % ((float(adc2)*5/1024),adc2) print msg2, adc3 = adc.get_value(3) msg3 = "%1.5fV(%04x)" % ((float(adc3)*5/1024),adc3) print msg3, sys.stdout.write("\n") time.sleep(0.5) if __name__ == '__main__': main()
このようなプログラムを作成します。TeraTermなどでRaspberry Piにログインして、サンプルプログラムを作成、テストします。
Linux raspbian-armhf 3.2.27+ #307 PREEMPT Mon Nov 26 23:22:29 GMT 2012 armv6l The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Tue May 14 07:07:04 2013 from dhcpe2078.a02.aist.go.jp pi@raspbian-armhf ~ $ vi adc_test.py pi@raspbian-armhf ~ $ chmod 755 adc_test.py pi@raspbian-armhf ~ $ ./adc_test.py
サンプルプログラムを実行すると以下のような画面になります。ジョイスティックを倒してみると、Ch0,Ch1のデータが変化します。
それぞれ、X軸は左に倒すと、Y軸は上に倒すと電圧値が上がり、逆に倒すと電圧値が下がることがわかります。 ministick sensorの座標の関係を図に表わすと以下のようになります。
これは、一般的な座標系とはX軸が逆向きになっていますので、センサ値を処理する際には注意が必要です。
また、中心位置では、それぞれ5.0Vの半分、2.5V程度を指していることもわかると思います。 ただし、この値はぴったり2.5Vではなく、状況によっても変化するので、使用する前にキャリブレーションが必要なこともわかります。
ministick sensorを利用したジョイスティックコンポーネントを作成します。 仕様としては、以下のようにします。
基本プロファイル | |
コンポーネント名 | Ministick |
モジュール概要 | Phidget ministick sensor component |
バージョン | 1.0.0 |
ベンダ名 | AIST |
モジュールカテゴリ | Input Device |
アクティビティ | |
onInitialize, onFinalize, onActivated, onDeactivated, onExecute | |
データポート | |
[out] pos | |
概要 | ジョイスティックのX-Y位置データ |
データ型 | TimedFloatSeq |
詳細 | data[0]: x位置, data[1]: y位置 |
単位 | 無し |
[out] vel | |
概要 | 移動ロボットの速度ベクトル |
データ型 | TimedVelocity2D |
詳細 | vx: 並進速度, vy: 0.0, va: 角速度 |
単位 | vx [m/s], va [rad/s] |
[out] wheel_vel | |
概要 | 車輪速度 |
データ型 | TimedFloatSeq |
詳細 | data[0]: 左車輪角速度, data[1]: 右車輪角速度 |
単位 | [rad/s] |
コンフィギュレーション | |
scaling | |
概要 | スケーリングファクタ |
データ型 | double |
GUIコントロール | slider.0.1 |
制約条件 | 0.0<=x<=10.0 |
tread | |
概要 | 移動ロボットのトレッド幅 |
データ型 | double |
GUIコントロール | slider.0.01 |
制約条件 | 0.0<=x<=1.0 |
print_xy | |
概要 | XYデータプリントのデバッグフラグ |
データ型 | string |
GUIコントロール | radio |
制約条件 | (YES,NO) |
print_vel | |
概要 | velデータのデバッグプリントフラグ |
データ型 | string |
GUIコントロール | radio |
制約条件 | (YES,NO) |
print_wvel | |
概要 | wheel_velデータのデバッグプリントフラグ |
データ型 | string |
GUIコントロール | radio |
制約条件 | (YES,NO) |
この仕様に従い、RTCBuilderでPythonのテンプレートコードを生成します。
コンポーネントにADCの読み込みなどの機能を追加していきます。
まず、コンポーネントのコンストラクタでSPIオブジェクトを生成し初期化します。
他の import 文の近くに、spidevをimportする一文を追加します。計算などで使用するのでmathモジュールもインポートします。
# Import RTM module import RTC import OpenRTM_aist import math import spidev
さらに、コンストラクタで、必要な変数を初期化子、SPIオブジェクトを生成します。
class Ministick(OpenRTM_aist.DataFlowComponentBase): def __init__(self, manager): OpenRTM_aist.DataFlowComponentBase.__init__(self, manager) self._scaling = [1.0] self._tread = [0.2] self._print_xy = ["NO"] self._print_vel = ["NO"] self._print_wvel = ["NO"] self.x = 0.0 self.y = 0.0 self.spi = spidev.SpiDev() self.spi.open(0, 0)
AD変換器からデータを読む関数を Ministickクラスに追加します。 init() 関数の次あたりに、以下の関数を追記します。
def get_adc(self, channel): sned_ch = [0x00,0x08,0x10,0x18] if ((channel > 3) or (channel < 0)): return -1 r = self.spi.xfer2([sned_ch[channel],0,0,0]) ret = ((r[2] << 6 ) & 0x300) | ((r[2] << 6) & 0xc0) | ((r[3] >> 2) & 0x3f) return ret
X-Yの位置から車輪の速度へ変換する関数をMinistickクラスに追加します。
dev xy_to_wvel(self, x, y): th = math.atan2(y, x) v = math.hypot(x, y) vl = v * math.cos(th - (math.pi/4.0)) vr = v * math.sin(th - (math.pi/4.0)) return (vl, vr)
車輪速度から速度ベクトルへ変換する関数をMinistickクラスに追加します。
def wvel_to_vel2d(self, vl, vr): v = (vr + vl) / 2.0 if v < 0.0: w = - (vr - vl) / self._tread[0] else: w = (vr - vl) / self._tread[0] return RTC.Velocity2D(v, 0.0, w)
コンポーネント初期化時に、ジョイスティックのニュートラル位置をキャリブレーションします。 AD変換器からデータを100回程度読み込み平均し、オフセットデータとして保存します。
def onInitialize(self): : 中略 self.x_offset_v = 0.0 self.y_offset_v = 0.0 for i in range(1, 100): self.x_offset_v += self.get_adc(0) self.y_offset_v += self.get_adc(1) self.x_offset_v = self.x_offset_v / 100.0 self.y_offset_v = self.y_offset_v / 100.0 return RTC.RTC_OK
最後に、onExecute関数を実装します。
def onExecute(self, ec_id): self.x = - (self.get_adc(0) - self.x_offset_v) * self._scaling[0] / 1000.0 self.y = (self.get_adc(1) - self.y_offset_v) * self._scaling[0] / 1000.0 if self._print_xy[0] != "NO": print "(x, y) = ", self.x, self.y self._d_pos.data = [self.x, self.y] self._d_wvel.data = self.xy_to_wvel(self.x, self.y) if self._print_wvel[0] != "NO": print "(vl, vr) = ", self._d_wvel.data[0], self._d_wvel.data[1] self._d_vel.data = self.wvel_to_vel2d(self._d_wvel.data[0], self._d_wvel.data[1]) if self._print_vel[0] != "NO": print "(vx, va) = ", self._d_vel.data.vx, self._d_vel.data.va self._posOut.write() self._velOut.write() self._wvelOut.write() return RTC.RTC_OK
Ministickコンポーネントと、いろいろなものを接続してテストしてみます。
TkMobileRobotCanvasと接続してみます。
Windows上のインストールされているOpenRTM-aist-Pythonのサンプルから TkMobileRobotCanvasを起動します。 同時に、ネームサービスとRTSystemEditorも起動してください。
Createボタンを押し、移動ロボットを一つ生成します。 ネームサーバにコンポーネントが一つ現れるので、SystemEditor上にドラッグアンドドロップします。
次に、Raspberry Pi上でネームサーバとMinistickコンポーネントを起動します。
$ rtm-naming $ ./Ministick.py
RTSystemEditorから、RaspberryPiのネームサーバに接続すると、Ministickコンポーネントが見えますので、SystemEditor上にドラッグアンドドロップします。
Ministick の wvel データポートから先ほど生成した移動ロボットコンポーネントへポートを接続します。
アクティベートすると、両方のコンポーネントが緑色になり操作可能になります。
前述のKobukiの制御、の節に従ってKobukiコンポーネントをRaspberryPi上で起動します。
Ministickコンポーネントを別のRaspberry Pi上で起動します。
それぞれのコンポーネントはローカルのネームサーバ(デフォルト)に参照を登録させて、別のPCからこれら2つのネームサーバにRTSystemEditorで接続します。 Name Service Viewに2つのコンポーネントが見えるはずですので、これら (Ministick の vel と KobukiAIST の targetVelocity) を接続します。(下図参照)
RTSystemEditorのメニューバーの緑色の再生ボタン(全活性化)を押すと、システムが動き出しMinistickでKobukiを操作できます。
Ministickがニュートラル状態でも、TkMobileRobotのロボットやKobukiが少しずつ動く場合があります。これは、ニュートラル状態のキャリブレーションが十分ではないためです。 Ministickコンポーネントを工夫して、使いやすいコンポーネントにしてみましょう。
例えば、キャリブレーションをonActivatedで行うようにすれば、一旦Deactivateして再度Activateすれば零点をリセットできます。 また、onDeactivatedの時には速度0を出力するようにすれば、JyoistickのDeactivateによりロボットが安全に停止します。 あるいは、零点付近に不感帯を設けることで、多少キャリブレーションがずれても、ニュートラル状態で必ず0が出力されるようにできます。
以下のようなパーミッション関係のエラーが出ることがあります。 上述のudevの設定が正しく行われていない可能性がありますので、見直してください。
pi@raspbian-armhf ~ $ ./adc_text.py Traceback (most recent call last): File "./adc_text.py", line 47, in <module> main() File "./adc_text.py", line 25, in main adc = ADC() File "./adc_text.py", line 10, in __init__ self.spi.open(0, 0) IOError: [Errno 13] Permission denied
また、sudo を利用しても実行可能です。
PiRT-UnitにはZigBeeモジュールXBeeを接続するためのコネクタがあります。 RaspberryPiからシリアルデバイス経由で利用して、他のZigBeeモジュールとの通信に利用したり、シリアルコンソールを無線化するのにも利用できます。 Raspbian Wheesyではデフォルトでシリアルコンソールに設定されています。 この解説では、シリアルコンソールをXBeeで無線化する方法を説明します。
XBeeモジュールとPCを接続するにはXBee-USBエクスプローラを利用する必要があります。 XBeeモジュール接続コネクタとUSBコネクタがついており、PCに接続してPCからXBeeの各種設定を行ったり、XBeeをシリアルポートとして利用することができます。
XBee-USBエクスプローラは、様々なメーカーから発売されています。
商品名 | メーカー | 価格 | URL |
AE-XBEE-USB | 秋月電子通商 | 1,280円 | http://akizukidenshi.com/catalog/g/gK-06188/ |
SFE-WRL-08687 | Sparkfun Switch Science |
2,619 円 | http://www.switch-science.com/catalog/30/ http://strawberry-linux.com/catalog/items?code=18128 でも入手可能 |
SFE-WRL-09819 | Sparkfun Switch Science |
2,619 円 | http://www.switch-science.com/catalog/344/ |
デバイスマネージャを開いてください。 Windows7では、「コントロールパネル」→「システムとセキュリティ」→「システム」→「デバイスマネージャー」から開くことができます。 デスクトップに「コンピュータ」がある場合、右クリック→「プロパティー(R)」→「デバイスマネージャー」から開くのが最も早いでしょう。
XBee-USBエクスプローラをPCのUSBポートに接続します。 初めて接続する場合は、デバイスの認識とデバイスドライバのインストールでしばらく時間がかかります。 デバイスドライバのインストールが終了すると、以下のようにデバイスマネージャにCOMポートとして現れます。 この時、どのCOMポートに割り当てられたかを覚えておいてください。(下の例ではCOM8に割り当てられた。)
運悪くドライバが自動でインストールされない場合、FTDI社のチップ(FT232B等)を使ったXBee-USBエクスプローラの場合はFTDI者から直接ドライバをダウンロードしてインストールしてください。
なお、秋月およびSparkfunのXBee-USBエクスプローラでは、Windows7はドライバのインストールは不要でした。
XBeeモジュールは大きく分けて親機と子機に分かれており、そのXBeeモジュールを親機にするか子機にするかはXBee-USBエクスプローラ経由でPCから設定します。
一つのXBeeネットワーク内には必ず1台の親機"Coordinator"が必要で、親機に対して複数の子機がぶら下がる形になります。 一方、購入直後のXBeeモジュールは子機"Router"に設定されており、初めてXBeeネットワークを構成する際には、どれか一つを親機"Coordinator"にしてあげる必要があります。
XBeeモジュールを設定するには、DigiのWebページからX-CTUという設定ソフトウエアをダウンロードしPCにインストールする必要があります。
DigiのX-CTUのダウンロードサイトへ行きます(更新等によるリンク切れがあった場合はMLなどでお知らせいただければ幸いです)。
ページの Diagnostics, Utilities and MIBs の項目をクリックすると、X-CTUのインストーラへのリンクが現れるので、クリックしてダウンロードします。(63MB程度あります。)
ダウンロードした実行ファイル 40003002_C.exe (このファイル名はバージョンアップなどにより変更されるかもしれません) をクリックして実行すると、インストーラが開始されます。指示に従ってインストールを完了してください。
最後に、frimwareのバージョンアップをするか聞いてくることがありますが、特に必要がなければスキップしてください。(結構時間がかかります。)
インストール完了後、X-CTUを起動します。起動後は以下のような画面が表示されます。
X-CTUの「PC-Settings」を選択します。 タブ内のSelect Com PortでXBee-USBエクスプローラデバイスが接続されているCOMポートを選択します。(この例ではCOM8です。) XBee-USBエクスプローラデバイスが接続されているCOMポートが不明な場合は、一旦デバイスをPCから取り外し、デバイスマネージャでなくなるCOMポートを観察するか、X-CTUを再度起動してなくなったCOMポートを見つけるなどして対応するCOMポートを特定してください。
Select Com Portで対象となるCOMポートを選択したら、右下のTest/Queryボタンを押してください。XBeeと通信を行い、以下のようにシリアルナンバーなどを表示します。
次に接続されているXBeeが現在どのような設定になっているか、ファームウエアの情報を読み込みます。 X-CTUの「Modem Configuration」タブをクリックし、下のModem Parameter and Firmwareのエリアの「Read」ボタンをクリックします。 すると、XBeeとの通信が開始され、少し経つと以下のようにXBeeの設定情報が下のエリアにツリー表示されます。
また、「Modem」の部分にXBeeモジュールの種類、「Function Set」の部分にファームウェアの種類、「Version」にファームウェアのバージョンが表示されます。
「Function Set」の部分はおそらく ZIGBEE ROUTER AT となっているはずですが、これはこのXBeeモジュールが"Router"すなわち子機として設定されていることを意味します。
ここで子機"Router"を親機"Coordinator"に変更してみます。 親機すなわり「Coordinator」に変更するために、プルダウンメニューからZIGBEE COORDINATOR ATを選択します。
「Write」ボタンを押すとXBeeへの書き込みが開始されます。1から2分程度で書き込みが終了します。
先ほどのファームウエアの選択時に、ZIGBEE COORDINATOR AT のほかに ZIGBEE COORDINATOR API というファームウエアがあったことに気付かれたかもしれません。 AT とつくものは、ATコマンドでXBeeの設定を行うタイプのファームウエアで、一方APIとつくものは、API経由でXBeeの設定を行うタイプのファームウエアを意味します。
もしXBeeが全く応答しなくなったら、強制的にファームウエアを上書きし出荷状態に戻します。 以下の手順に従って、工場出荷状態に戻してください。
Raspberry Pi上に存在する GPIO ピンのうちのI2C用ピン(2本)を用いると、複数の I2C デバイスを操作することができます。 ここでは、I2C を利用するためのセットアップ、C言語によるプログラム記述の実例、RTコンポーネント化するためのヒントを示します。
を取り上げます。
I2C は2線を用いるシリアルバス通信の一種です。クロック線のエッジを用いてデータ線上で値の授受行い、バス上にある複数デバイスを制御することができます。 バス上にはマスターとスレーブがあり、規格では複数のマスター/スレーブの存在を許しているようですが、実際には単一マスター/複数スレーブによる使用が簡単です。 マイコンなどから利用する場合は、マスターによるクロック信号の送信と、データの通信プロトコル実装などを考慮して実装しなければなりませんが、Raspberry Pi を用いると既存のライブラリを使用して非常に簡単に I2C デバイスを利用することができます。
Raspberry Pi の GPIOポート(26pin)のうち、もともと I2C 通信専用に設定されている GPIO が2本存在します。(下図参照) GPIO 0 が I2C のデータ用ポート、GPIO 1 が I2C のクロック用ポートとしてあらかじめ設定されており、これらを利用することで簡単に I2C 通信を行うことができます。
この2本のポートを用いて I2C デバイスを直接接続するだけで、クロック線のドライブ・通信プロトコルの解釈などはすべて Raspberry Pi上の Linux で行われます。 ユーザーはデバイスファイル (/dev/i2c-*) の読み書きを行うことでデバイスからのデータ取得/デバイスへのデータ出力を実現できます。
複数のデバイスの接続はバス接続(下図)で実現することができます。 デバイス間の調停も Raspberry Pi側である程度は行うことになっています。 なお、上記GPIO 0、GPIO 1ポートは Raspberry Pi 基板上でプルアップ抵抗によりプルアップされていますので、別途プルアップする必要はありません。
Raspberry Pi で I2C 通信を使うためにはいくつのかの設定ファイルを変更する必要があります。 ファイルは root 権限で編集してください。
/etc/modules に以下の一行を追加します。
i2c-dev
これにより、/dev/i2c-* が有効になります。
/etc/modprobe.d/raspi-blacklist.conf の以下の一行をコメントアウトします。
# blacklist i2c-bcm2708
以上の変更が終了したら、変更を反映するために再起動してください。
i2c-tools はコマンドラインから I2C デバイスへアクセスするためのツールです。 実際に開発する際には、コマンドラインから I2C デバイスの動作を確認したいことがたびたびありますので、事前に i2c-tools をインストールしておいてください。
sudo apt-get install i2c-tools
として、インストールします。
上記のブロック図では、I2C デバイスは SDA、SCL の2線のみが配線されていましたが、実際には当然各デバイスに電源を供給してあげる必要があります。 それほど消費電力の大きくない I2C デバイスであれば、Raspberry Pi の GPIO ピンヘッダ 26pin のうち、2,3pin(5V)、1,17pin(3.3V)からでている電源を利用することができます。 I2C デバイスの説明書・データシートを参照した上で、5V ないし 3.3V のうち適切な電源を供給するようにしてください。 また、PiRT-Unit には I2C用の4ピンのコネクタが付属しており、SDA、SCL、3.3V、GND が配線可能です。
今回用いる I2C デバイスはすべて 3.3V で動作するため、Raspberry Pi の 1,17pin(3.3V)から各デバイスに電源を供給します。 以下にブレッドボード上に上記の4つのデバイスを配置した際の配線図を示します。
配線の際にはデバイスの説明書/データシートをよく読んで間違いのないよう配線してください。配線を間違うとデバイスが認識されないだけでなく、場合によってはデバイスが破壊される可能性もあります。
デバイスの種類によっては、使用方法によって適宜ジャンパが必要なものや、I2Cの2本の信号線以外に割り込み、リセット信号などをが必要なものもあります。その場合は、Raspberry Pi の GPIO ピンを適宜利用し、プログラム側から制御する必要があります。
上記の配線が完了したら、Raspberry Pi上から i2c-tools を利用してデバイスを操作することができます。 まずは、i2cdetect コマンドで、I2C バスに接続されているすべてのデバイスのアドレスを確認してみましょう。以下のようにタイプすると、下図のような表示が現れます。
$ sudo i2cdetect 1
図では4個のデバイスが存在していることが確認できます。-(マイナス)以外に16進数の数字が表示されていますが、それぞれが各デバイスのアドレスを表しています。内訳は、
となっています。このコマンドと各デバイスの説明書/データシートを突き合わせることで、Raspberry Pi が I2C デバイスを認識できているかを確認することができます。 なお、Raspberry Pi のリビジョンによって、コマンドの後ろに入れるバス番号が0の場合と1の場合がありますので注意してください。
デバイスに実際にデータを書き込むには i2cset コマンドを、デバイスからデータを読み込むにはi2cgetコマンドを使用します。(下図参照)
// LSM303DLHCの地磁気センサーへアクセス $ sudo i2cset -y 1 0x1e 0x00 0x14 $ sudo i2cset -y 1 0x1e 0x01 0x20 $ sudo i2cset -y 1 0x1e 0x02 0x00 $ sudo i2cget -y 1 0x1e 0x32 $ sudo i2cget -y 1 0x1e 0x31 $ sudo i2cget -y 1 0x1e 0x03 $ sudo i2cget -y 1 0x1e 0x04 $ sudo i2cget -y 1 0x1e 0x05 $ sudo i2cget -y 1 0x1e 0x06 $ sudo i2cget -y 1 0x1e 0x07 $ sudo i2cget -y 1 0x1e 0x08 $ sudo i2cget -y 1 0x1e 0x09 // LSM303DLHCの加速度センサーへアクセス $ sudo i2cset -y 1 0x19 0x20 0x27 $ sudo i2cget -y 1 0x19 0x28 $ sudo i2cget -y 1 0x19 0x29 $ sudo i2cget -y 1 0x19 0x2a $ sudo i2cget -y 1 0x1e 0x2b $ sudo i2cget -y 1 0x1e 0x2c $ sudo i2cget -y 1 0x1e 0x2d
この例では、LSM303DLHCの説明書に従って、まず地磁気センサを動作させるために0x1eのアドレスのデバイスに対して内部レジスタ0x00~0x02に所定の数値を書き込み、内部レジスタ0x31~32、0x03~0x09を読み出しています。 その後、LSM303DLHCの加速度センサを動作させるため、0x19のアドレスのデバイスに対して内部レジスタ0x20に所定の数値を書き込み、0x28~0x2dまでの数値を読み込んでいます。
i2c-toolsのコマンド群はルート権限でのみ実行可能であるのでsudoを使用するか、sudo bashとしてrootになって実行する必要がありますので注意してください。
プログラムからこれらのデバイスにアクセスするには、デバイスファイル (/dev/i2c-0 または /dev/i2c-1) をオープンし、読み書きすることでデバイスのレジスタ操作および値の読み出しを行います。
ただし、I2Cデバイスの種類によっては特有の初期化シーケンスを持っていたり、デバイスのデータの読み書きに一定の手順を要求するものがあります。各デバイスの説明書やデータシートを確認しながらプログラムを作成する必要があります。 (インターネット上には、RaspberryPi/AVRマイコン/ArduinoなどからのI2Cデバイスの制御方法に関する情報が色々あるようですので、そちらも参考にしてください。)
以下に、L3GD20デジタル3軸ジャイロセンサモジュールを用いたサンプルプログラムを掲載します。
このモジュールはI2CおよびSPIでの通信が可能なセンサモジュールで、I2Cデバイスとして利用する場合、アドレスを0x6a、0x6bの2種類から選択可能です。ここではアドレスを0x6aとして使用しています。
内部レジスタは、
0x0f | 常に0xd4を出力 |
0x20 | 0x0fを書き込むことで動作開始 |
0x28~2d | 3軸ジャイロデータが格納される |
このほか、検出レンジ、サンプリングレート等の設定も可能ですが、ここでは触れません。
以下にプログラムを示します。 なお、こちらからダウンロードすることもできます。また、I2CセンサをRTコンポーネント化した、データ取得コンポーネントおよびディスプレイコンポーネントもサンプルとして示します。
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <unistd.h> #include <linux/i2c-dev.h> // I2C用インクルード #include <fcntl.h> #include <sys/ioctl.h> #include <wiringPi.h> // delay関数用にインクルード // プロトタイプ宣言 void L3GD20_readData(int *gyrodata, int fd); void L3GD20_write(unsigned char address, unsigned char data, int fd); unsigned char L3GD20_read(unsigned char address, int fd); void L3GD20_init(int fd); int main(int argc, char **argv) { int i2c_fd; // デバイスファイル用ファイルディスクリプタ // char *i2cFileName = "/dev/i2c-0"; // I2Cデバイスファイル名 char *i2cFileName = "/dev/i2c-1"; // RaspberryPiのリビジョンに合わせて変更 int i2cAddress = 0x6a; // L3GD20のI2Cアドレス int gyroData[3]; // ジャイロ3軸(x,y,z)データ格納用 printf("i2c Gyro(L3GD20) test program\n"); delay(500); // I2Cデバイスファイルをオープン if ((i2c_fd = open(i2cFileName, O_RDWR)) < 0) { printf("Faild to open i2c port\n"); exit(1); } // L3GD20用にセット if (ioctl(i2c_fd, I2C_SLAVE, i2cAddress) < 0) { printf("Unable to get bus access to talk to slave\n"); exit(1); } //デバイス初期化 L3GD20_init(i2c_fd); // 1秒ごとに20回ジャイロデータを取得、表示 int i; for(i=0; i<20; i++){ // デバイスからデータ取得 L3GD20_readData(gyroData, rtc); // 取得したデータを校正して表示、1秒待ち printf("x, y, z : %5.2f, %5.2f, %5.2f\n", (float)gyroData[0]*0.00875,(float)gyroData[1]*0.00875, (float)gyroData[2]*0.00875); delay(1000); } return; } // L3GD20用 1バイト書き込みルーチン:addressで示すレジスタにdataを書き込む void L3GD20_write(unsigned char address, unsigned char data, int fd) { unsigned char buf[2]; buf[0] = address; buf[1] = data; if((write(fd,buf,2))!=2){ printf("Error writing to i2c slave\n"); exit(1); } return; } // L3GD20用 1バイト読み出しルーチン: addressで示すレジスタの値を読み出す // 戻り値がレジスタ値 unsigned char L3GD20_read(unsigned char address, int fd) { unsigned char buf[1]; buf[0] = address; if((write(fd,buf,1))!= 1){ // addressを一度書き込む所に注意 printf("Error writing to i2c slave\n"); exit(1);} if(read(fd,buf,1)!=1){ printf("Error reading from i2c slave\n"); exit(1);} return buf[0]; } // L3GD20用 ジャイロデータ読み出しルーチン: // 整数値配列へのポインタを使ってデータを受け渡す void L3GD20_readData(int *gyrodata, int fd) { unsigned char data[6]; // センサから3軸に対して2バイトずつデータを読み出す int i; for(i=0; i<6; i++){ data[i]=L3GD20_read(0x28+i,fd); } // 各数値を32bit幅の整数に整形する // センサの数値精度が16bit・2の補数表現での出力のため、シフトで加工 gyrodata[0]=((int)data[1]<<24|(int)data[0]<<16)>>16; gyrodata[1]=((int)data[3]<<24|(int)data[2]<<16)>>16; gyrodata[2]=((int)data[5]<<24|(int)data[4]<<16)>>16; return; } // L3GD20用 ジャイロデータイニシャライズルーチン void L3GD20_init(int fd) { unsigned char Data; printf("L3GD20 init seq. start\n"); // L3GD20 動作確認 // L3GD20の0x0fレジスタは常に0xd4にセットされているため動作確認ができる Data = L3GD20_read(0x0f,fd); if(Data != 0xd4){ printf("L3GD20 is not working\n"); exit(1);} delay(10); // レジスタへの書き込みチェックとイニシャライズを同時に行う printf("read OK, Now writing check...\n"); // 0x20レジスタに0x0fを書き込むことで動作させる L3GD20_write(0x20, 0x0f, fd); // 0x20レジスタに実際に0x0fが書かれたか確認 Data = L3GD20_read(0x20,fd); if(Data != 0x0f){ printf("Writing miss\n"); exit(1); } printf("Writing OK\n"); delay(10); return; }
RaspberryPi上でI2Cデバイスにアクセスするプログラムは以上のように記述することができます。上記のコードをRTコンポーネント化する場合には、例えば初期化部分をRTコンポーネントのonInitializeまたはonActivatedに実装、デバイスからデータを取得して表示するルーチンを onExecute に実装し、OutPortから出力するようにすれば、センサデータを出力するコンポーネントが出来上がります。
実行コンテキストの周期は、I2Cデバイスおよびバスの速度と、バスに接続されているI2Cデバイスの数、それぞれのI2Cデバイスのサンプリングレートなどから決める必要があります。
複数のデバイスをI2C接続した状態でこれらをコンポーネント化する場合、各デバイス間でデータの読み書きのスケジューリングを考慮する必要があります。 実現手法として考えられるのは、Kobuki は Yujin Robotics から発売されている研究用移動ロボットです。 掃除機ロボット Roomba とほぼ同様の大きさで、USBシリアル接続でPC等から制御ができるようになっています。 また、IO、シリアル入出力、電源コネクタ、ボタン、LED等が装備されており、実験用ロボットとしての利用に適しています。
以下の Kobuki のサンプルを動作させるために必要なソフトウエアのインストールなどを行うスクリプトがこちらからダウンロードできます。
$ wget http://svn.openrtm.org/Embedded/trunk/RaspberryPi/tools/rpi.sh $ chmod 755 rpi.sh $ sudo ./rpi.sh hostname --type kobuki
で、以下の解説で行っている環境構築と Kobuki のサンプルのコンパイルが自動で行われます。
下図は Kobuki のメインパネルです。
Raspberry Pi への電源供給に 5V1A DC出力コネクタ、Raspberry Pi との接続には USBコネクタを利用します。
Kobuki には 5V 1A 出力可能な DC出力コネクタがあり、Raspberry Pi の電源をここから供給することができます。
5V1A 出力コネクタは以下の型番のものを使用します。
Kobuki 5V1A用コネクタ | |
ハウジング | Molex PN : 43645-0200 |
ターミナル | Molex PN : 43030-0001 |
RTロボットショップなどでも購入できます。
下図のような DCコネクタと USBの変換ケーブルを作成することで、Raspberry Pi へ電源を供給します。
近年ではスマートフォン用の USB出力端子がついたバッテリーが多数発売されていますので、こういった電源も利用できます。
Kobuki に付属している USB ケーブルで Kobuki と Raspberry Pi を接続します。 Raspberry Pi側からは /dev/ttyUSB0 として見えます。
$ ls /dev/ttyUSB* /dev/ttyUSB0
Raspberry Pi を Kobuki に搭載して、電源と USBを接続します。Raspberry Pi を無線LAN接続にすれば、無線遠隔操作可能な Kobuki になります。
Kobuki 動作時に脱落する可能性がありますので、Raspberry Pi はマジックテープなどで固定するとよいでしょう。
前節でも RTコンポーネントのコンパイルのテストを行いましたが、ここで再度おさらいします。まずは、KobukiAIST RTコンポーネントを以下のリポジトリからチェックアウトしビルドします。
$ svn co http://svn.openrtm.org/components/trunk/mobile_robots/kobuki $ cd kobuki $ mkdir build $ cd build $ cmake -DCMAKE_INSTALL_PREFIX=/usr .. $ make $ cd src $ sudo make install
試しに起動してみます。デバイスファイル /dev/ttyUSB0 へのアクセスには root 権限が必要ですので、sudo を使って起動しています。
$ rtm-naming $ sudo /usr/lib/openrtm-1.1/rtc/KobukiAISTComp
RTSystemEditor を起動し、Raspberry Pi のホスト名またはIPアドレスに接続すると、KobukiAIST0 というコンポーネントが見えるはずです。 クリックして Configuration ダイアログを表示させてみてください。
LED1 や LED2 などの操作が行えるようになっていますので、radio ボタンで RED や GREEN などをクリックしてください。LED が点灯します。
KobukiAIST コンポーネントをRaspberry Pi 起動時に自動的に起動するようにします。 これにより、Kobuki に電源を投入すると、Raspberry Pi および KobukiAIST コンポーネントが自動的に起動するようになり、Raspberry Pi にいちいちログインしなくとも Kobuki を RTC 経由で操作できるようになります。
以下のようなスクリプトを /etc/kobuki.sh として作成します。
$ sudo vi /etc/kobuki.sh
kobuki.sh の内容な以下の通りです。
#!/bin/sh # # KobukiAIST RTC launch script # # Copyright Noriaki Ando <n-ando@openrtm.org> # 2011.03.27 # # This script should be executed from rc script like a rc.local # as the following command line. # # ns=/usr/bin/rtm-naming kobukiRTC=/usr/lib/openrtm-1.1/rtc/KobukiAISTComp workdir=/tmp/kobuki \$ns sleep 5 if test -d $workdir ; then echo "" else mkdir \$workdir fi cd $workdir while : do rm -f \$workdir/*.log \$kobukiRTC sleep 5 done
実行権限をつけます。
$ sudo chmod 755 /etc/kobuki.sh
さらに、自動的に起動するように /etc/rc.local の最後の exit 0 の手前に以下のような一行を挿入します。
/etc/kobuki.sh 2>&1 | perl -p -e 's/\n/\r\n/g' 1>&2 & exit 0
これで、Raspberry Pi が起動すると、KobukiAIST コンポーネントも自動的に起動します。 また、万一 KobukiAIST コンポーネントを exit で終了させても、5秒後再度起動します。 Kobuki に電源が入っている限り、KobukiAIST コンポーネントは常駐し続けるようになっています。
TkJoystick は OpenRTM-aist-Python にサンプルとして含まれているコンポーネントです。ただし、出力はジョイスティックのX-Y値と、対向2輪型移動ロボットの車輪速度用の出力のみで、2次元速度ベクトル (TimedVelocity2D) 出力は有りません。
TkJoyStick コンポーネントを改良して、2次元速度ベクトル (TimedVelocity2D) の出力をするようにし、Kobukiと接続して操作してみてください。
Windows では以下のディレクトリーもインストールされています。(x.yはバージョン)
TkJoystick.py の中では、左右の車輪速度を計算しています。ここから、移動ロボットの運動学を考慮すれば、速度 v および角速度 ω を計算することができます。 (参考のため、東北学院大学の熊谷先生のページへのリンクを張っておきます。)
なお、TimedVelocity2D は以下のようなデータ構造となっています。
struct Velocity2D { double va; // 角速度 [rad/s] double vx; // 並進速度(前方) [m/s] double vy; // 並進速度(横方向) [m/s] 対向2輪型では0 }; struct TimedVelocity2D { Time tm; Velocity2D data; };
Kobuki をセンサーを利用して自律的に移動させてみます。 Kobuki は、バンパセンサー、近接センサー(遠・近)、Cliffセンサーを装備されています。 ここでは、Roomba っぽく、前進し続けて壁を検知したら、少し下がり、回転し、再び前進をする、というアルゴリズムで動かしてみます。 (Roomba はもう少し賢く動きますが。。。)
KobukiAIST RTC のセンサ出力は以下のようになっています。 IRセンサはドックからの赤外線による信号を受けるためのもので、障害物検知には使用できません。したがって、バンパおよび崖センサーのみが障害物・崖検知に利用できます。
No. | enum | 意味 |
0 | RIGHT_BUMPER | 右バンパ |
1 | CENTER_BUMPER | 中央バンパ |
2 | LEFT_BUMPER | 左バンパ |
3 | RIGHT_WHEEL_DROP | 右車輪脱輪 |
4 | LEFT_WHEEL_DROP | 左車輪脱輪 |
5 | RIGHT_CLIFF | 右崖センサ |
6 | CENTER_CLIFF | 中央崖センサ |
7 | LEFT_CLIFF | 左崖センサ |
8 | RIGHT_IRFAR_RIGHT | 右IR/ドック右遠 |
9 | RIGHT_IRFAR_CENTER | 右IR/ドック中央遠 |
10 | RIGHT_IRFAR_LEFT | 右IR/ドック左遠 |
11 | RIGHT_IRNEAR_RIGHT | 右IR/ドック右近 |
12 | RIGHT_IRNEAR_CENTER | 右IR/ドック中央近 |
13 | RIGHT_IRNEAR_LEFT | 右IR/ドック左近 |
14 | CENTER_IRFAR_RIGHT | 中央IR/ドック右遠 |
15 | CENTER_IRFAR_CENTER | 中央IR/ドック中央遠 |
16 | CENTER_IRFAR_LEFT | 中央IR/ドック左遠 |
17 | CENTER_IRNEAR_RIGHT | 中央IR/ドック右近 |
18 | CENTER_IRNEAR_CENTER | 中央IR/ドック中央近 |
19 | CENTER_IRNEAR_LEFT | 中央IR/ドック左近 |
20 | LEFT_IRFAR_RIGHT | 左IR/ドック右遠 |
21 | LEFT_IRFAR_CENTER | 左IR/ドック中央遠 |
22 | LEFT_IRFAR_LEFT | 左IR/ドック左遠 |
23 | LEFT_IRNEAR_RIGHT | 左IR/ドック右近 |
24 | LEFT_IRNEAR_CENTER | 左IR/ドック中央近 |
25 | LEFT_IRNEAR_LEFT | 左IR/ドック左近 |
26 | KOBUKI_DOCKED | ドック完了 |
これらの出力を受けるため RTC::TimedBooleanSeq 型の InPort が一つ必要になります。 また、Kobuki に移動速度指令を出力するための TimedVelocity2D型の OutPort が一つ必要になります。
基本プロファイル | |
コンポーネント名称 | KobukiAutoMove |
モジュール概要 | Kobuki auto move component |
バージョン | 1.0.0 |
ベンダ名 | AIST |
アクティビティ | |
onInitialize、onFinalize、onActivated、onDeactivated、onExecute | |
データポート | |
[in] bumper | |
概要 | センサ情報 true:障害物検出(バンパ接触、車輪落下、崖検知) false:障害物無し |
データ型 | TimedBooleanSeq |
詳細 | data[0]: 右バンパ、data[1]: 中央バンパ、... data[7]: 左崖センサ(上の表参照) |
[out] targetVelocity | |
概要 | 移動ロボットの速度ベクトル |
データ型 | TimedVelocity2D |
詳細 | vx: 並進速度、vy: 0.0、va: 角速度 |
単位 | vx [m/s]、va [rad/s] |
以上の情報を手掛かりに、Kobuki を自律移動させる簡単なコンポーネントを作成してみてください。 コンポーネントの接続でうまく行かない場合は、トラブルシューティング をご覧ください。
Kobuki の速度指令は TimedVelocity2D という型で、上でも示しましたが、以下のようなデータ構造です。
struct Velocity2D { double va; // 角速度 [rad/s] double vx; // 並進速度(前方) [m/s] double vy; // 並進速度(横方向) [m/s] 対向2輪型では0 }; struct TimedVelocity2D { Time tm; Velocity2D data; };
対向2輪型移動ロボットでは、vyは常に0.0であると考え、たとえば直進なら
va = 0.0; vx = 0.2; vy = 0.0;
となります。後進するなら、
va = 0.0; vx = -0.2; vy = 0.0;
であり、その場で旋回するなら
va = 0.0; vx = 0.0; vy = 1.0;
となります。
InPort にデータが来ていたら、データを読み込みバンパ情報を取り出します。バンパ情報は、TimedBoolSeq というデータ型の .data という配列のメンバに格納されており、上の表で0,1,2番目の要素であることがわかります。 これらのどれかが true になっていたらバンパで衝突を検知したということですから、いったん下がり、旋回します。そして、再び前進します。 これらの動きを TimedVelocity2D のメンバーにそれぞれ設定して OutPort に writeすれば、速度指令データは Kobuki に伝達されます。 アルゴリズムのフローチャートを下に示します。
どのくらい下がるか・下がったか、あるいは旋回するか・したかを計測しながら制御するのが理想ですが、簡単のために sleep関数を使用することもできます。 Linuxではcoil::sleep が使えます
coil::sleep(coil::TimeValue(0.01); // 10ms待つ
Windows では coil::sleep の精度が悪いので、Sleep関数を利用したほうがよいでしょう。 これらのヒントを基に、Kobuki を自律移動させるような制御コンポーネントを作成してみてください
解答として、上記の TkJoyStick コンポーネントと自律移動コンポーネントを以下に示します。
アカデミックスカラロボットはヴイストンが販売しているロボット制御学習用の水平多関節型ロボットアームです。
アカデミックスカラロボット制御の RTC については以下のページを参考にしてください。
この章ではアカデミックスカラロボットを Kobuki のプレートに固定する手順を説明します。
名前 | 数量 |
Kobuki | 1台 |
プレート | 1枚 |
支柱(5cm) | 8本 |
アカデミックスカラロボット | 1台 |
木ネジ(2cm以上) | 4本 |
アカデミックスカラロボットの仕様 | |
自由度 | 4自由度 + ハンド |
サーボモーター | RS304MD |
通信方法 | HID USB - UART ブリッジ |
プレートに直接スカラロボットを取り付ける手順を説明します。
まずはプレートにキリ等で下穴をあけます。 以下の赤い点の位置に穴をあけてください。
スカラロボットを土台に取り付けて、土台をプレートに固定する方法について説明します。
Kobuki のプレートに固定するために、スカラロボットの土台に穴をあけます。 以下の図の赤い部分に穴をあけてください。穴の大きさは使用する木ねじの大きさで決めてください。
まずスカラロボットを土台に取り付けます。 図のように逆向きの取り付けた後、ユリアねじで固定してください。
予めプレートにはキリ等で下穴をあけておいてください。 土台の穴をあけた部分に木ネジを差し込んでネジでプレートと接合すれば完成です。
まずは Kobuki に支柱を4本立てます。 レーザーレンジセンサー、Raspberry Pi は両面テープなどで Kobuki に接着しておいてください。
この章ではサインスマートが販売している4自由度ロボットアームを Kobuki に取り付ける手順を説明します。
4自由度ロボットアーム制御の RTC については以下のページを参考にしてください。
この作業には必要なものは以下の通りです。
名前 | 数量 |
Kobuki | 1台 |
プレート | 1枚 |
支柱(5cm) | 8本 |
4自由度ロボットアーム | 1台 |
Arduino Uno※ | 1台 |
ジャンパーコード | 15本以上 |
ブレッドボード | 1枚 |
電池ボックス 単3×4本用 | 1個 |
単三電池 | 4本 |
木ネジ(2cm以上) | 4本 |
※Intel Edison、Raspberry Pi から制御する場合は PCA9685 搭載のサーボドライバでも可
4自由度ロボットアームの仕様 | |
自由度 | 4自由度 |
サーボモーター | MG995、SG90 9G |
4自由度ロボットアームには最初から取り付け用の穴があいているためこちらへの加工は不要です。
アカデミックスカラロボットの手順と同じです。
Raspberry Pi の設定画面(Raspi-config)にて SSH を有効に設定することで、sFTP が利用できるようになります。 Windows から sFTP で Raspberry Pi に接続する場合には sFTP に対応したソフト(WinSCP など)を使用します。
こちらから WinSCP のダウンロードページに移動することができます。
Raspbian のGUI 環境を開発用PC上で操作するために、VNCサーバーをインストールします。
こちら から VNC をダウンロードすることができます。
$ su # apt-get install tightvncserver
インストール途中で、VNCサーバーに接続する際のパスワード入力を求められますので、適当なパスワードを設定します。 VNCサーバーをインストール後、開発用PC からターミナルを使用して Raspberry Pi に SSH 接続し、VNCサーバーを起動します。
$ vncserver :1 -geometry 1024x600 -depth 16 -pixelformat rgb565
Windows から VNCサーバーに接続する場合には、VNCクライアントソフト(RealVNC など)を使用します。