2013年06月09日

RaspberryPiを使って太陽電池の充電状態をXivelyにアップロードする機器を作る

先日、.NET Micro Frameworkの勉強会の準備会というのが梅田でありまして、参加させて頂きました。

その時、参加されていた林田さんと吉田さんから、Xivelyというネットサービスを教えてもらいました。
Xivelyというのは、過去CosmやPathubeと呼ばれていたネットサービスで、センサーなどからのデータをアップする事が出来るものです。林田さんの資料の言葉を借りますと、「Xively はセンサデータを公開し合うユーチューブを意識したサービスとしてスタートした経緯がある。そのデータ投稿管理が良く出来てるので、簡易なM2Mクラウドとして利用する。」との事です。

Xivelyへのアップロードは、Xively側で各種環境向けにライブラリを公開してくれていて、それを利用することで手軽に実施出来ます。
2013年6月9日時点では、Android、Arduino、mBed、C、ElecricImp、Java、JavaScript、Objective-C、Python、Rubyに対応したライブラリが公開されているようです。

xivelyLib.png
今回は、ベランダに設置した以下のような太陽電池を使って、バッテリーを充電し、それをモニタリングしてみたいと思います。
solar.jpg
そこで、Raspberry Piで簡単な製作を行なってみました。本記事はその取り組みの紹介になります。
今回、僕はRaspberryPiで太陽電池から鉛シール蓄電池へ充電を行い、そのバッテリー電圧をモニターしてXivelyにアップロードしてみることにします。

測定に使用するモジュールはストロベリーリナックスで販売されている、「INA226 I2Cディジタル電流・電圧・電力計モジュール」を使用します。これは、I2C接続で電圧と電流をモニターできるものです。
ina226.jpg

このモジュールは以前本ブログの「Raspberry PiのI2Cを利用して簡易電流・電圧計を作る」で取り上げたものです。
http://projectc3.seesaa.net/article/350916175.html

システム構成はこんな感じです。
xively_solar_blockdiagram.png

Raspberry Pi側のソフトはCで作成しました。XivelyのライブラリはC用のものをそのまま使用しています。
Cのライブラリの実装は、普通のPOSIX環境で実行できるもののようで、実際にMacOSX上と、Raspberry Pi上で試しましたところ、そのままアッサリ問題なく動いてくれました。
制御はシンプルに、2秒ごとにバッテリー電圧と充電電流をI2C経由で取得し、Xively側にアップロードします。
ソースコードはこちらです。
https://github.com/yishii/rpi_solar_charger_with_xively

上記リポジトリ内に、Xivelyのアップロードに使用するライブラリ(libxively.a)のソースも含んでいます。src直下でmakeすると、libxively.aとメインプログラムのビルドをまとめて行います。

(なお、conf_xively.hにXivelyで使用するキー(API KEYやFEED ID等)に関する情報を設定するようにしています)

こんな感じで確認できます。(電流の系は接続してないので0のままです^^;) xively_SS.png
実際のXivelyのURL : https://xively.com/feeds/2077712670

IMG_20130609_181657resized.jpg
と、いうわけで、Raspberry Piを使用することで、とてもお手軽に測定データをアップして共有する事ができます。今回は有線LAN接続していますが、USB-3Gドングルを接続するなどすると、外に設置した(ex.ビニールハウスに設置して、温度をアップするとか)機器のデータのアップロードも非常に簡単に行えますし、結構楽しそうですね。

Raspberry Pi Type B 512MB
Raspberry Pi Type B 512MB
posted with amazlet at 13.06.09
RS Components Ltd
売り上げランキング: 457

Raspberry Piユーザーガイド
Eben Upton Gareth Halfacree
インプレスジャパン
売り上げランキング: 2,358

50W 単結晶ソーラーパネル 太陽光パネル
POWERTEC
売り上げランキング: 3,194

図解入門よくわかる最新太陽電池の基本と仕組み (How‐nual Visual Guide Book)
東京理科大学総合研究機構太陽光発電研究部門
秀和システム
売り上げランキング: 193,610
posted by いしいっち at 19:18| Comment(0) | TrackBack(0) | Raspberry Pi | このブログの読者になる | 更新情報をチェックする

