2015年1月31日土曜日

電池昇圧回路+赤外線リモコン受光センサー

今回は素回路だけで終わってしまった

長い間何故か手を付けなかった赤外線リモコンを扱ってみます。

手元にある赤外線リモコン受信センサーは5v駆動、しかし最近私の周りは3.3vプラットフォームがメイン。ということで、昇圧ICを使って3.3vから5vを作るところから。昇圧にはこのICを使いました。
DC/DCのモジュールなら500円ぐらいで売ってるけど、このICは外付けにコンデンサ2個、インダクタ1個、ショットキーバリアダイオード1個で簡単 / コンパクト / 廉価 / 電源0.9vから利用可能なので部品箱に転がしとくと便利です(「転がしとくと便利」は部品沼への直線コース)。

なお、同じタイプのICで3.3v出力のものもあり、両方買っても400円です(その発想が部品沼だと何度言えば)。


まず部品拾い。100uのマイクロインダクタがないので47uでいいか、とか、47uと22uのチタコンないから同容量の電解とセラミック積層でいいや、逆電圧防止のSBDは1S4で…みたいに多少の違いは気にしない。インダクタは気にした方が良いのですが、今回消費電力微弱で入力も3.3vなので、まぁ試してみてダメなら考えます。やっぱりマイクロインダクタと積層セラミックコンデンサの詰め合わせも買っておこう。

Amazon : ありゃ在庫切れだ


ブレッドボード上に昇圧IC回路と受信センサ回路を組み立てて、受信センサを抜いてから電源チェック、問題なければ受信センサを戻して手近のリモコンに出力に反応が出ているか、異常な電圧が出ていないかを確認。問題なし。

5v出力を3.3v回路の入力端子につなぐと壊れるので、分圧回路作らなきゃな…と思いつつ受信センサの出力端子を5v・10kでプルアップして電圧みたら約3vしか出ていなかった。のでそのまま接続w


Energia付属のリモコンライブラリで動作チェック、動きました。なお、そこらに転がっていたMP3プレイヤ用のカード型リモコンは問題なく受信できるのですが、やっぱりエアコン用はライブラリが対応していませんでした。

で。

これを使って、先日のデジタル時計に時間合わせ機能を付けようと思っていたのですが…デジタル時計で使っているRTCライブラリとレジスタがかち合ってしまい、ビルド通りませんでした。ソース追ってみたけど、あちこち影響が出そうでどちらのライブラリも手を入れるのはめんどくさそうな感じ。諦めました。

今朝はウォーキングに出たら路面凍結してるし、どうもツイてません。

2015年1月27日火曜日

MSP430/Energia+RTC+秋月巨大LED=デジタル時計

暗いとアラが目立たない

■またデジタル時計だ■

お前は他にやることがないのか、と言われるのは承知で作ります。

前回はダイナミック点灯させたところで力尽きたので、今回はちゃんと時計として動くようにします。TIの低消費電力MCU MSP430G2シリーズの2553、開発環境は同LauchPad + Energiaを使います。2553/LauchPadは日本だとちょっと手に入れにくいですが、RS onlineなどでLaunch Padとして$9.99で売ってます。せっかくなので、チップ単体のMSP430G2553も何個かまとめて買っておくと良いと思います(1個300円ぐらい)。LPC1114FN28と比べるとメモリなどごく限られるのですが、うそみたいに電池が長持ちしますし、かなりフットプリントが小さいので。

表示器は秋月の「超大型4桁7セグLED表示キット」です。低消費電力チップと組み合わせるのもどうかと思いますが。本来、秋月の時計キット用なのですが、巨大なLEDが今どきこの値段(1500円)で手に入るのは珍しいと思います。まぁaitendoで1280円で売ってたけどね…。注意しなければいけないのは、使っているLEDは16セグメントなのですが、秋月のキットでは7セグメントとして使ってます。aitendoのは16セグメント全部使っているけどね…でも16セグメント使いたくてもピンが足りないのよだからこれでいいのよ文句ないのよ(何その未練)

あとはRTCですが、今回は2553内蔵の発振回路 / カウンターを使います。キットには32768hzの水晶発振子が同梱されてます。小さくてLaunchPad基板へのハンダ付け大変ですけども。

温度計も2553内蔵の温度センサを使います。analogReadで華氏☓10の数値が直接返ってくるので便利です。まぁチップが多少なりともあたたまるので正確ではないけども(電源を入れた直後は他の室温計と一致していた)。

■先に落とし穴を書いておく■

内蔵温度センサも同じA/Dコンバータ使ってます。なので、Reference電圧を正しく設定しないと値がズレます。これで30分つぶしましたよ…。

■ハード編:巨大LED■

追記:
キットに付いてくるコロン用のLEDはクリアタイプで、方向によって明るさがかなり異なります(というか正面が眩しい)。「LED光拡散キャップ(5mm) 赤 (50個入)」を被せるか、広角タイプのLEDを用いると良くなると思います。

