TERRYのブログ

最近は競技プログラミングにお熱。

Sponsored Link

Netduinoで修論タイマーをつくる

f:id:terry_u16:20160124103525j:plain
卒論修論シーズンになりましたが、皆様いかがお過ごしでしょうか。
この時期になると研究室のムードが一気に修羅場っぽくなってきますね。
かく言う僕も現在M2ですので、ちょうど修論執筆真っ最中です。*1

締切が近付いてくると、あと何日残っているか気になるものです。
とはいえ、手動でカウントダウンするとつい忘れちゃう日もあるし……。
そこで僕は考えました。
「そうだ、Arduinoを使って自動でカウントダウンさせてやれば良いのでは?(ピコーン)」

構想

まず適当に概念図を書きます。
今回も.NET Micro Frameworkが使えるNetduino 3 Wi-Fi(ピン配置はArduino互換)を使用。
残り時間表示用の液晶ディスプレイ(LCD)は必須、
Netduino内蔵の時計は精度が悪いのでリアルタイムクロック(RTC)モジュールも欲しいです。
また修論シーズンはラボ泊する人も多いので、
暗くなったときにLCDのバックライトが眩しくないよう光センサで自動消灯機能を追加。
ついでに温度センサがあると体調管理に便利な気がするのでなんとなく付けてみました。
ラボのデスクにはコンセントがあるので電源はDC9Vで供給します。

ちなみにこの図はSurface Pro 4OneNoteで書いてます。
雑なざっくりしたメモが手軽に取れるので結構気に入っています。

部品購入

以前お世話になった秋月電子さんとスイッチサイエンスさんから、適当に部品を購入します。
福岡住みには通販の存在は大変ありがたいです。
今回使った主なパーツは以下の通りです。

スイッチサイエンス

部品 型番 価格
キャラLCDをTWIシールドにするキット BS21LAB-015 1296円
漢字/カナLCDシールド 3.3V/5V 兼用化オプション BS21LAB-016 432円

配線をすっきりさせたいので、今回センサー類は全てI2C(=TWI)接続のものにしています。
せっかくのArduino互換機なので、LCDはシールド化することにしました。
既製品でも良かったのですが、秋月の緑色バックライトLCDが気に入ったので今回はキットを購入。
また、NetduinoのI/Oピンは3.3V出力なので、
シールドキットの3.3V兼用化オプションも忘れずに購入しました。

シールドキットの組み立て


こ、こいつをはんだ付けしろと……。
はんだ付けなんて中学校の技術でしかやったことないので、
一番精神をすり減らしたポイントです。
ですが人間ひたすら気合でやればなんとかなるもののようで。



無事動作確認もパス。やったー!
ちなみにはんだ付けだけで2時間近くかかりましたので、
僕みたいに慣れていない人は普通に完成品を買うことをおすすめします。

回路図


回路図はこんな感じ。
ブレッドボード上の左のICはRTCモジュール、右の小さな基板は温度センサモジュール、
右上の透明なやつは照度センサのつもりです。
LCDシールドはNetduinoに重ねるのでここでは省略しました。
緑の導線はI2Cのクロック線を、オレンジの導線はI2Cのデータ線を表しています。
また、Netduinoのアナログ0番ピンにはフォトトランジスタで分圧された電圧(青)が、
デジタル12番ピンにはRTCモジュールからの割り込み信号(黄色)が入ってきます。
この辺は需要とやる気があれば日を改めて説明するかもしれません。
見辛いですが、実際にブレッドボード上に実装するとこんな感じです。

コード

using System;
using System.Net;
using System.Threading;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;
using MastersThesisCountDown.I2C;
using MastersThesisCountDown.Extensions;

namespace MastersThesisCountDown
{
    public class Program
    {
        static int anotherDisplayCount = 0;

        public static void Main()
        {
            // デジタル12番ピンの電圧立ち下がりで割り込み処理を行うポートをインスタンス化
            var interruptPort = new InterruptPort(Pins.GPIO_PIN_D12, true, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeLow);
            var lightPort = new SecretLabs.NETMF.Hardware.AnalogInput(Pins.GPIO_PIN_A0);

            // RTCモジュールによる割り込み処理
            interruptPort.OnInterrupt += (_, __, ___) =>
            {
                // 割り込みからRTCモジュールの秒カウンタの書き換えまで92μsかかる
                Thread.Sleep(1);

                DateTime currentTime;
                using (var clock = new RX8025NB())
                {
                    // I2C経由でRTCモジュールから現在時刻を取得
                    currentTime = clock.CurrentTime;
                }

                // ボタンが押されたら5秒間だけ裏画面になる
                StartCounters();

                if (anotherDisplayCount <= 0)
                {
                    // メイン画面(〆切りまでの残り時間)を表示
                    ShowMainDisplay(currentTime);
                }
                else
                {
                    // 裏画面(現在時刻・温度)を表示
                    ShowAnotherDisplay(currentTime);
                }

                ManageBackLight(lightPort);
            };

            while (true)
            {
                // メインスレッドは特になにもしない
                Thread.Sleep(1000);
            }
        }
    }
}

メインループはこんな感じです。
RTCモジュールから1秒ごとに割り込み信号を送信するようにして、
Netduinoの割り込み機能を使い、RTCモジュールから現在時刻を取得、
ディスプレイへの表示を行っています。
詳しいコードはGitHubに上げているので詳しく知りたい方はこちらで。
github.com

ちなみにですが、.NET Micro Frameworkでは、
割り込み処理は本来の意味の割り込みではなく、別スレッド上で実行されます。
そのため、メインの処理をしながら同時並行で割り込み処理をする、なんてことも可能です。

完成!


完成品がこちら。
時刻は起動時に付属のwifi経由でNTPサーバーから自動で取得し、
その後はRTCモジュールを使ってスタンドアローンで動作します。
普段はひたすら死のカウントダウンを行い、ボタンを押すと現在時刻と温度を表示してくれます。




ラボのデスクに置いてみた図。
ふと気を抜こうとしても嫌でも視界に入ってくるので、大変研究が捗るようになりました。
ちなみに周囲が暗くなるとバックライトを消灯する機能も付けたのですが、
一日中研究室の明かりが点いているのであまり効果はありませんでした……。


皆さんもArduinoでガジェットを作って、充実した研究室ライフを!

*1:余談ですが、今日は福岡が大雪で帰りのバスがなくなったため、この記事は研究室に泊まり込みで書いています。