2013年05月12日

Raspberry Pi+GPSで現在地図+ストリートビューを表示する車載機器を作ってみる

GWで実家に帰省してて時間もあるというわけで、Raspberry Piで、非Xで、Raspberry Piならではのアプリケーションを実現したい、と思っていたら、Raspbian "wheezy"の/opt/vc/以下にRaspberry Piのハードを活用できる各種サンプルコードが入っていました。主に、OpenMAXを叩いてどうこう、みたいなのが多いようです。

このコードをベースに、VideoCoreのハードを叩いて何か作ろう、と思いました。

さて、そのネタとして、たまたま僕が普段乗っている軽トラには非常に地図データが古いカロッツェリアのカーナビを搭載してまして、最近はスマホでナビしている関係で全然活用してませんでした。
このナビにはコンポジットビデオ入力がついているので、そこにRaspberry Piを接続し、たまたま手元にあったGPSモジュール(ストロベリー・リナックスで販売しているもの)を使用して、現在地のGoogle MapとStreet View表示するシステム MapTracer を作ってみることにしました。

/opt/vc以下にハードのデコーダーを使用してデコードのみ行なっているとおもわれるサンプルコード(hello_jpeg)があったので、これを参考にハードでコードしてフレームバッファ展開しようと思いましたが、結局ソフトデコードで全然問題なさそうでしたので、結局/opt/vc以下のコードベースのハードデコードは使ってません。


軽トラに取り付けた様子

IMG_20130504_183859resized.jpg
雨降ってます。笑
IMG_20130504_182919resized.jpg

IMG_20130504_182913resized.jpg

なんかー、若干(?)設置イメージがあやしいです。笑

MapTracerの構成
構成は以下のようにしました。
maptracer_image.png

maptracer_stack.png
GPSからのデータはRS-232Cで受信します。RS-232C-USB変換ケーブルを使用しました。Raspberry Piのピンヘッダ上のUART(/dev/ttyAMA0)でも通信出来るでしょう。
このGPSのデータ形式は多くのGPSモジュールで採用されているNMEA0183のタイプですので、オープンソースのNMEA Libraryを使用させていただき、パースすることにします。

http://nmea.sourceforge.net/

パースした結果の位置情報から、地図のデータを取得するのに、Google APIの「Static Maps API」と「Street View Image API」を使用します。Google APIは以下のサイトに入って有効にしておきます。
https://code.google.com/apis/console/

enable_api_map_and_stview.png
APIを使用したアクセスにはAPIキーが必要なのですが、それは上記Google APIのサイト内「API Access」にて取得できます。

APIのやりとりにhttpのリクエスト・レスポンスを使用します。その動作の実現にlibcurlを使用します。

GUIの描画及びキーイベント等のハンドリングにはSDL(Simple DirectMedia Layer)を使用します。
SDLの構造はこんな感じです(WikipediaのSDLライブラリの項目より)
sdl_architecture.png
SDLを使用して作成したコードは複数のプラットフォーム間で一定の互換性を持って使用できるようです。今回Linuxの非Xで構築しようとしていましたが、同じバイナリをXから起動するとマルチウィンドウでそのままうまく動作してくれました。

今回は静止画データを扱うので、SDLとその補助ライブラリであります「SDL_image」を使用しました。

実行環境の整備と、ソースダウンロード+ビルド方法

今回使用するRaspberry PiのディストリビューションはRaspbian "wheezy"の2013/2/9のもの(2013-02-09-wheezy-raspbian.zip)です。
これをRaspberry Piで起動し、SDL、libcurl等のセットアップを行っていきます。
$ sudo apt-get update
$ sudo apt-get install curl libcurl4-openssl-dev libsdl-dev
ついでに、今回使用するイーモバイルの3Gドングル D31HW用にwvdialとusb-modeswitchもインストールします。
$ sudo apt-get install usb-modeswitch
ここでudevのキックするか再起動する
$ sudo apt-get install wvdial
★ここでGPSモジュールがボードに繋がっていると、wvdialが実施する初期設定から戻ってこなくなので注意。
また、SDL_Imageの共有ライブラリのシンボリックリンクを貼っておきます(何故か張ってなかったので)。
$ cd /usr/lib/arm-linux-gnueabihf/
$ sudo ln -s libSDL_image-1.2.so.0 libSDL_image.so

