1

IOIO for Androidのアナログ入出力を試した

IOIOの10bit ADコンバータと10kHz PWM出力を試した。

今回のコード https://github.com/shokai/android-ioio-study/tree/master/AnalogInOut


Androidの画面上のシークバーを操作すると、PWMによる擬似的なアナログ出力でLEDの明るさを調整できる。
ブレッドボード上のCdSで明るさを計測して、Androidの画面上のシークバーの長さで表示したりした。
R0016190


動画




■準備
まず久しぶりに秋葉原に行ったら秋月が改装工事中だったので、他の店を見て回った。IOIOの開発者が使っているピンヘッダを千石で発見したので買った。

このピンヘッダ気に入った


このピンヘッダ、みっしりと敷き詰めるように装着できる。いつも使ってるメスピンヘッダは隣のピンにぶつかるので敷き詰められない。
ピンヘッダ装備IOIO

これでブレッドボードに線を引き出す準備が整いました


■回路を作る
ブレッドボードに5Vか3.3Vと、GNDを引き出す。
4番ピンでデジタル入力を試すために、タクトスイッチを通して5Vを流し込む。IOIO内部でGNDにプルダウンするので直結で良い。ただし、Read This Before Connectingに書いてある通り5Vを入れて良いピンは決まっているのでよくわからなかったらブレッドボードに出すのは3.3Vにしておいた方が良い。

3番ピンをLEDに接続する。PWMを試すため。

アナログ入力は40番ピン周辺に16個ある。45番ピンにCdSをつけ、10kΩで分圧した。

R0016189



■プログラムを書く
書いた。
AnalogInOutActivity.java

1からAndroidプロジェクトでIOIOを使う方法は前の記事を参考にされたし


このへんのドキュメント参考になる。



重要なのはAnalogInOutActivity.javaの49行目あたり
class IOIOThread extends AbstractIOIOActivity.IOIOThread{
private DigitalOutput led;
private DigitalInput btn;
private PwmOutput pwm;
private AnalogInput ain;
protected void setup() throws ConnectionLostException{
led = this.ioio_.openDigitalOutput(0, true);
btn = this.ioio_.openDigitalInput(4, Mode.PULL_DOWN);
pwm = this.ioio_.openPwmOutput(3, 1000); // 1000hz
ain = this.ioio_.openAnalogInput(45);
}

protected void loop() throws ConnectionLostException{
try{
led.write(!btnLed.isChecked());
if(btn.read()) seekBarDigitalIn.setProgress(1);
else seekBarDigitalIn.setProgress(0);
pwm.setDutyCycle((float)seekBarPwm.getProgress() / seekBarPwm.getMax());
seekBarAnalogIn.setProgress((int) (ain.read() * seekBarAnalogIn.getMax()));
sleep(10);
} catch (InterruptedException e) {
}
}
}

DigitalInputはMode.PULL_DOWNにしておく。PwmOutputは1kHzに設定した(最大10kHz)
PWMもAnlogInputも、0〜1の間のfloat値で入出力値を扱う。Androidの画面のSeekBarは最大値を1000にしておいたので、IOIO上での値を1000倍してintにcastすればSeekBarに表示できる。


デジタル入力の状態をAndroidの画面上に表示する時、IOIOThreadからUI Threadを操作するとデッドロックが起きてアプリが停止するが、なぜかSeekBarはデッドロックが起きないので長さ1の小さなSeekBarを作ってデジタル値を表現するように工夫した。

ほんとうは「android.os.Handlerクラスのpost()を使え」、とyoggyさんが言っていたので今度やってみます。

0

IOIO for AndroidでLEDピコピコ光らせる

IOIOのデジタル出力を使った。
作ったものはテストなのでどうでもいいとして、IOIOLibをimportして自分で1からAndroidアプリプロジェクトにするところと、Eclipseの設定でハマった事について書いておく。


■できたもの
コード https://github.com/shokai/android-ioio-study/tree/master/LED_Blink


