Arduino→Android→ネットワークの実験その2

Androidを使った実験として、今度はネットワークからの制御をしてみました。

我が家は普通のコンセントから繋いだ間接照明を利用してる為、それに使用することで、世界中誰でもブラウザで私の部屋の照明をオンオフしやがれって企画です。

Twitter等で告知して公開実験したときの特設サイト↓

http://pocomo.skr.jp/android/

手書きのラフなブロック図ですが、下記の通りとなります。

  • ハードウェア&Arduino

コンセントのオンオフはリレーで行います。

リレーにはomron製G5CA-1A(5VDC入力 耐圧10A 200VAC)を使用しました。

Arduinoからコイルの直接駆動は厳しいので、トランジスタ(2SC1815)で駆動します。ベース抵抗に3K程度。

これであとは普通にArduinoのIOをoutputにし、HIGH/LOWさせればコンセントの電源をオンオフできます。

Arduinoのソースはこちら

—–

[sourcecode language=”cpp”]

#include <LiquidCrystal.h>

const int analogOutPin = 9;//LED PWM出力ピン
const int relay = 13;//リレー用ピン
int sensorPin = A0;//CdS入力ピン
int sensorValue = 0;
int outputValue = 0;
int temp = 0;
char sRead;
char cnt=0;
int reflesh=100;//LCD 照度更新レート
int frame=0;

//LCD設定
LiquidCrystal lcd(11, 12, 2, 3, 4, 5);

void setup()  {
//IO初期化
pinMode(relay, OUTPUT);
digitalWrite(relay, LOW);

//シリアル初期化
Serial.begin(115200);

//LCD初期化
lcd.begin(16, 2);
lcd.setCursor(0, 0);
lcd.print("Input :");
lcd.setCursor(0, 1);
lcd.print("Output:");
}

void loop() {
//シリアル受信
//LED輝度調整とリレーオンオフを兼用
if (Serial.available()){//受信データ有り
sRead = Serial.read();
if(sRead==’B’){//LED最大輝度
analogWrite(analogOutPin, 255);
digitalWrite(relay, HIGH);//リレーオン
}else if(sRead==’N’){//LED普通輝度
analogWrite(analogOutPin, 50);
}else if(sRead==’D’){//LED暗め
analogWrite(analogOutPin, 20);
}else if(sRead==’O’){//LEDオフ
analogWrite(analogOutPin, 0);
digitalWrite(relay, LOW);//リレーオフ
}else if(sRead==’R’){//CdS情報リクエスト
VRout();
}

if(!cnt){
lcd.setCursor(7, 0);
lcd.print("         ");
}
if((sRead!=’\r’)||(sRead!=’\n’)){//デリミタ受信時LCD書き換え
lcd.setCursor(7+cnt, 0);
lcd.print(sRead);//受信データ表示
cnt++;
}
if((sRead==’\n’)||(cnt>9)){//LCDは9文字目まで
cnt=0;
}
}
if(frame >= reflesh){
sensorValue = analogRead(sensorPin);//CdS読み取り
outputValue = sensorValue/4;//10bit→8bit

if(outputValue !=temp ){
lcd.setCursor(7, 1);
lcd.print("   ");
lcd.setCursor(7, 1);
lcd.print(outputValue);//LCDにCdS値表示
temp = outputValue;
}
frame=0;
}

frame++;
delay(2);

}

void VRout(){
Serial.println(outputValue);//CdS値をシリアル送信
}

[/sourcecode]

—–

  • Android

Arduinoの制御は前回記事同様にAndroid側にFTDriverを使わせていただいてUSB接続しています。

ついでに前回の名残でArduinoで取り込んだCdSセルの照度をサーバーに送信してますので、そちらも部屋の明るさログとして流用しました。

20秒毎にサーバーにアクセスするポーリング方式です。GCM APIを使えばPUSH送信のシステムも組めるようですが、今回は手っ取り早く済ませました。

Androidのソースは現在ひどい状態なので勘弁してください。

  • サーバー

Androidからアクセスする先のサーバーに置いてあるperlソースはこんなかんじです。

—————————————————-

[sourcecode language=”perl”]

#!/usr/local/bin/perl

#POST送信されたデータを受け取る
if ($ENV{‘REQUEST_METHOD’} eq ‘POST’) {
read(STDIN, $alldata, $ENV{‘CONTENT_LENGTH’});
} else {
$alldata = $ENV{‘QUERY_STRING’};
}

foreach $data (split(/&/, $alldata)) {
($key, $value) = split(/=/, $data);
$value =~ s/\+/ /g;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(‘C’, hex($1))/eg;
$value =~ s/\t//g;
$in{"$key"} = $value;
}

#status.txt(照明の状態)を読み込み
open(IN,"status.txt");
@file = <IN>;
close(IN);