ほぼキットの説明書通り組み立てるだけなのですが、キットに付属しているコネクタはL型で表示器と平行に下側に伸びるように取り付けます。私は下面をフラットにしたかったので、手持ちの20ピンヘッダを取り付けました。あと、ハンダ付けの注意ですが…

  1. 金メッキ基板にはフラックスを(昔やった
  2. くれぐれもLEDの向きを間違えない(昔やった
  3. くれぐれも水平垂直平行を(昔やった
  4. ハンダ付けは必要十分に(昔(ry
基板と部品はまず最初に必ず仮組みをします。はんだ付けをしないで並べてみて、ぶつからないかちゃんとピンが全部ホールに入るかどうか、などを確認します。

1)のフラックスというのはピンや基板などをハンダで濡れ(?)やすくする処理剤です。小瓶で数百円、まぁ10年ぐらい使えます。キャップをあけると小さな刷毛がついてますので、それでハンダ付けする部分(ランドと言います)に少量塗ってやります。

2)はピンが多い部品を外すのはかなり困難です。確認確認また確認しましょう。

3)はピンを通す穴は案外大きいです。なので、雑に取り付けると微妙に部品が傾いてしまいます。傾く方向は左右だけでなく、基板と部品が平行になっているかも注意しなくてはいけません。なので、最初に1本をハンダ付けしたら、平行になっているかどうかをしっかり確認し、ずれていたらもう一度コテをあてて修正します。これで平行になっていることを確認したら、対角線上にあるピンをハンダ付けして再度確認します。これでOKならば、一応、隣のLEDも支障なくピンに入ることを確認してから、最初のLEDの残りのピンをハンダ付けします。

4)はリズムを身体で覚えるしかないっす。ただ、温度調整機能のついたハンダゴテを使っている分には最近の部品は滅多に壊れないです。それよりも、溶かしこむ時間が短すぎて接触不良になるケースの方が遥かに多いと思います。コテをあててピンを温める、コテというよりピンにハンダを当てて溶かす、ピンに自然にハンダが流れ込んだところでハンダとコテを同時に離す…ここまでまぁ3〜5秒くらい、10秒くらいかかってしまってもOKです。

今回の配線はソースに書いてありますが、こんな感じで。

信号名LEDボードのピン2553のピン番号同ピン名
Anode1桁目43P1_1
Anode2桁目22P1_0
Anode3桁目15P1_3
Anode4桁目56P1_4
Seg A177P1_5
Seg B188P2_0
Seg C129P2_1
Seg D1410P2_2
Seg E1311P2_3
Seg F1612P2_4
Seg G1513P2_5
dp<未使用>
コロン(+)204P1_2
コロン(-)18(GND)
水晶-19XIN
水晶-18XOUT

水晶は、Launch Padにこんなのが付属しています。


袋およびパッケージから取り出すとこんなに小さい。


2553のXIN-XOUTは右側のピンヘッダにもつながっているのですが、水晶発振子はピンから離れると動作が不安定になるので、なるべく近くに取り付ける必要があります。下の写真では中央の2553の右ちょっと上の方にある縦に2つ穴の空いたところがソレです。



貧乏症のワタシはこういう開発キットのようなものに手をいれるのはイヤなのですが、ハンダ付けします。ただ、こんなに小さいものなので、まずテープで止めて位置をルーペで見ながら位置を微調整してからハンダ付け。

これはハンダ付け前

ああしんど。

その他LaunchPadとLEDボード間は、メス−オスのジャンプワイヤで一本ずつ配線していきます。

■ソフト編■

MSP430/Energia用のRTCライブラリを使います。ライブラリ、ありがとうございます。なお、同ライブラリのライセンスはGPLです。
リンク先フランス語ですが、英語に切り替えられます。リンクからダウンロードすると、他にも面白そうなライブラリが並ぶのですが、今回はsRTCだけを使います。sRTCフォルダをEnergiaのディレクトリ下にあるLibraryに入れます。

使い方は簡単で、ヘッダをインクルードし、setup()で.begin()を呼び出し、秒単位の割り込みルーチンで秒をインクリメントします。あとは時分秒を取ってくるだけ。2秒間時計〜1秒間温度表示、を繰り返します。



あとはもういつものダイナミック点灯方式のよくあるデジタル時計ルーチンです。

以下ソースを公開しますが、ライセンスは一応GPLで。難しいことはしていませんが、ご質問いただければ喜んでお答えします。この後は、これに赤外線リモコン受光器か時刻合わせスイッチを取り付けてから、久々にプリント基板にしてみようと思います。


■使ってみて■

いやー、デカい。存在感ありすぎます。3.3vでのダイナミック駆動なのをいいことに電流制限抵抗もドライバも入れてないので少し表示が暗いのですが、ちょっと昭和の薫りがしていい感じw 昼間でも見えますし夜電灯を消すと睡眠の邪魔にならない程度の明るさで動いてくれています。何より、乱視+近視でも目を凝らさず見えるのが良いです。

ピンがあと2本空いているので照度センサと時刻合わせスイッチ(または赤外線受光器)は取り付けられるか…。プリント基板が遠のくなぁ。

■更新■

  • 2015-01-31
    コロンの出力をPWMに変更。ほどよい明るさになったけど点滅が見えてウザい

2015年1月24日土曜日

スマートフォン クイックジャック ソリューション



スマートフォン クイックジャック ソリューション (Quick-Jack Solution) OM13069は秋月などで売っているスマートフォンのマイク/ヘッドフォン端子に接続するI/Oモジュールです。モジュール上にはLPC812が乗っていて、音声端子を通じてマンチェスター符号(TJさん、ご教示ありがとうございました)で通信するだけではなく、音声出力から電力ももらおうという素晴らしいデバイス。

最初、つないでも反応しない!?と焦ったのですが「ボリュームを上げないとダメよ」とのこと。ボリューム上げたらLEDが点滅始めました。なるほど、信号だけじゃなくて電力としても使っているんですね。

動作を確認したところで、さてiOS用のSDKを落としてこようと思ったら…iOS用は公開されていませんでしたorz Android用は提供されているのですが、iOS用はサポートに連絡してくれ、とのこと。

週末遊ぼうと思ったのに…まぁ買う前に調べておけって話なんですけどもw

2015年1月23日金曜日

完璧なゆで玉子

お前は何もわかっていない(海原雄山風に。


上記はココロ社宗派が乱立する半熟ゆで卵の製法を統一。簡単&短時間&失敗なく半熟卵を作る方法と、ゆで時間と仕上がりの比較写真より。

試行錯誤の結果、倉橋家で確定したメソッドは以下の通り。「ためしてガッテン!」がベースだけど、より成功率が高い。室温や卵のサイズが変わっても失敗しないよう調整してきました。

  1. コレールなどガラスの鍋に50cc+卵1個あたり10ccの水を入れ火にかける。
  2. 冷蔵庫から出した卵の丸い側に針で穴を開け、スプーンで軽く叩いてヒビを入れる
  3. 沸騰したら卵を入れて蓋を閉め、タイマー起動。
  4. およそ1分経過したところで十分に沸騰したら少し火を弱める。弱めすぎないこと。
  5. 蓋を閉めてから3分30秒(夏は3分)経過したところで火を止め、静かに放置
  6. 火を止めてから6分30秒経過したら鍋に水を500cc入れて、30分ほど放置
  7. 水から取り出して濡れているうちに殻をむく
卵は買ってから1週間以上経ったやつを使うとベター。冷蔵庫から出した卵を使うのは開始温度を一定にするため。穴を開けヒビを入れるのは気室にある空気と卵白などに含まれる二酸化炭素の逃げ道を作るため。卵膜内側の圧力が高いと卵膜に白身が貫入(?)して剥きにくくなるから。

コレールを使うのは火を止めてから熱が下がりにくいからです。普通のいわゆる金属製ラーメンサイズの鍋の場合は加熱時間を1分程度長くしたほうがうまくいきますが、室温の影響を受け易いので安定した品質を維持するのは難しいです。

6で火を止めてからすぐ冷水にいれると黄身は生っぽい仕上がりになり、追加する水を250ccにすると昔ながらの半熟卵になります。

鍋の熱容量や気温によって、秒数は変わってきます。上記の数字を参考に調整してみてください。

2015年1月22日木曜日

EmberをXMLで

はい、まだ続きます>Ember

このところ平均睡眠時間が4時間を切っているので今日は手短に。勤務先で別のシステムについてもEmberを使えないか?という話が出てきまして。ただ、問題はそのシステムはAPIがすべてRESTというかXML。

しかしEmber DataさんはもうXMLの欠片もない世界。公式APIを隅から隅まで見ても、やっぱりできません。

が。

需要あれば供給あり。見つけました。


さっそく試してみたのですが…エンベロープなどXMLの書式が違うのか、エンドポイント間で通信はできるものの取得したXMLをmodelに入れても表示できない…というか変換できねーよエラーになってしまいます。

で。

こうなったらjQueryでXMLを取得して、それをJsonに変換すりゃあいいんじゃね?と思ってググってみたら…ありました。


やっぱりみんな困っているのね。もちろん、今更XMLなんて使いたくないんだけどレガシー対応とかいろいろあるからしょうがない。

ということで、上記ページで教えてもらったコード、ばっちり動きます。良かった良かった。

念のためですが、xml2jsonにはjQueryのプラグインを使ってください。同じ名前の他のライブラリ等だと動きません(ハマりました)。

そして、部品沼は淀む

Google Spreadsheetを使って「次に通販で頼む品物」などをメモしてます。これは秋月用のページ…


で、ある程度の金額になるか、急に欲しい必要なものが出てきた時には型番をコピーして…


ペーストすれば…


発注できてしまう…

便利すぎて困っちゃう…

2015年1月21日水曜日

Ember+Bootstrap3でナイスなモーダルダイアログを

なんだろう、この「居るよね、こういう奴」感w

…出そうとしてハマった記録です。

■公式ページ■

USING MODAL DIALOGSというページがあるのですが…この通りやっても動きません。何で動かなかったのかはこれから調べるんですが…とにかく、下の方にあるサンプルコード表示窓から正しくコピペしても動きません。ああもう、何時間ツブしたんだよorz

■ここがバッチリ■

で、どうにかならないかと探して出てきたのがここ。
  MASTER YOUR MODALS IN EMBER.JS
ember modal dialogで探すと2番目に出てくるんですけどね。ともかく、テキスト読みながら、必要なhandlebarsを補っていけば、ちゃんと動きます。bootstrapのfade dialogも効いて、ズルっとダイアログが出てきた瞬間「やったー!」と大声を上げてフロアの人の注目を浴びてしまいました。

なお、コピペで動かない場合には、一番下にサンプルコードのページがありますので、そちらを使ってください。自分でコピペしたものと比べると間違いがよくわかります…私のように。

ステップバイステップでコードの意味が解説されているので改造も簡単だし…今後はここで勉強しようっと>ember guru

■{{outlet}}について■

Emberを扱い慣れている方には当たり前のことなのだと思いますが、ググってもすぐには出てこなかったことなので説明しておきます。

ご存知の通りEmberはone page htmlをWebアプリを作ることができます。その際、一度に表示されるのは
<script type="text/x-handlebars">
で示されるテンプレートで区切られた範囲です。ただ、通常のWebアプリではツールバー、フッター、サイドバーなど共通の要素が多いです。そういうのをいちいち、各テンプレート内に置くのはあまりにもダサいです。こういう場合には、
<script type="text/x-handlebars">
  {{toolbar}}
  {{outlet}}
  {{footer}}
</script>
のようにして外側を定義します。ここでは data-template-name が指定されていませんが、なしだとアプリケーション全体で共通して【外側】として扱われ、遷移したページは勝手に {[outlet}} のところに挿入されます。

…知りませんでした。

知らなかったので【内側】の部分を全部コンポーネントで作って {{yield}} で挿入していました。ははははははははははははh orz

また、
{{outlet}}
{{outlet "modal"}}
と並べて書いておけば、常時outletに【内側】のページが表示され、指示をすればその上にモーダルダイアログが表示されます。overlayに関するスタイルなどは勝手にemberが面倒を見てくれます(サンプルではbootstrapが装飾してくれています)。以下のコードは、ダイアログを開くためのボタンで、
<button {{action 'showModal' 'settings-modal' model}}>settings</button>
そこから呼び出されるのが以下の関数です。
showModal: function(name, model) {
  this.render(name, {
    into: 'application',
    outlet: 'modal',
    model: model
  });
}
結果として {{outlet "modal"}} に、'settings-modal'というコンポーネントが表示されます。くどいですが、outletは予約語、'modal'は名称です。

■data-template-nameなしと"index"指定■

ついでに <script type="text/x-handlebars" data-template-name="index"> に関しては「何も指定しなければ初期状態で表示される」ぐらいしか書いていないのですが、これと data-template-name なしのhandlebarsとの違いは、なしは外側ページ、data-template-name="index"アリは外側ページのoutletに初期表示されるテンプレート、っていうことになるようです。

蛇足ですが、なしだとApplicationController、アリだとIndexControllerがcontrollerになります。暗黙の了解が多くて悩むことも多いのですが、わかってしまえばスッキリですね。

なおjsbin.comを使うと、アトリビュートを削ったり {{outlet}} を足したりした結果が即座に反映されるので、とても勉強になります。ぜひご自身の目でお確かめください。

さーて、明日はAuthenticationを調べて、その後は無限スクロールをpromiseとbootstrapを使って実装してみます。このペースなら、予定通り今週中に開発中のアプリに必要な技術要素をだいたい網羅できそうだなぁ。

いやはや…@53歳。

2015年1月20日火曜日

Ember.jsで初心者が落ちた穴

Building Web Apps with Ember.js [Kindle版]

大変、頼りになります。

Emberを使ってハマったネタを集約しておきます。まぁ、わかってしまえば「ドキュメント読めよw」って感じなんだけど…チュートリアルの更新が追いつかなかったり、暗黙の設定が若干進みすぎ気味のframeworkなので、自分が落とし穴に落ちていることすら気づかないこともあるので。
  1. Routingを呼ぶ #linkTo は #link-to に変わりました。
  2. handlebarsの id は id から data-template-name に変わりました。
  3. コンポーネントの名前は、必ずダッシュを含む必要があります。
    data-template-name="side-bar"
    みたいな感じで。ダッシュ取るとエラー出ませんが、動きません(記事)

Ember.jsのコンポーネントを使う

こんなにでっかく書いてあるのにorz

昨日はEmberのコンポーネントを使おうとして見事にハマりました。

結論から申しますと、コンポーネントの名前は、ダッシュで切らないといけません。公式のGUIDEにも書いてあります。しかし、そこに気付かなかったために3時間ツブしました。フレームワークを再ダウンロードしたり、ページ上で読み込む順番を変えたり、もう思いつく限りの試行錯誤をしたけど動かない。あげく、チュートリアルの関連コードを貼ってみたら動いてしまう。で、何度目かにようやく「コンポーネント名は、ダッシュを含まないとあかんよ(Components must have a dash in their name.)」の記述に気づいた次第。動いたさ。ああ動いたさ。

なお、ハマったネタとして、こっちにまとめておきます。今後、ネタが増えないことを祈ります。いやマジで。とりあえず、ChromeのEmber Inspectorを試してみます。

以下余談。

MVCとしてのEmberは大変良く出来ています。サイズはやたらデカいのですが、実際に走らせてみると表示はむしろ他のMVCフレームワークよりも速く、特にどこかEOF(NeXTSTEPのEnterprise Object Frameworkなんて知ってる人いるかなー)を思い出させるようなオブジェクトの連携に関しては重いという感じがありません。設計思想もCoCが徹底されていて余計な設定やらBoilerplateな記述はほとんど必要ありません(まぁ「暗黙の設定」が多すぎて、それでハマることも多いんですがw)。

が。

どっかでも批判されていましたが、ドキュメントの更新が追いついておらず、公式サイトでもチュートリアル本文とサンプルコードが一致していなかったり、CoCなのに重要なアトリビュート名が変わったりで「もう誰も信じない!」な状態に陥ることもあります。

#linkToが#link-toに変わったこととか、idがdata-template-nameになったり。上記のリンクを含めて本家のサイトでもバラバラだし、日本語の解説ページで一番充実しているDevelopers.ioこの入門シリーズにも反映していただけるとありがたいのですが…。

…まぁDevelopers.ioで一番改めてもらいたいのは、あの歯茎だけどね。とにかくバナーの写真のお前らはこっち見るなw

…それはともかく…ドキュメントはしっかり読みましょう。少なくとも「Note」ってところぐらいはね。

2015年1月17日土曜日

SOP-28ピン(過去最多)のリフロー

これは成功した方。フラックスが汚い。

久しぶりにはんだリフロー。antendoのハンダメッキ基板にSOPの28ピンという過去最多のピン数でしたが、2枚に行って1勝1敗でした。

なるべくペーストの塗布を少なくした方が2箇所もブリッジして失敗し、多めに盛った方が成功という不思議な結果でした。足のまわりをルーペで見ても問題ないので、プラスチックパッケージの下でブリッジしているんですかね。フットプリントにはみ出した分の拭き取りが甘かったかもしれませんが、品質管理(w)の基本である証跡(塗布してパッケージを乗っける前の写真)を撮り忘れたのが致命的でした。

なお、塗布には例によってマイナスドライバーを使いました。写真のように、盛大にはみ出してはいるのですが、塗った後、パッケージと基板に挟まる部分については拭き取りました(つもりだった)。

使用機材は1200wのホットプレートと、放射温度計です。どっちもアマゾン。ハンダは共晶ハンダを使っています。換気のため、台所の換気扇の真下で作業を行い、窓を一箇所、細く開いて循環性を高めます。

温度制御は例によってまったくの手動ですが、こんな感じ:

  1. 予熱して150度前後になったら電源を切り蓋をし、2-3分放置。
  2. 温度を測定して140-160度ぐらいの場所を探して基板を置く
  3. 蓋をして1分間放置(この間電源はOFF)
  4. 蓋を開けてヒーターON
  5. 基板周辺の温度が230度を超えないようチェック
  6. 超えたところでヒーターをOFF。その後も温度は上昇を続けるので、それを見越して早く切るわけです。何度で切るかは使っているホットプレートや置き場所、室温によっても違うのですが…基板を乗せない状態で何度も試して「この温度で切れば250度を越えない温度」を求めておきます。うちの場合、それが230度でした。
  7. ハンダが溶けてきます。基板の上の温度などもチェックして230度を超えているようなら問題なし、なるべく早く冷ましましょう。と言っても、取れる手段はうちわで扇ぐぐらいしかないんですが。
  8. ハンダが固まる温度を下回ったら、素早くピンセットなどで基板を取り出します。

以下、役に立たない写真です。


aitendoのLEDドライバ基板

1枚目。塗布後。

冷ましているところ。検査の結果は2箇所ブリッジ

2枚目。手が滑って落ちた。汚え。

位置を直した。やっぱり汚え。でも結果は正常だったからイヤになる。
まぁ、そんな感じで。

3Dプリンタならぬ、プリント基板プリンタがKickstarterとかに出ているみたいですが、いくらぐらいなんでしょうねぇ。最終的に焼結する必要があるみたいですが、表面実装部品もそのときついでに焼付けできる=スキージングが要らなくなるのであれば少し高くても欲しいのですが。

2015年1月12日月曜日

Play!アプリとBoneScriptの通信 - 3.BoneScript

「BBBとは?」みたいな余計な説明がなくて中身が濃い。

というわけで、Play!アプリとBoneScriptの通信、完結編です。

  1. 構成
  2. Playアプリ
  3. BoneScript

■BoneScript■

以前、BoneScriptで7セグメントLEDを駆動したら、毎秒170桁しかダイナミック点灯させることができずにちらつきました。その際には各セグメントのon/offもループしていたのでおよそ毎秒7x170回はループしていた、ということになります。ダイナミック点灯は無理でも毎秒10回程度のサンプリングなら余裕ですね。8bit時代のBASICマイコンで空のFOR〜NEXTループを回すと250回ぐらいだったかなぁ(遠い目)。

ということで、以下ソースです。


特に目新しいことはしていません(できません)。line 11で100m秒ごとのインターバルを設定してchechPIRを呼び出し、digitalReadのコールバックとしてprintStatusを呼び出しています。

printStatusでは100m秒ごとにサンプリングして入力がHIGHならcountDetectedをインクリメントし、「1分間のうち何秒間、PIRセンサがHIGHを返してくるか(なおPIRセンサは負論理で動きを検出するとLOWになるのですが、トランジスタでレベル変換した時に正論理に変わってます)」を求めています。結果はCSVとしてファイルに書き出し(line no 56 - 62)、JsonとしてWeb APIに送っています(line no 64 - 94)。

その処理自体は簡単なのですが、起動直後の中途半端な「分」を無視したり(prevMinute==99)、「睡眠記録」として作ったので昼の12時でファイル名が切り替わるようにしたりで(line no 44 - 54)、ちょっと面倒になっています。

なお、日付書式の変換には下記で公開されている「formatDate」を使わせていただきました。ありがとうございます。上記ソースを試す場合には末尾にformatDateをコピペしてください。
Qiita : 日付フォーマットなど 日付系処理

■今後の予定■

現状ではセンサーを追加したらDBの定義からやり直さなければいけないですが…それはなんぼ何でもIoTっぽくないので、定義を抽象化するなりシリアライズして「思いついたらすぐセンサーを追加してグラフ化」という路線を目指してみましょうか。

そういえばXivery申し込んだんだけど、返事が来ない…まぁXiveryを使っていたら、Play!でグラフ化するなんてことをやろうとは思わなかったでしょうから、むしろ感謝すべきかなw

2015年1月11日日曜日

Play!アプリとBoneScriptの通信 - 2.Playアプリ

もうこの本なしでは行きていけない(Play的に)

というわけで、前回の続きです。

  1. 構成
  2. Playアプリ
  3. BoneScript

■機能■

  1. Webページ
    1. ログイン
    2. グラフ表示
  2. Web API
    1. ユーザ登録 / 更新
    2. データ受信
    3. データ返信
こんだけです。ユーザ登録もAPIで済ませてます…まぁ自分用なので。

■githubリポジトリ■

公開しました。TareObjects/ShowSensorsです。

■ダメなコード■

公開してから気づいたのですが、System.outがそのまま残っていますねぇ…お恥ずかしい。一度必要なところはログに書き換えたのですが、余計なことをしてroll backかけた際に巻き添えになり、また書きなおすのも面倒なのでそのままに。

そのうち直しますm(_ _)m。

Calendarを定義しているところでやたらと
calFrom.set(Calendar.MILLISECOND, 0);
ってのが出てきます。不要なところもあるのですが、ミリ秒単位に初期化されていない値が入ってて一致しない、というバグでしばらく時間を潰してしまったので、それ以来入れてます。まさにあつものに懲りてなますを吹くってやつですねorz

■一応、Playプロジェクトを作るところから■

コマンドラインで
$ activator new ShowSensors
を実行し、プロンプトでplay-javaテンプレートを選択します。できたら
cd ShowSensors
activator run
これでアプリに必要なライブラリなどが自動的にダウンロードされ、ビルドされます。メッセージが落ち着いたらブラウザで http://localhost:9000 を表示するとplay!の画面が表示されます。なお、この画面は、conf/routesの

GET     /            controllers.Application.index()
public static Result index() {
return ok(index.render("Your new application is ready."));
}
及びapp/views/index.scala.html, app/views/main.scala.htmlから生成されています。

■Playプロジェクトにソースを追加する■

Play!は「設定より規約」なので、所定のディレクトリにファイルを作れば、あとは勝手にactivatorが認識してくれます。ただ、vimだけで作業している分にはそれでも問題ないのですが、Eclipseで作業する場合にはコマンドライン側でソースを追加した後、一度Eclipseを終了してから
activator eclipse
でeclipse用の設定を更新し、Eclipseを起動してからプロジェクトを右クリック→Refreshをする必要があります。

また、通常はactivator runしたままで作業を続けられるのですが、build.sbtなどappディレクトリの外にあるプロジェクトの構成に関する部分を修正した場合には、一度activatorを終了してから再起動し、activatorのプロンプト上で
update
eclipse
clean
run
とします。cleanは省略しても良いはずですが、一度ハマったことがあってそれ以来念のため実行するようにしています。

■モデル■

今回、persistentにはEbeanを使います。Springにはいい思い出がないのと、せっかくPlay!がCoCなのにXMLでチマチマやってられっか、ってことでw

モデルはデータベース用とWeb API用が必要です。データベース用はUser.javaSensorData.java、Web APIとして返すJsonの定義にSensorDataRest.javaです。

いずれも特別なことはしていませんが、SensorData.javaでMany to Oneリレーションシップを定義する際に通常はpublicでインスタンス定義すればそれでOKなはずですが何故かうまく動いてくれず、ググったところ「play!のバグじゃね? アクセサにしたら動いたよ」とのことで、回避できました。

ソース:

それにしても、こんな風にクエリを書けるのは、ホントに楽です。S2JDBCを更に洗練した感じで、今までEOFのEOQualifier最高!と思っていましたが、宗旨替えします。


■ユーザ登録/更新■

Application.javaのnewUser()、フツーです。


■データ受信■

Application.java、receive()。curlをそのままソースに貼っておくと手動テストが楽ですが、こうやってコピペに頼るからいつまで経っても覚えないんですよね…。


■データ返信■

データを返すAPIとして、GET用とPOST用を用意しました。こっちはGET用です。


■認証■

人生で大事なことはタイミングにC調に無責任、と歌ったのは今は亡き植木等師匠ですが、Playでの認証機能に最低限必要なのは、ログインのためのフォームAuthenticatorの実装、あとは認証の必要なAPIに@Security.Authenticated(Secured.class)アノテーションを付けてやるだけです。

詳細についてはこちら(「認証機能の追加」)…というか、ほぼここからコピペして使ってます。

■データ表示■

Playとしては、Application.javaで単にgraph.scala.htmlを返しているだけです。

で、そのgraph.scala.htmlではD3.jsを使って、PlayアプリのWeb API(上記「データ返信」のところ)からデータを読み込み、グラフを描画しています。以下はデータを読み込んで15分ごとの平均値を求める処理です。平均値なんてサーバ側で求めたほうが良いと思うのですが、動かしてみたら思っていた以上に速かったのでそのままにしていますw なお、念のためですが、これだけでグラフが出るわけでなく、この後に縦軸横軸などの設定が続きます。

■次回は■

いやー、ほんとにサンプルを切り貼りしただけで何にもしていないのですが、でも1つにまとめて動かすのにホント苦労しましたわ。

さて、次はBoneScriptを公開します(しました)。明日の予定です…三連休で良かった。

gist、知りませんでした…

大掃除の成果

今までここにソースを貼るときには、手動でソースを成型して書式を設定してました。貼った後で改行が崩れていたりするとまたそれを治すのが面倒で。

が。gistって便利っすね…何の手間も要らないっすね…。

ということで、途中まで書いてたPlay+Bonescriptの件、現在修正中です。

2015年1月10日土曜日

Play!アプリとBoneScriptの通信 - 1.構成

余分なジャンパが苦闘の痕跡を示すのだった

表題の通り、PIRセンサーの状態をBeaglebone black上のBoneScriptで読み取ってHeroku上のPlayアプリへ送り、D3.jsを使ってグラフ表示する方法をまとめました。

  1. 構成
  2. Playアプリ
  3. BoneScript

■アナログは苦手■

前回の記事の後PIRセンサの調子が悪くなってしまい、対応に追われました。どうもPIRモジュールの温度特性が良くないようで、プルアップ抵抗などを調整してうまく動くようにした後、外出や就寝で暖房がきれると徐々に特性が悪化してしまいます。

今回使っているPIRの最終段はオープンコレクタなのですが…コレクタ側に100Ωの保護抵抗が入っているためlowでも電圧がすっきり落ちてくれません。プルアップで調整するのも面倒になってきたので、これは2SC1815でバッファ入れて解決しました。ベースを10k、コレクタを1kΩで3.3vからプルアップし、エミッタをGND、コレクタからBBBのGPIOにつないでます。



あともう一つ、PIRからのノイズなのか、そのままだとGNDに200mVぐらいのスパイクノイズが乗ってしまってます。これも使い始めたころはなかったのですが、室温が15度を切るようになったから悪化したように思います。なので、4.7μFのケミコンと0.1μのセラコンを入れたところ見違えるように安定しました。

いやはや。

■ハードウェア構成■

センサには秋月の焦電型赤外線センサモジュールを用い、Beaglebone blackの5v電源出力とGNDを接続、上記回路で安定させてからBBBのP8_19に接続しています。非常に単純です。

なお、別のところでも書きましたが、最初は以前秋月で売っていたParallaxのPIR Rev.Aを使ってみたのですが…室内での人の動きと無関係に信号が出ていて、どうやっても改善しなかったので諦めました。現在秋月での扱いが終了しているのは、何か問題があったからではないか?と邪推している今日このごろ。貧乏サラリーマンの数百円を無駄にした恨み、思い知るがいい(違

■まずPlay側■

あっちこっちのサンプルの寄せ集めですが、こんな構成になっています。
controllers---Application.java
              Secured.java
models--------SensorData.java
              SensorDataRest.java
views---------graph.scala.html
              index.scala.html
              login.scala.html
              main.scala.html
Secured.javaなんてファイル名はまさにこのサンプルそのまま、笑ってやってください。

このアプリをHeroku上で稼働させています。データベースには同じくHerokuのPostgreSQLを用いています。どっちも無料枠内。PaaS万歳。

グラフ表示アプリには必要最小限の認証を付けました。でないと「留守・就寝中を世界に向けて発信する」アプリになってしまいますので。

グラフの表示にはD3.jsを使っています。ブラウザ上のD3からPlayアプリのAPIを叩いてJsonで過去24時間分の1分ごとのデータを受け取り、15分単位に集計してグラフを表示します。

■BBB側■

Beaglebone black Rev.Cはほぼ素のママで、BoneScriptを動かしています。0.1秒ごとにサンプリングして1分間のうち何秒間センサが動きを検出したかを集計し、1分ごとにHeroku上へとJSON形式のデータを送っています。

今のところ、送信エラー時のリトライは行っていません。Herokuは24時間に一度勝手にインスタンスがリスタートするので、エラーが出たらバッファにためといて再送するような仕組みを入れておくべきなのですが…。

■次回■

Play!のソースについてご説明します。公開しました。

2015年1月6日火曜日

Energia + MSP430G2でのハマりポイント

そうさ、またデジタル時計さ。MSP430G2553+RTC+秋月巨大LED
小数点のポートはデバッグ用に使用中

■UART関連■

同じG2でも、UARTのTxとRxが逆になっているものがあるので気をつけましょう。2553でもRevision 1.4以前とRevision 1.5は異なります。これはLauchPad基板のジャンパで切り替えるようになっています。

Guide to the MSP430 LaunchPad (MSP-EXP430G2)

シリアルモニタでLaunchPadからSerial.write / printで出力されてくる値を見るにはTxを使うのですが、ジャンパが違っていると書き込みできません。Energiaからの書き込みは正常にできるので、てっきり正しくつながっているものと思い込んでいたら、違いましたorz

■sprintfがクラッシュ■

複雑な書式指定をするとメモリ領域がメチャメチャになってクラッシュします。小さなプログラムだと通っちゃうことが多いのですが、10KBを越えるようなプログラムで、例えば、
sprintf(buf, "%02d%02d%03d%d", h, m, t1, t2);
とやると、以下のような症状が出たりします。

  • bufに値が入らない
  • 数秒ごとに繰り返しsetupが呼び出される
  • シリアルポートが文字列の途中でぶっちぎれる
  • 一度電源引っこ抜かないとEnergiaから書き込めなくなる


解決策としては、バッファとして使うメモリにvolatile指定を行い、sprintfの書式、特に数値変換については極力単純にして、あとは(上の行と同等のことをするには):
volatile char buf[16],temp1[16], temp2[16];
sprintf((char *)temp1, "%d", 10000 + h*100 + m);
sprintf((char *)temp2, "%d", 10000 + t1*10+t2);
sprintf((char *)buf, "%s%s", (char *)temp1+1, (char *)temp2+1);
で1つにまとめます。temp1,temp2を+1しているのは最初の'1'をスキップさせる古いc言語のテクニックです(懐かしい…)。

■MSP430G2553について■

これ温度センサー内蔵なんですね。analogRead(TEMPSENSOR)使うと華氏*10で返ってくるので、楽です。ワンチップで温度計作れます。我が家の他の温度計とも誤差1度以内なので、まぁ合っているんだろうなぁ、みたいなw

で、巨大LEDですが…3.3v駆動+PWMで制御しているのをいいことに、電流制限抵抗なしでつないでます。良い子は真似してはいけません。

さて、あとはRTCとの接続か…。

一応Xtalを外付けしてオープンソースのライブラリをつかえばリアルタイムクロックとしても動くのですが、年月日まで管理してくれないのでその辺を自前で実装するのが面倒くさい。かといって、RTCについても以前RTC-8564NBをArduinoにつないだときのソースを探すのが面倒くさい。

昨日今日とsprintfで全能力を使い果たしてしまったので、まぁそのうち元気が出たら作ります。

私を何より元気にするのは現金なんすけどねw

■追記■
これをデジタル時計として動くようにしました。ソース公開してます。予定ではRTCチップを外付けする予定でしたが、水晶発信しだけ外付けして使いました。

2015年1月5日月曜日

LEDアレイを波打たたせた



上の動画、音量注意っす。調節する方法がわからんw

各色LEDが一列に並んだモジュールを電子工作仲間のOさんから頂戴しました。どうもありがとうございます。

LEDとデジタル時計が三度の飯より好きな私なので、さっそくLチカしてみました。ただ、普通に点滅させても面白くないので、ウェーブしてみます。でもウェーブさせるにはPWMが必要ですが、いただいたのは12bit分、Arduino unoのPWMは6chしかありません。

ので、ソフト的に処理しました。一番内側のループphaseの値を0〜31まで変化させ、sinテーブルの値がその値よりも大きければ点灯、小さければ消灯させます。sinテーブルから拾ってくる位置をピンごと(i*3)に、また時間の経過(offset)ごとにずらしていけば、こんな具合いにうねうね動きます。モジュールの端にGND端子があり、1枚はArduino unoの13ピン隣にあるGNDに、もう1枚のGNDは7ピンに接続してLOWを出力しています。

だいたいPWMとしての基本クロックは70hzぐらい、肉眼で見ている分にはあまりフリッカは感じないですが、目をすっと動かすと点滅が軌跡となって見えますねぇ。


以下ソースです。
const int p01 = 13;
const int p02 = 12;
const int p03 = 11;
const int p04 = 10;
const int p05 =  9;
const int p06 =  8;
const int p07 =  6;
const int p08 =  5;
const int p09 =  4;
const int p10 =  3;
const int p11 =  2;
const int p12 =  1;
 
const int pGnd = 7; 
const int pins[] = {p01, p02, p03, p04, p05, p06, p07, p08, p09, p10, p11, p12};
const int nPins = sizeof(pins) / sizeof(int);
const int nSin = 32;
 
int iSin[nSin]; 
void setup() {
  pinMode(pGnd, OUTPUT);
  digitalWrite(pGnd, LOW);

  for (int i = 0; i < nPins; i++) {
    pinMode(pins[i], OUTPUT);
    digitalWrite(pins[i], LOW);
  }

  int half = nSin / 2;
  for (int i = 0; i< nSin; i++) {
    float d = (float)i / (float)nSin * 2.0 * 3.14159265;
    iSin[i] = sin(d) * half + half + 2;
  }
}

int phase = 0;
int outer = 0;
int offset = 0;

void loop() {

  for (int i = 0; i < nPins; i++) {
    int output = iSin[(i*3 + offset) % nSin] /2;
    int lowHigh = (output > phase) ? 1 : 0;
    digitalWrite(pins[i], lowHigh);
  }

  phase++;
  if (phase >= nSin) {
    phase = 0;
 
    outer++;
    if (outer > 2) {
      outer = 0;
   
      offset++;
      if (offset >= nSin) {
        offset = 0;
      }
    }
  }
}

2015年1月4日日曜日

PlayとD3とBeaglebone



会社でのお仕事として年明けからPlay+Spring+Emberを使ってサイトを1つ立ち上げることになっているのですが、どれもチュートリアルをなぞった程度で本格的に使ったことありません。しかし:

  • 休み中はしっかり休みたい。
  • でも勉強しておかないと死ぬのは確実。
  • でも休み中は電子工作方面に浸りきりたい

ので、この3つを満たすために「Beagleboneで収集したデータをPlay! frameworkで書いたHeroku鯖へ送り、グラフ化して表示」ってやつを作ろうと思います。visualizeには同僚さんに教えてもらったD3jsというフレームワークのグラフがあまりにもきれいなので、それ使います。EmberとSpringのことはとりあえず忘れます。

■動作フロー■

基本的にこんな動き。まずセンサ〜収集系:
  1. Beaglebone Black Rev.c上でPIRセンサーを読み取り人の動きを検出
  2. 検出した結果は1分あたり動いた秒数として出力し、Heroku鯖へ送る
  3. Heroku上で動くアプリはWeb APIとしてデータを受信する。
  4. 受信したデータはHerokuのPostgreSQL上にリングバッファ的に保存(Herokuのポスグレは10k行まで無料で使えるので)。
続いてデータ表示系:
  1. ブラウザからのリクエストを受けてHTMLを返す
  2. HTML上でD3.jsがHerokuへデータをリクエスト、Jsonで返す
  3. D3.jsがグラフを描画
D3.jsはデータ形式も多彩でcsv, tsv, json, xmlなど思いつくものはだいたい入ってます。

■予備実験■

BBB+PIRセンサーは現在絶賛安定稼働中なので、未体験要素としてD3jsでのグラフ生成を試してみます。棒グラフを出すだけならChart.jsの方が圧倒的に簡単なのですが、もうね、表現力が圧倒的すぎるのですよD3様は(そこまで使いこなせるかどうかは別の話)。

ということで、まずチュートリアルからサンプルソースをコピペ。こんな立派なグラフがこれだけで?と思うぐらいソース短い。

■Play 2.3.7■

しばらく自宅MacでPlayをいじっていなかったら、ターミナルでactivatorとタイプしてもエラーになってしまう。のでbrewでアンインストール&インストール(安易だ)。
brew uninstall typesafe-activator
brew install typesafe-activator
で、プロジェクトを作る:
activator new ShowSensors
起動後、play-java templateを選択。戻ってきたらactivator uiを起動
cd ShowSensors
activator ui
しばらくしてブラウザ上にIDEが開く。最近ブラウザIDEが流行ってますねぇ。ただ、エディタがタブ対応でないならviの方がマシだし、何よりcompile/runがうまくいかないので今回も利用を見合わせます。Play2の場合、Eclipseを使うメリットがあんまり感じられないのでsublime text2使います。ctrl+cで終了し、
activator run
ビルドその他のメッセージがおとなしくなったところでブラウザで localhost:9000 を開けばいつものページ、緑色の「Your new application is ready」のメッセージがお出迎えしてくれます。

■ヘンなエラー■

ひと通り実装をしたところで試すとこんなエラーが:

[error] play - Cannot invoke the action, eventually got an error: java.lang.RuntimeException: Error getting BeanDescriptor for path User from models.User
ググってもどうもピンと来ない。何となくEbean系の間違いのようなので、
  • とりあえず@OneToMany / @ManyToOneなどを消して見る
  • とりあえずactivator clean / activator updateなどを試す

などやってみたのですが、ダメ。その後、トレースしてみると、
User user = find.fetch("user").where() .eq("email", inEmail) .findUnique();
ここで落ちてました。そりゃそうだ。ここを
User user = User.fetch().where() .eq("email", inEmail) .findUnique();
に変えたら通りました。先にUserの生成と検索についてのtestを書いてりゃ容易に切り分けが出来ていたケースですね…反省(@元日)。

■で、Web API■

フツーにRoutesにURIとコントローラを書いて、
GET /fetchFromHours controllers.Application.fetchFromHoursGet()
コントローラでdbからデータをfetchし(仮にarrayDataとする)、最後に return ok(Json.toJson(arrayData)); と書けばOKです。以下は過去24時間の計測データを返すAPIの処理:
// curl --header "Content-type: application/json" --request GET http://localhost:9000/fetchFromHours
public static Result fetchFromHoursGet(String inEmail) {
User owner = User.findByEmail(inEmail);
Calendar calFrom = Calendar.getInstance();
calFrom.setTime(new Date());
calFrom.add(Calendar.HOUR_OF_DAY, -24);
calFrom.set(Calendar.MILLISECOND, 0);
Integer hours = 24;
List<SensorData> sds = SensorData
                       .findByUserSinceDateForHours(owner, calFrom, hours);
if (sds == null || sds.size() == 0) {
return badRequest("no data found");
}
List<SensorDataRest> sdr = new ArrayList<SensorDataRest>();
for (SensorData sd : sds) {
sdr.add(new SensorDataRest(sd));
}
return ok(Json.toJson(sdr));
}

■Macにポスグレをインストールして起動■

brew install postgresql
initdb /usr/local/var/postgres -E utf8
postgres -D /usr/local/var/postgres &
これで
psql -l
とやってデータベース一覧(初期状態の設定テーブルが2-3個あるはず)が見えればOK

■Web APIでURLパラメータを渡すには■

今回は使いませんでしたが、http://.........../apiName?name=kura&email=foo@bar.comという処理をしたい場合には、routesに
GET /apiName  controllers.Application.api(name:String, email:String)
と書き、ソースに
public static Results api(String inName, String inEmail) {
....
}
と書けばOKです。routesにはパラメータが省略された時の値を指定することも可能で
GET /apiName controllers.Application.api(name:String ?="kura", email:String ?="tare@panda.com")
と書きます。RESTfulな書き方については簡単に見つかるんですが?&でパラメータを渡す方法がなかなか見つからなかったのでメモしておきます。

■Heroku上のpostgreSQLへ接続■

まずHeroku上のpostgreSQLを有効にします。

すると、URLやid, passwordなどが通知されますので、それに基づいてapplication.confを書き換えてdatabaseをH2からpostgreSQLに変更し

build.sbtにpostgreSQLのドライバを追加します。
libraryDependencies ++= Seq(
  javaJdbc,
  javaEbean,
  cache,
  javaWs,
  "com.fasterxml.jackson.core" % "jackson-databind" % "2.4.4",
  "com.fasterxml.jackson.core" % "jackson-annotations" % "2.4.4"
,
  "postgresql" % "postgresql" % "9.1-901-1.jdbc4"

)
ま、上の設定が決まるまで一発では動いてはくれなかったんですが…その辺は末尾の「ハマりリスト」をご笑覧くださいorz

■Herokuへdeploy■

これはもうここに書いてあるそのまんまです。
  Heroku へのデプロイ(playframework.com)
便利になったものです…初回はdependencyのチェックでエラい時間かかるけど、待ってりゃ終わります。終わったところで

で、以下の様な表示が出ればOK
koichi$ heroku ps
=== web (1X): `target/universal/stage/bin/showsensors -Dhttp.port=$PORT`
web.1:
up 2015/01/04 08:36:10 (~ 2s ago)

大事なのはここのupってところ。これがcrushedだとデプロイor起動に失敗したということ。もう見飽きるほど見ましたよ…ええ…。

■BoneScript変更■

テストではcsvに書き出すだけでしたが、コードを追加しました。まずpayloadを作って
var body = JSON.stringify({
    date:  sDate,
    count: sCount,
    email: "kkurahashi@me.com"
});
POSTします。
var request = new http.ClientRequest({
    hostname: "ホスト名",
    port: 80,
    path: "/receive",
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "Content-Length": Buffer.byteLength(body)
    }
});
request.write(body);
request.end();
通常のPlayアプリだとポートは9000ですが、Herokuにデプロイすると特に設定しなくても80でつながります。他にエラー処理もあるけど、あとでGithubに上げるのでそっちをご覧くださいませ。

■できあがり■

8:48はトイレに行ってた

■今後■

上記は生データ表示なので24時間収集すると表示が細かすぎます。これを5分か15分にサマライズします。あとはローカルとリモートのPostgresをdev/deployで自動的に切り替わるような設定も組み込まないといけません。ぽすぐれと接続できないでウロウロしてた時にその辺の設定は全部後回しにしてしまい、現状はapplication.confを手動で切り替えておりますw

それからソースを掃除してからGithubでプロジェクトを公開します。まぁ今度の週末にでも。

そして以下は今回の作業でハマった箇所です。改めて見直すと…我ながら…アホです。でも失敗して覚える…というか失敗しないと学習しないタイプなので、とっても勉強になりました。正月休みはウォーキングにも行かないでこればっかりやってたせいで3kg太ってけども。

餅は危険です。

■ハマりリスト■

  • テストが作動しない
    • せっかくテストコードを書いたのに activator test を実行しても新しいテストコードが認識されないことがある。そういう場合には、activator cleanを実行すると直る。もしダメなら一度activatorからexitして(もし起動していれば)Eclipseを終了させ、activator cleanを実行してから再度activatorに戻ってtestを試してみる。
    • 全般的にソースを追加した場合にはcleanするかactivatorを一度終了した方がいいかもしれない。また、application.confやsbt関連ファイルを弄った場合にはactivatorを終了/再起動しないとダメっぽい。
    • あと、activatorを起動しっぱなしで半日作業したら「メモリが足りない」ってエラーが出たことがありました。Eclipseばかりではなく、たまにはコンソールも見ましょう。
  • @Constraints.Requiredが機能しない
    • Ebeanでは @NotNull を使うorz
  • @ManyToOne(fetch=FetchType.EAGER)が効かない
    • objをfetchしてきた時、obj.toOneには値が入っているけどobj.toOne.someとやるとnullになってしまう。toOneをprivateに変更し、getter/setterを設けることで解決。
    • StackOverflowには「Play!のバグじゃね?」って意見もあるけど、どーなんでしょうね。
  • 複数項目を対象にしたunique属性
    • @Entityの後に @Table(uniqueConstraints = @UniqueConstraint(name="制約につける名前", columnNames = { "attr1", "attr2" })) ...とカラム名を列挙する。
    • なお、java上のattribute名ではなくdb上のカラム名なので、対象となるattributeには@Columnでカラム名を指定するか、Evolution表示で出てくるカラム名を使うこと。
  • PostgreSQLと接続できない
    • application.confでのURI書式が違ってたorz
      db.default.driver=org.postgresql.Driver
      db.default.url="jdbc:postgresql://localhost:5432/データベース名"
      db.default.user=ユーザ名
      db.default.password=パスワード
  • PostgreSQLでテーブルができない
    • userというテーブル名は予約語なので作れませんorz
    • クラス名を変更するか、@Table(name="users")を追加してテーブル名を変更する。
  • その後、UserをUsersに変更したけど、evolutionで生成されるSQLが古いままでcleanなどをやってもcreate userのまま
    • 中途半端なところでevolutionが止まったため、管理テーブルplay_evolutionsだけがpostgreSQL上に出来ていたのが原因っぽい。
    • ので、drop databaseでまるごと削除したら動いた。
  • 以下、Herokuへデプロイできた後の話
  • コンソールやpsqlで見るとデータがあるのにAPIでfetchできない
    • Herokuがアメリカ時間だったため。以下の記事を参考にして、JSTに変更したら治った。インスタンスの再起動も不要でした。
    • http://blog.ruedap.com/2011/02/10/heroku-timezone-japan-jst
    • コマンドラインで heroku config:add TZ=Asia/Tokyo