Androidの画面上のボタンが3つあって、IOIOのLED3つと対応している。
1つ前の記事で作ったUSB給電ケーブルとeneloopで外でも動かせる。下の4つ目のボタンは気にするな。
R0016179

動画



■EclipseのCompiler Compliance Level
Eclipse->環境設定->Java->CompilerにあるCompiler Compliance Levelを1.6にする。
これをしないと後述のioio.lib.impl.*impl.java等で90個ぐらいのエラーが発生してビルド出来ない。

でもCompiler Compliance Levelを変更すると、Level 1.5等で作ったAndroidプロジェクトが今度はエラー表示を大量にだしてしまう。なのでIOIO用に新しいworkspaceを作ったほうが良いでしょう。


■最新のIOIOLibを使わない
IOIO for Android Beginners Guide – SparkFun ElectronicsにあるIOIOLib.zipを解凍して、Eclipseでworkspaceにimportする。

こうなればよし。

http://codaset.com/ytai/ioioに最新版のgitリポジトリがあって、毎日すごい勢いで実装されている。
だが、最新のIOIOLibでビルドして動かしてみるとLogcat上でもAndroidとIOIOが接続できているっぽい様子が見えるが、デジタル出力ができなかった。firmwareも修正しているのでプロトコルがupdateされているのかもしれない。とりあえずBeginners GuideのIOIOLibを使いましょう



■新規プロジェクト作成
まっさらからAndroidプロジェクトを作り、IOIOLibを使う方法。

まず普通にAndroidプロジェクトを作る。どうも2.3.x以降じゃなくても動くらしい。http://codaset.com/ytai/ioioのサンプルもAndroid1.6用とかで作ってた。


プロジェクトを右クリックしてプロパティで、Android->Libraryに ../IOIOLib を追加する。workspaceのIOIOLibが読み込まれる。

Eclipse使ってない人は default.properties

android.library.reference.1=../IOIOLib
を追加する。


AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
を追加する。(どうもADKじゃなくて、debug bridgeを使って通信している様だ)

あとはAndroidアプリとしてごプログラムを書く


■IOIOのプログラムを書く
今回作ったMainActivity.java

まずioio.lib以下で必要な物をimportする。
MainActivityはandroid.app.Activityではなく、ioio.lib.util.AbstractIOIOActivityを継承する。
サンプルのHelloIOIOと同様に、クラス内クラスでAbstractIOIOActivity.IOIOThreadを作ってその中に関数setup()とloop()を作った。

そしてMainActivityからIOIOThreadを呼び出す。
@Override
protected AbstractIOIOActivity.IOIOThread createIOIOThread() {
return new IOIOThread();
}

あとはArduinoっぽく書ける

どうもActivityがアクティブの時しかIOIOは動かないらしい。Intentで画面遷移させるアプリから使う時どうなるか気になる。



■IOIOはADKじゃないっぽい
IOIOはADKで通信してるんだと思ってたら、debug bridgeを使って通信してるっぽい。http://codaset.com/ytai/ioio/wiki/IOIO-Over-OpenAccessory-BetaにADKとして動作させる方法が書いてある。



■logcatを見る
IOIOとAndroidを接続するのにUSBポートが塞がれるので、logcatができない。またNexusSはrootを取らないとWiFi経由でのadb logcatができないので、ブラウザからlogcatを見る – 明日の鍵にあるツールを使う。
wget http://tomorrowkey.googlecode.com/svn/trunk/LogcatOnBrowser/LogcatSocketServer/bin/LogcatSocketServer.apk
adb install -r LogcatSocketServer.apk
wget http://tomorrowkey.googlecode.com/svn/trunk/LogcatOnBrowser/Client/logcat.html
open logcat.html

grepしたいので、後でlogcat.htmlを改造しようと思う

Androidへのapkのインストールはhttpからできるので、https://gist.github.com/1090762でhttpdを動かしてUSBケーブルを抜き差ししなくてもapkをインストールしてlogcatを見る事はできる。多少面倒くさいのでこの辺どうにかしたい。

0

PhoneGap NFC Plugin作った

