2011年9月17日土曜日

[PlayStation] DUALSHOCKの修理

Repairing a broken DUALSHOCK

プレステ2のコントローラDUALSHOCK2が誤動作するようになってしまいました。
振動すると、触ってないはずの×ボタンとL1ボタンが押されたような動作をします。
コントローラーを本体から抜き差ししても誤動作するので分解してみました。
ボタンや配線やハンダに異常はなさそうです。
ただし、赤丸で囲んだモーターのスポンジが劣化しています。
おそらくモーターに遊びができてしまい、回転した瞬間に基板に干渉していると思われます。

ホームセンターやカー用品店で売られている「制振テープ」とか「隙間テープ」を用意して修復します。上の画像のコントローラーの下に写っているものがそれです。
モーターに張られていたスポンジの厚さは1mmほどでした。今回用意できたのはそれよりちょっと厚めですが問題ありませんでした。
エーモン 防音テープ 3mm厚

エーモン 防音テープ 3mm厚
950円
(税込、送料別)

ホルツ防振、防音テープ 5mm厚

ホルツ防振、防音テープ 5mm厚480円
(税込、送料別)

古いスポンジは強力な両面テープで貼られているので根気よくはがします。
はがした後に新しいスポンジを貼り付けます。
後は元通りに組み立てます。

これで誤動作しなくなりました。

以上、参考になれば幸いです。

2011年9月10日土曜日

[Android-NDK] ERROR [binderDied] end

How to solve "[binderDied] end" error

アプリを開発していたら、突然こんなエラーが起こりました。
ERROR/CameraService(1215): [binderDied] end

