バーサライタをいいタイミングで正しく点灯させるためには、1回転するには何秒かかるのかをキッチリと計測しないといけないです。
M5StickC内蔵のセンサーでできればよかったのですが、いい方法が思いつかなかったので、外部センサーを用いることにします。
ちょうど、以前にELEGOOキットに入っていたものを使ったフォトレジスタ&抵抗があったので、これを使うことにしました。
M5Stack:光通信
http://shikarunochi.matrix.jp/?p=2629
接続方法は以前に試してみたのと同じ。本来の部品として使用されて、彼らも本望であろう。
最初は空中配線で接続。動作することを確認しました。(よくこんな接続で動いたものだ…。)
うまく動作したので、小型基板に実装しました。
圧着工具持ってると、ピン付きの配線コードを自分の好きな長さで好きなだけ作れて便利です!
基板はこちらのミニユニバーサル基板を使いました。これも色々使えて便利!
aitendo:ミニユニバ基板(3枚入) [P-D139]
http://www.aitendo.com/product/16582
M5StackCでアナログ値の入力が可能なのはGROVE側の端子だけみたいですね。NeoPixelでG32を使ったので、開いているG33に接続します。フォトレジスタ基板もネジでガッチリ固定。
周りからの光の影響を防ぐ必要があります。ちょうどいいサイズの熱収縮チューブがあったので、いい感じの長さに切ってフォトレジスタにスッポリとかぶせました。
固定はホットボンド(グルーガン)です。固定に困ったときはホットボンド!
これで、ほぼ真下からの光のみを検出するようにできました。
フォトレジスタに光を当てるLEDですが、ライドウオッチにもともとついていたLEDをボタン押下で光らせるようにしました。
ボタン&LED基板の配線が、
こうなってたのを
こう。
これも最初からこうすることを想定されていたかのようなプリントパターンがありました!
モーター用の1.5V乾電池ではLEDを光らせることはできないのでLED用に3Vのボタン型電池を用意しました。
これもなんとかギリギリ納まった!閉じるのにちょっと苦労しましたが…なんとかなった!
あとは、LEDの光が反射しやすいようにアルミホイルを貼りました。(気持ち程度の効果ですが)
そして、光が周りに漏れないようにカバーしておきます。ペットボトルキャップ切ったパーツですw
1回転の計測は、フォトレジスタがLEDの上を通ったときに、フォトレジスタ回路から取得する値が大きくなることを利用して、
(これまでの値の平均値) * 100 < 今回の値
になったときに、LEDの上を通ったと判定してます。(100は試行錯誤による適当な値です。環境によってこれだとうまくいかないかも。)
LEDの上を通った時刻を基準位置として、1周するのに必要な時間は
1周するのに必要な時間 =(今回基準位置を通った時) – (前回基準位置を通った時)
となります。micros(); を使うと、起動からの時間がマイクロ秒で取得できますので、これを用います。
回転してない時の誤判定を防ぐため「1秒以内に2回以上、上の現象が発生した時」も条件に加えています。
これで、原点の位置と、1回転に要する時間が正確に取得できるようになりました。
1回の表示に使う時間は
1回の表示に使う時間 =(1回転に要する時間) / (分割数)
で求められますね。
これで、1回の待ち時間が分かったので、
1番目の位置表示→(決められた時間のdelay)→2番目の位置表示→(決められた時間のdelay)→ 3番目の位置
という感じで表示してみました。でも、なんかうまく表示されない。
文字は原点固定で表示されてるので、もう一息なのだ…。
delayMicroseconds(0)で、ノンストップしてこの状態。原点開始から「HELLO!M5♡」と描くつもりが「HELLO!M」の途中までしか描けてないです。待ち無しの最速でこれってことは、描画が間にあっていないということですね。
どうやら、計測も含めた1つ1つの処理が重くなって、じわじわと遅れ、半分ぐらい表示したところですでに1周回転終了している感じです。毎回行う必要がある analogRead も、microSecondレベルで考えると時間かかってそう。
ちょっとあきらめかけたのですが、現時点でLEDがどの位置にいるのかがわかるようになったので「データを律儀に抜けなく順番通り表示しなくても、単純に現在の位置で出すべきデータを出すだけでいいのでは…?」ということに気が付きました!
1番目の位置表示→(決められた時間のdelay)→2番目の位置表示→(決められた時間のdelay)→ 3番目の位置
だったのを
現在の位置表示→(適当なdelay)→ 現在の位置表示→(適当なdelay)→現在の位置表示
にしてみます。現在の位置は、
現在の位置 = (現在の時間 – 前回原点を通った時間) / (1回の表示に使う時間)
で計算できますね。
これでいけました!この方式なら、途中に別の処理を入れても破綻が起きないです!
ということで、完成したプログラムがこちらです。
POVforM5StickC/M5StickPOV/
https://github.com/shikarunochi/POVforM5StickC/tree/master/M5StickPOV
回転開始後、LEDを光ってること検出したら、NeoPixel点灯するようにしてます。この制御を入れることで、ボタン押下のタイミングで光りだすことができるようになりました。
M5StickCのHOMEボタン押すとNeoPixel消灯します。これ、タイミングによっては数個点灯しっぱなしになるみたいですね…。まあ、細かいことはよいでしょう!