PhoneGapでAndroidのNFCを使えるpluginを作った。



JavaScriptから簡単にNFCタグのIDが読める。
<script src='./phonegap.nfc.js' type='text/javascript' />
document.addEventListener('deviceready', function(){
window.plugins.nfc.id(
function(tag){
var id = tag.id; // get Tag ID;
},
function(e){
log(e);
});
}, true);


インストール方法はgithubに書いた。サンプルプロジェクトもある。
普通のPhoneGap pluginと同じく、phonegap.nfc.jsとNfcPlugin.javaを所定の場所に置くのだけど、NFCを使うためにguava librariesとAndroidManifest.xmlの修正も必要。

とりあえず、NFCでタグのIDを読むだけしか機能は無い。もちろん他にも色々データは取れるんだけど、どこまでwrapしたらいいのかよくわからないのと俺がIDしか使う予定が無いので、とりあえずIDだけにしておいた。(要望あれば追加する)




PhoneGap pluginの作り方は、phonegap / PhoneGap Pluginsが参考になった。JavaScriptからJavaのコードを呼びだす方法が書かれている。


既に公開されているプラグインがいくつかあって、それも参考になった。


0

AndroidでHTTP POST

targetはAndroid2.3.4、API 10向けにビルドして試した。

参考:


<uses-permission android:name="android.permission.INTERNET" />

import java.io.*;
import java.util.*;
import org.apache.http.*;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

HttpClient client = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://localhost:8080");
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("message", "ほむ"));
try{
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
HttpResponse res = client.execute(httppost);
ByteArrayOutputStream os = new ByteArrayOutputStream();
res.getEntity().writeTo(os);
Log.v("result", os.toString());
Log.v("status", res.getStatusLine().getStatusCode());
}
catch(Exception e){
e.printStackTrace();
}


リクエストができているかの確認は、EM::HttpServerで見た
gem install eventmachine_httpserver
#!/usr/bin/env ruby
require 'rubygems'
require 'eventmachine'
require 'evma_httpserver'

class Handler < EM::Connection
include EM::HttpServer

def process_http_request
res = EM::DelegatedHttpResponse.new(self)
puts "request_method : #{@http_request_method}"
puts "path_info : #{@http_path_info}"
puts "query_str : #{@http_query_string}"
puts "post_content : #{@http_post_content}"
res.status = 200
res.content = "こんにちは"
res.send_response
end
end

EM::run do
EM::start_server("0.0.0.0", 8080, Handler)
puts "http server start, prot 8080"
end

0

Nexus SのNFCでFelicaのIDを読む(2)

Nexus SのNFCでFelicaのIDを読む – 橋本詳解の時に、Android 2.3 GingerBread NFCをやってみる – TOPGATE Google関連技術サイトのTagWrapper.javaを使わせてもらってたんだけど先日のNexus Sのandroid2.3.4へのアップデートで動かなくなったので少しやり方変えた。
TagWrapper.javaの中でやってる事を参考にさせてもらった。


ただFelicaのユニークなIDだけが必要だったらこれでいい
(先に橋本詳解の方に書いたManifestとかguavaとかを設定しておく必要はある)

import java.lang.reflect.*;
import java.util.*;

import com.google.common.primitives.UnsignedBytes;

import android.app.Activity;
import android.content.Intent;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.*;
たくさんのimportが必要。


    public void onCreate(Bundle savedInstanceState) {        
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
resolveIntent(this.getIntent());
}

void resolveIntent(Intent intent) {
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
try{
Parcelable tag = intent.getParcelableExtra("android.nfc.extra.TAG");
Field f = tag.getClass().getDeclaredField("mId");
f.setAccessible(true);
byte[] mId = (byte[]) f.get(tag);
StringBuilder sb = new StringBuilder();
for (byte id : mId) {
String hexString = Integer.toHexString(UnsignedBytes.toInt(id));
if (hexString.length() == 1) sb.append("0");
sb.append(hexString);
}
String id = sb.toString();
Log.v("TAG", id);
}
catch(Exception e){
e.printStackTrace();
}
}
}