#log.txt(照度ログ)を上書き
open(OUT,">log.txt");
print OUT $in{‘message’};
close(OUT);

#POST送信元(Android端末)へのレスポンス
if(@file[0] == "1"){
print"On";#Androidに"On"を返答
}else{
print"Off";#Androidに"Off"を返答
}

exit;
[/sourcecode]

——————————

‘message’はAndroidからのアクセス時に照度情報を送ってlog.txtに書き込んでます。(実験中につき名前の付け方がおかしいのは気にしない方向で…)

照明のオンオフはstatus.txtに入ってる1か0の数字を読み取り、1のときはAndroidに”On”、0のときは”Off”を送信。

このstatus.txtをウェブブラウザのフォームで書き換えできる、という仕組みです。

Android側は受信した”On””Off”をもとにArduinoにシリアル送信して出力制御します。

  • 所感

Twitter,facebook,mixiでページを公開し、2時間ほど実験してみましたが、時折、平均すると1,2分に1度ほどパチパチされました。

物理的に自分にアクセスされることは、ネット上でコメントなどやり取りするのともまた違った感覚があって面白い体験ができました。同時にすごく見られてる感じがして落ち着かなくもありました。

  • 課題

問題点は、2時間程でスマホが再起動して動かなくなってたことです。やはりAndroidは手で持って運用することが第一で、固定して遠隔操作させるには安定性など不都合が面が多いことを実感しました。組み込み用などの為にウォッチドッグ機能とかあれば心強いのですが…

また普通に家で使うならArduinoにEthernetで繋げば早いので、そもそもAndroidを使う利点も薄くなってます。

今回のシステムについて、遠隔操作で他人に弄ってもらうのは面白いのですが、面白いのは9割方私自身だという事も弱点です。

せめて7割くらいにしようとUstreamで配信していましたが、演出として実に微妙です。フィードバックが弱い→すぐ飽きるのは致命的。

  • 今後の改善案

・物理的に動かしたものをみんな楽しめる

→アコースティック楽器をモーター等で鳴らして、それをwebラジオ配信、BGMとして使えるレベルに仕上げる

・操作先が多人数の施設およびイベント

→ライブ中の照明コントロール、ライブカメラ移動、音色チェンジ等…

なにかそういうもので使えるといいかなと考えてます。

あまりに混雑しても意味不明になるので参加人数調整が必要だったり、同時に弄られたときの対処、その他リアルタイム更新のブラウザ画面とか、特にコンセプトとインターフェース周りは課題は色々ありますが、とりあえず今回はAndroid実験として色々学べたので良しとします。

Arduino→Android→ネットワークの実験


Androidのアプリ開発を始めてみました。開発環境だけは整えてたものの、きっかけが無くてン年放置してました。

今回I/O制御とかしたいのでArduinoと繋げました。こういうとき、やりたいことはあくまでAndroidの勉強なんで、一瞬でハード・ソフトともに組めるArduinoはものすごく便利です。

私の所有しているArduinoはシリアル-USB変換にFTDIのFT232RLのチップが使われてます。イマドキはADKとかあるみたいですが。

ここもArduinoの魅力であるユーザーの多さが功を奏し、これのドライバを作ってる方がいらっしゃいました。ksksueさんのFTDriver(https://github.com/ksksue/FTDriver)。すげえ。

こうなればこっちの方が便利です。FT232RLは300円程度で売ってますし、これさえブリッジさせればシリアル通信ができるマイコンなら何でもOKですし。

そちらのドライバ&サンプル「FTSampleTerminal」を流用させていただきつつ加工し作業してます。アプリ名がそのままです。

Android側がUSBホストになるので、Arduinoはバスパワーで動きます。

Arduino側はLEDとCdSセルとLCDを接続。

LCDはシリアル通信のデータ確認用。

Android側で「送信」ボタンを押すとArduinoにリクエストが行き、CdSでADにとりこんだ照度を返すという処理をさせてます。

ついでに10秒間隔の自動送信やラジオボタンでLEDの明るさ制御(PWM)とかを実装。

んで取り込んだデータはAsyncTaskによる非同期処理でサーバーにPOST送信し、cgiでテキストファイルを書き換えてます。

折角定期的に送信されるのでブラウザからもリアルタイムで更新されると面白いと思って、慣れないJavascriptで表示させてみました。

うっかり処理をミスって時間が変わってませんが、10秒おきに増えてます。

”68”とかの数字が明るさ。LEDライトくっつけて大体200、手で塞いで4,5くらいになります。

照度センサとしてならAndroid単体でもやりようがあるかもしれませんが、マイコンと繋げるのは色々先が考えられてワクワクします。

Androidのアプリ開発も、まだまだブラックボックスだらけで自分自身理解してないことが多すぎます。とりあえず動かせたよってレベル。

でもやっぱりLCDに出したりAD値を取り込んだりするとモチベーションが上がってやる気が沸きますね。