2014年1月3日金曜日

Arduino時計+温度計

年末年始は電子工作で遊ぶ予定だったのに大掃除の際にハンダゴテを破損。次にいじれるのはいつになることやら…と思っていたら、思わぬところから発掘しました。

何年行方不明だっただろう…。
というわけで、SainSmartのキットからLCDと小型ブレッドボードとLM35(温度センサ)をつかって、デジタル時計/温度計を作ってみました。何を今更と言われようとも、私のデジタル工作の原点は秋月ならぬ信越商会のMN5311デジタル時計キットなので(アナログは今はなき三鷹トリオ商会で買った2石レフレックストランジスタラジオ)、ともかく時計を作らなければいけないのです。

Arduinoはハンダゴテ使わずに試作できてしまうのですが、SainSmartのキット付属の
LCDにはヘッダピンが付いていなかったので、ハンダ付けします。老眼が大いに障害になりましたが、何とか完了。ハンダの溶け込むリズムを思い出すのに時間がかかったぜ。

そして、小型ブレッドボードをパッチベイのように使って配線。まぁパッチベイといってもGNDやらVccなど複数の線が集まるところをブレッドボードのrowを使って配線するってだけですけども。

まずは、キットのテストコードをそのまま入力して実行。最初まったく表示が出なくて焦りましたが、コントラスト調整をしたら文字が出ました。また、LCDバックライトの抵抗を220Ωにしたら物凄く明るくて全体的に薄暗い写真になってしまいました。この後、1kΩまであげてみたのですが、それでもかなり明るいです。


続いて時計スケッチ。あちこちサンプルが上がっているのですが、いまさらArduinoで時計作る人も少ないのか、Timeライブラリの仕様が古かったりして使えません。ので、ググりつつコーディングしてアップロード。

温度計の補正に悩みましたが、それもなんとかクリア。とりあえず、
 温度 = analogPort値 ☓ 基準電圧 ☓ 100 / 1024
で上手いこと動きます。素子の出力電圧が1度=10mVなので基準電圧☓100、1024はフルスケール値です。なお、浮動小数点なら最後の3つの定数を電卓で計算して1つにしてしまえばいいのですが、浮動小数点演算の負荷を嫌って整数を使う場合は演算の順番を考えないとオーバー/アンダーフローを起こします。こういう場合、例えば500と1024を因数分解して演算の途中でも値がintの生の最大値32767を超えないようにします。今回は確実に動くこと優先で浮動小数使いました。また、文字列への変換もsprintfを使っています。書式指定のあるprintf/sprintfはプログラムサイズが大きくなるのですが、まぁここは確実に動くこと優先で…なお、Auduinoのライブラリではprintfの浮動小数への書式指定 %f は使えませんのでご注意を(少しハマりました)。

追記:
ArduinoのADCは基準電圧の切り替えが可能です。unoの場合は電源電圧、外部、内部(1.1V)に設定可能です。設定するには analogReference(type); のtypeにDEFAULT、INTERNAL、EXTERNALのいずれかを使います。EXTERNALの場合にはAREFピンに基準電圧を与える必要があります。詳細については以下のページが参考になりました。ありがとうございます。
  Arduino 日本語リファレンス - analogReference(type)

というわけで、何とか動きました。デジタル時計作ったのは何年ぶりかなー。

次はmbedのLPC1114FN28と適当なRTCを使って、ローコストかつデカイLEDデジタル時計でも作ろうっと。

#include <Time.h>
#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
time_t tokei;

int iYear  = 2014;
int iMonth = 1;
int iDay   = 3;
int iHour   = 18;
int iMinute = 20;
int iSecond =  0;

int lm35 = 0;

void setup() {
  lcd.begin(16, 2);
  setTime(iHour, iMinute, iSecond, iDay, iMonth, iYear);
  tokei = now();

  analogReference(INTERNAL);  
}

void loop() {
  
  while( tokei == now() ) {
    delay(100);
  }
  
  tokei = now();
  digitalTokei();
  digitalOndokei();
}


void digitalOndokei() {
  float val;
  int dat;
  char buffer[5];
  
  val = (float)analogRead(lm35) * 110.0 / 1024.0;
  dat = val * 10;
  sprintf(buffer, "%02d.%1dc", dat / 10, dat % 10);
  lcd.setCursor(11, 0);
  lcd.print(buffer);
}

void digitalTokei(){
  char buffer[20];
  
  sprintf(buffer, "%4d/%02d/%02d", year(), month(), day());
  lcd.setCursor(0,0);
  lcd.print(buffer);

  sprintf(buffer, "%02d:%02d:%02d", hour(), minute(), second());
  lcd.setCursor(4,1);
  lcd.print(buffer);
}


さて、一応時計なのでしばらく動かして精度を見てみようと思いますが、USBにつないだままにしておくのも少し不安があるので、とりあえず使わなくなったスマフォ充電用エネループをつないで放置したところ、約18時間で終了。消費電力150mAってところでしょうか。なお、スマフォ充電用のエネループを使うと写真ではわかりませんが何やら液晶が脈打ってるようになります。他の電源やUSBではこういう症状が出なかったので、電池の3.7V出力を5Vに変換するためのDC/DCがあんまり安定していないのかもしれませんね。



■追記■

その後、別バージョンの時計も作りました。この他にも教材用やアルバイトで3つ作ったw

Arduino時計+温度計(7セグメントLED編)
Arduinoユニバーサルボードにハンダ付けして作りました。私の部屋で元気に稼働中です。

Beaglebone Blackで7セグメントLEDデジタル時計
待ちに待ったBeagleboneがようやく入手してうれしさのあまりついデジタル時計を作ってしまいましたが、BoneScript(Node.js)でセグメントごとに制御しているため表示がちらつきます。digitalOutじゃなくBus命令があればもうちょっと速くなるんですが。とりあえず多セグメント用のLEDドライバを入手したので、そのうち改良します。

Energia + MSP430G2でのハマりポイント
製作途中の巨大7セグメントLEDデジタルクロック。TIの省電力MCU MSP430G2シリーズをArduino互換のEnergiaという開発プラットフォームで動かしています。マカーにはありがたい。

0 件のコメント:

コメントを投稿