Android-NDKのログにはこんなエラーが出てます。
DEBUG/ndk(2474): [ 08-27 20:12:59.451 2474:0x9aa F//system/bin/app_process ]
DEBUG/ndk(2474): stack corruption detected: aborted

原因はJNI(Android-NDK)のchar配列の要素不足でした。

エラーになったコードの抜粋
sprintf関数の引数xとyとzがdouble型だったため、文字列に変換すると予想以上に長くなり、50バイトを超えてしまいました。
char c[50];を
char c[100];に変更したら正常に動きました。

LogCatに「CameraService」とあるし実際に android.hardware.Camera を使うアプリだったのですが、カメラは全く関係ありませんでした。
エラー内容と関係ないログが出力されたので、少し手間取りました。

ちなみにVisual C++ 2010 ではどんなエラーメッセージが出るのかと思い、同じバグを再現したところ
Run-Time Check Failure #2 - Stack around the variable '変数名' was corrupted.
バッファー オーバーランが *****.exe で発生し、プログラムの内部状態を破損しました。[中断] をクリックしてプログラムをデバッグするか、または [続行] をクリックしてプログラムを終了してください。
と表示されました。

「[binderDied] end」というメッセージはわかりにくいですが、「stack」と「corruption / corrupted」というキーワードを見たら、スタック領域の破損∋配列の要素不足の疑いがありそうです。

以上、参考になれば幸いです。

2011年9月3日土曜日

[GPS] 経度1度の距離の求め方

How to get distance of 1degree longitude

blog.fujiu.jp  経度1度の距離の求め方
緯度(北緯)1度あたりの距離はおよそ111kmですが、経度(東経)1度あたりの距離は緯度によって大きく変わります。
経度1度の距離は赤道に近づくほど大きく、遠ざかるほど小さくなります。
GPSセンサーを使ったアプリケーションで距離を測る時に困ってしまいます。

経度1度のおおよその距離(km)は次の式で求められます。

経度1度の距離(km) = cos(緯度×0.017453293) × 111.3194908
※0.017453293=2×π÷360(角度からラジアンを求める係数)
※111.3194908=6378.137×2×π÷360(地球を半径6378.137kmの球として断面の円周を求める係数)

cos関数の括弧の中は緯度(北緯)のラジアンです。経度(東経)ではないのでご注意ください。緯度と経度を間違えると正しく計算できません。

この計算は地球を真円としてしますが、実際の地球は楕円です。
計算結果がどれくらい誤差があるのか、国土地理院の距離と方位角の計算と比較してみます。

緯度(北緯) 計算値(km) 国土地理院(km) 大まかな位置
20 104.60610 104.64693 沖ノ鳥島
26 100.05330 100.11747 尖閣諸島
33 93.36038 93.45286 四国、九州
36 90.05936 90.16329 関東、近畿、竹島(島根県)
40 85.27568 85.39341 東北
44 80.07654 80.20570 北海道

案の定、赤道から遠ざかるほど誤差が大きくなってます。北緯44度の地点で誤差0.16%です。
とは言え、三角関数1個の計算で距離が求まるので、スマートフォン用アプリケーションには十分だと思います。 (※1)
実際に使ってみると計算誤差よりセンサーの誤差のほうが大きいくらいです。


distance(km) of 1degree longitude = cos(latitude_degrees * 0.017453293) * 111.3194908

計算にはMicrosoft Excel 2010を使いました。

(※1) 2010年当時、スマートフォンが今のものよりスペックが低くバッテリー容量が少なかった頃の考えです (2016年4月追記)


以上、参考になれば幸いです。

2011年8月27日土曜日

[AV] コンポーネント端子がついてないテレビにPS2や古いDVDプレイヤーを接続する

How to connect component terminal to D terminal?

テレビも液晶ディスプレイも故障したため新しいテレビを買を買ったのですが、このテレビにはコンポーネント端子がついていません。(承知の上で買いました)
今までのテレビが10年以上前に買った製品だったので、ゲーム機もDVDプレイヤーもコンポーネント端子でつなげていました。

テレビ背面の端子。コンポーネント端子やS端子がありません。


左がプレステ2用、左が汎用
綺麗な映像を見たいのでコンポジット端子は使いたくありません。
このテレビにはD端子がついてるのでD端子ケーブルを買えばいいのですが、機器に合わせて全部そろえるとしたら大きな出費です。
HDMIの時代に、アナログ規格のケーブルに投資するのは気が引けてしまいます。

そこで、1780円前後で売られているコンポーネント端子をD端子に変換するケーブルを買いました。
富士パーツD端子コンポーネント変換ケーブル AD-513 0.1m(D端子・オス-コンポーネント端子・メス)
AVケーブルD端子⇔コンポーネント端子変...

AVケーブルD端子⇔コンポーネント端子変...
価格:1,785円(税込、送料別)

これで綺麗に映りました。

私事ですが、プレステ用のAVケーブルはコンポーネント端子ケーブルの他、21ピンアナログRGBケーブルやS端子ケーブルも持ってます。
過去にいろいろなAV規格があったのに、デジタル時代の今ではHDMI、DisplayPort、Thunderboltといった異なる規格が乱立してます。
日本のメーカーのノートパソコンにはHDMIがついてますが、HP製にDisplayPort、アップル製にThunderboltといった別の規格がついてます。
ノートパソコンの映像を外部出力するにはそれぞれの規格に対応した装置が必要になってしまいます。
規格争いはいい加減にして欲しいですね。

2011年8月20日土曜日

[Android] ThumbモードとARMモード、どちらが速いのか?

Which is faster, Thumb or ARM?

多くのAndroid端末に使われているARM系CPUは16ビットのThumbモードと32ビットのARMモードとがあります。
「ARMモードの方が速い」という意見がある一方、「Thumbモードはプログラムサイズが小さい分メモリーアクセスが少ない」という意見があり、どちらが効率がいいのかよくわかりません。
そこで、ThumbモードとARMモードを比較してみました。

Activityのソース(Main.java)
jni/nck.cpp
Android.mk(Thumbモードの場合)
Android.mk(ARMモードの場合)
結果
(1)int型(32ビット)の検証
エミュレーター・実機(IS01)とも、Thumbモードの方が速い。

(2)float型(64ビット)の検証
エミュレーターではARMモードの方が速く、実機(IS01)ではthumbモードの方が速い。

(3)atan2関数(複雑な計算)の検証
エミュレーターではARMモードの方が速く、実機(IS01)ではthumbモードの方が速い。

結論
Thumbモードの方が速い場合がある。
ARMモードが常に速いとは限らないようです。Android-NDKを使ったアプリケーションを公開する時は機種ごと・アプリごとにベンチマークを取って比較した方がいいようです。

以上、参考になれば幸いです。

2011年8月13日土曜日

[Android] 自身をタスクキルするアプリケーションを作るには

How to kill the application's own self

Androidアプリケーションは終了すると、何の処理をしなくてもRAM(メモリー)に残ります。
(終了してもバックグランドで処理を続けるプリケーションもあります)
他のアプリケーションが起動するなど、空きメモリーが必要になったときにOSがRAMから消します。
アプリケーションがRAMに残っていた方が速く起動できるし、バッテリーやフラッシュROMの寿命も長持ちします。

ただ、アプリケーションが終了後もRAMに残ることに不安を覚えるユーザーも少なからずいらっしゃるようです。
そこでActivityを終了したらRAMから消える(タスクキル)サンプルを作ってみました。

ソースです。
Activityのソース用(Main.java) ※パーミッション不要のため、マニフェストは省略

onDestroyメソッドの最後に Process.killProcess(Process.myPid()); を書くだけです。

アプリケーションを起動するとタスクリスト(※)にパッケージ名が表示されます。
(※正式名称は不明ですがここでは「タスクリスト」と呼びます)
一度起動したアプリケーションは、RAMに十分な空き容量があれば終了してもタスクリストから消えないのが普通です。

Process.killProcess(Process.myPid()); が実行されると直ちにタスクリストから消えます。

ちなみにタスクキルすると
INFO/ActivityManager(**): Process jp.fujiu.AndroidApp.ProcessKiller (pid ***) has died.
というログが残ります。異常終了したときと同じ内容なので、あまりいい気分ではありません。
タスクキルのメリットを強いて上げるならメモリーリークを解放してくれるようですが、メモリーリークを起こしているならタスクキルに頼らずコードを直すべきです。
本当にタスクキルするかどうかをユーザーに確認する画面を用意した方がいいと思います。

以上、参考になれば幸いです。

2011年8月6日土曜日

[Android] Android-NDKでテクスチャを表示するには

How to draw textures in Android-NDK

Havaは大きいソースが扱えないので、[Android] 頂点の多いポリゴンを扱うには では頂点数の多いポリゴンをAndroid-NDKを使ってJNIからJavaに大きい配列を渡す方法でバナナを表示しました。この方法はFloatBufferの作成に時間がかかるという問題がありました。
今回は、頂点とテクスチャの機能もJNIで書いてみます。

JNIで画像を扱うには?
テクスチャを表示するためglTexImage2Dを使います。
glTexImage2Dで表示できるテクスチャ画像はunsigned char型配列のビットマップデータです。配列の内容は1ピクセルごとにRGBAの順に1バイトずつです。
このブログを作成している時点ではJNIからres/drawableフォルダーやassetsフォルダーのファイルを扱う方法が見当たりませんでした。
そこで、JNIで画像データを扱うために次のようにしました。
  1. Javaでres/drawableフォルダーの画像をint型配列に変換してJNIに渡す
  2. JNIでJavaから渡されたint型配列をunsigned char型配列に変換しテクスチャ表示する
以下ソースです。
ndk.cpp
glu.h (Android-NDKのsampleの com.example.SanAngeles から抜粋しました)
Android.mk
これら ndk.cpp、glu.h、Android.mk と、HBehrens-obj2opengl-a0f123e.zipのbanana.h をプロジェクトのjniフォルダーにインポートし、カレントフォルダーをjniに移してndk-buildを実行します。
HBehrens-obj2opengl-a0f123e.zipののbanana.jpgをres/drawableフォルダーにインポートします。

Activityのソース(Main.java)
画面をフリックするとバナナが回転するようにしました。
これをエミュレーターで実行したら一瞬でバナナが表示されました。JavaでFloatBufferを作成する方法(エミュレーターで2分くらい)とは大違いの速さです。
テスト環境では、Heapを見比べたらJavaでFloatBufferを作成する方法に比べて1MBほどメモリーの節約になりました。
Android-NDKでビルドしたアプリケーションはARMの端末でしか動作しないのが玉に瑕です。

以上、参考になれば幸いです。