MapTracerのコード(+NMEA Library)はgithubに上げてあります。
https://github.com/yishii/MapTracer

ソースコードを取得される場合には、
$ git clone https://github.com/yishii/MapTracer.git
とします。(RPiでも、gitがセットアップしてあれば(sudo apt-get install git)そのまま取得出来ます)

ここで、handle_googleapi_key.hに取得したAPI KEYを設定して下さい。

#ifndef __HANDLE_GOOGLEAPI_KEY_H__
#define __HANDLE_GOOGLEAPI_KEY_H__

#define GOOGLE_API_KEY "SET_YOUR_OWN_API_KEY_TO_HERE!" // ★ここにAPIキーをセットする!

#endif

ビルドは、
$ cd ./src
$ make
とするだけです。ビルドに成功すると、「maptracer」というプロセスが生成されています。

起動と操作方法
いくつかのオプションで動作を指定出来ます。-p オプションは必須です。
maptracer [option]
-p [tty_device] : GPSを接続したポートを指定する。例)-p /dev/ttyUSB2
-c : コンポジット出力対応に画面解像度を落とす
-d : デモモード(GPSが何を言おうと大阪駅前を指す)

また、操作ですが、キーボードで行います。
[1] : Google Mapモードへ
[2] : Google Street Viewモードへ
[0] : アプリ終了
出来れば、画面の左右にストリートビューとマップを同時表示する画面作ったほうがよかったですね。そういえば。。

IMG_20130512_202227.jpg

GPSと3Gドングルのデバイス名の固定化
今回使用したイーモバイルの3Gドングル D31HWは/dev/ttyUSB*として認識します。
GPSモジュールはUSBシリアル変換ケーブル(PL2303を使用したもの)を使用したのですが、これも/dev/ttyUSB*として認識します。
認識した順序でデバイス名が割り振られるので、番号が変化するのは固定的にデバイス名を指定して起動したい場合には不都合です。
そこで、3Gドングルは/dev/ttyUSB_3G、GPSモジュール(PL2303のUSB)は/dev/ttyUSB_GPSとして認識するようにしてみます。
ここでudevルールファイルを設定します。以下のようなファイルを用意しました。
これを例えば「/etc/udev/rules.d/45-local.rules」というファイル名として保存します。
# udev rules
ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", NAME="ttyUSB_GPS"
SUBSYSTEM=="tty", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="143a", ATTRS{devnum}=="5", SYMLINK="ttyUSB_3G"
Raspberry Pi電源投入後自動で3G接続しアプリ起動するようにする
/etc/rc.localの最後の方に以下のように記載しました。maptracerのパス等はカスタマイズして下さい。
/usr/bin/wvdial &
sleep 20
/home/pi/MapTracer/src/maptracer -p /dev/ttyUSB_GPS


作ってみて
地図はきちんと追従してくれて楽しいです。特に、ストリートビューが楽しいかも、って思いました。ただ、自分が運転してると危なっかしくて画面見てられません。笑

助手席で見たいです。(出来れば)
また、GPSモジュールですが、今回使用したものは1Hz出力のものです。10Hz出力のものだとかなり細かく動いてもっと楽しいかもしれません。

ギモン
Raspberry PiのHDMI出力での使用時には問題ないのですが、コンポジット出力時はSDL_SetVideoMode関数の第二引数(画面の高さ)を400程度にしておかないとAPI内で落ちてしまうようでした。ひとまずコンポジット出力の時は400にするようにしています。別にコンポジット出力の解像度にバインドされている と思ってなかったのですが、そういうもんなのでしょーか?

コードの引用
bool gui_open(bool cvbs,bool no_gui)
{
    if (SDL_Init(SDL_INIT_VIDEO) < 0){
        printf("SDL_Init failed (%s)\n",SDL_GetError());
        return false;
    }
    cvbs_resolution = cvbs;
    no_gui_mode = no_gui;

    SDL_VideoInfo* vinfo = SDL_GetVideoInfo();

    if(cvbs_resolution == false){
      screen = SDL_SetVideoMode(600,
                                600,
                                16,
                                SDL_HWSURFACE);
    } else {
      screen = SDL_SetVideoMode(600,
                                400, // ★ここ
                                16,
                                SDL_HWSURFACE);
    }
GROVE - GPS
GROVE - GPS
posted with amazlet at 13.05.12
スイッチサイエンス
Raspberry Piユーザーガイド
Eben Upton Gareth Halfacree
インプレスジャパン
売り上げランキング: 1,150
Raspberry Pi Type B 512MB
Raspberry Pi Type B 512MB
posted with amazlet at 13.05.12
RS Components Ltd
売り上げランキング: 1,093
posted by いしいっち at 12:03| Comment(7) | TrackBack(0) | Raspberry Pi | このブログの読者になる | 更新情報をチェックする

2013年04月28日

Raspberry PiでI/O拡張&Arduinoシールドを使おう〜firmata+Ruby編

Raspberry Piでいろいろと制御を楽しむ時に、よりたくさんのI/Oを叩きたいとか、サーボを手軽に動かしたくなる場合があるかもしれません。また、Arduinoシールドを既に持っている場合、これを活用したいという場合もあるでしょう。
Raspberry PiはそれほどはI/Oが充実していませんしね〜。
以下は回路図のピンヘッダのところ。
RPi_PIN_sch.png
回路図にありますように、SPI、I2Cが出てるので、ポートエキスパンダを接続するという手は使えます。
ポートエキスパンダは、例えばこんなのとか。
http://akizukidenshi.com/catalog/g/gI-03708/

とはいえPWMやりたい、とかAD値を取りたいとか、なんてことを手軽な工作で実現するには手間がかかりそうです。


本記事では、上記を解決するアプローチの1つとして、firmataのスケッチを書き込んだArduinoマイコンボードをRaspberry PiのUSBポートに接続し、Raspberry Pi側からArduinoを手足のように使って制御を行なってみる内容になっています。
そんなわけで、ArduinoシールドもRaspberry Piから制御できるようになります。いろいろお持ちの方は資産活用できるかもしれませんね

firmataは、元々PC用のJavaベースの開発環境Processingで、PCに接続したArduinoマイコンボードを制御してフィジカルコンピューティングするものです(と理解してます)。

そこで、firmataのプロトコル http://firmata.org/wiki/Protocol をRaspberryPi側に喋らせる事で、Raspberry Piで手軽にArduinoマイコンボードを制御できるようにする準備をしていきたいと思います。
今回、Raspberry Pi側で使用する言語はRubyにしました。これでRaspberry Pi上のスクリプト言語で、お手軽にスケッチ相当のコードを書いて、フィジカルコンピューティング出来ますね!(たぶん)

IMG_20130428_030933resized.jpg
さて、今回はArduinoマイコンボードとして最もスタンダードなものの1つである、Arduino Unoを使用しました。
最近スイッチサイエンスさんではこのボード、永久保証されてるようで話題になりました。
【永久保証付き】Arduino Uno
スイッチサイエンス
売り上げランキング: 3,309

Arduinoマイコンボード側の準備

では、これに、Standard Firmataのスケッチを焼きこんでおきましょう。サンプルに用意されています。
ss_firmata.png

Raspberry Pi側の準備
Raspberry Pi側のディストリビューションはRaspbian Wheezyを使用します。その他のLinuxディストリビューションでも多分実施可能かとは思います。Arduno Unoを認識させる為には、USB CDC ACMデバイスを認識できるようにする必要がありますが、Raspbian Wheezyでは標準で認識するようになってます。

●Rubyのセットアップ
今回はRubyとRubyでシリアルポートを制御するruby-serialportを使用します。また、ruby-serialportをセットアップするのにRubygemを使用しますので、以下のようにセットアップするとOKです。

$ sudo apt-get install ruby
$ sudo apt-get install ruby-dev
$ sudo apt-get install rubygems
$ sudo gem install ruby-serialport

ruby-devは、gemでモジュールをインストールする際に必要になる関係でセットアップしています。

では、ライブラリを準備します。

patcoll氏のruby-firmataをベースに、現在のfirmataで使用できるように改造し、改変や機能追加したものを私のgithubで公開しています。

当初そのまま使えるかなと思ってたのですが、ruby-firmataの開発が2年ほど止まっているようで、その間のfirmataの拡張などもあったためでしょうか、そのままでは動作させられませんでした。
改変版は以下にあります。
https://github.com/yishii/ruby-firmata
これを取得します。
下記のようにgitで取得出来ますし、gitを使わない場合、「zip_icon_github.png」アイコンをクリックするとZip形式でダウンロード出来ます。
git clone https://github.com/yishii/ruby-firmata
それではサンプルコードを用意します。以下のコードは、上述のリポジトリ内にあります、test.rbとなってます。
runメソッドにクラスを渡すとsetupとloopを呼び出すArduino IDEライクなスタイルです。直接Arduinoクラスメソッド呼び出しでの制御もできますので、お好みで。

digital_readやanalog_readメソッドの値は、firmataではレポートが定期的(または変化があった時)にArduino側から送られてきますので、それをパースした結果を返します。本ライブラリでいえば、Arduino::parseを呼び出した内部でArduinoからのレポートを解釈し、内部で記録します。

コードを見ていただくとおわかりになるかと思いますが、内容としては、デジタルピン2番をリードしてデジタルピン13番のHigh/Lowを制御するのと、アナログピン0番をリードしてデジタルピン9番に接続したサーボモーターを制御させています。

require './lib/arduino'

class Test
  def initialize(arduino)
    @arduino = arduino
  end

  def setup
    @arduino.set_report_interval(100) # アナログ値のレポート間隔 = 100[ms] 短かくし過ぎた場合通信量が大きくなるので注意
    @arduino.pin_mode(Arduino::DIGITAL2 , Arduino::INPUT)
    @arduino.pin_mode(Arduino::DIGITAL3 , Arduino::INPUT)
    @arduino.pin_mode(Arduino::DIGITAL13, Arduino::OUTPUT)
    @arduino.pin_mode(Arduino::DIGITAL9 , Arduino::SERVO)
    @arduino.pin_mode(Arduino::ANALOG0  , Arduino::ANALOG)
    @arduino.report # デジタル・アナログのレポート開始
  end

  def loop
    @arduino.parse # レポートを受信して解釈する

    # デジタルピン2番のLOW/HIGHでデジタルピン13番を制御
    if (@arduino.digital_read(Arduino::DIGITAL2) == 0)
      @arduino.digital_write(Arduino::DIGITAL13,0)
    else
      @arduino.digital_write(Arduino::DIGITAL13,1)
    end

    # アナログピン0番の入力値を用いてデジタルピン9番のサーボを回転させる
    val = @arduino.analog_read(Arduino::ANALOG0)
    @arduino.servo_write(Arduino::DIGITAL9,val >> 2)
   end

end

arduino = Arduino.new("/dev/ttyACM0")
arduino.run(Test)



/dev/ttyACM0は、Arduino Unoのシリアルポートのデバイススペシャルファイルです。これを介してRaspberry PiからArduino Unoにアクセスします。

テストに使用したのは、ジョイスティックシールド+サーボモーター+LEDです。
IMG_20130428_030941resized.jpg
IMG_20130428_030852resized.jpg
使用してるところの動画撮りましたのでどーぞ!


firmataを使用すれば、手軽にRaspberry PiでI/O制御の拡張と、既存Arduinoシールド資産が活用できるので、よかったら是非どうぞー!

ちなみに、今回使用したライブラリはArduino::parseメソッドを呼び出して1バイトずつデータを解釈させるのですが、できれば受信は別スレッドで行わせたほうが扱いやすいように思います。その内また更新して本ブログに掲載させていただこうかなーと思います。
Raspberry Piユーザーガイド
Eben Upton Gareth Halfacree
インプレスジャパン
売り上げランキング: 1,952
Raspberry Pi Type B 512MB
Raspberry Pi Type B 512MB
posted with amazlet at 13.04.28
RS Components Ltd
売り上げランキング: 1,915
posted by いしいっち at 04:16| Comment(0) | TrackBack(0) | Raspberry Pi | このブログの読者になる | 更新情報をチェックする