ARDUINO RTC-LCD
Arduino はじめました
Arduino 始めました。リアルタイムタイマーリレーを完成させる予定です。このページでは、とりあえず LCD(液晶表示器)に RTC(リアルタイムクロック)からデータを取得し、現在時刻を1秒毎に表示するところまで掲載します。
今回準備したハードウェアとソフトウェア
Arduino Uno(純正品)を購入したのですが、意外と消費電流が大きいし、I2Cは2個しか刺さらないしで、これは教則的な使用方法を学ぶ、教材の立ち位置なのかな、と思いました。
そこで、中華サイトにて上記 Uno の 1/10以下(315円/個)の値段で購入した Nano Clone をブレッドボードに挿して使用してみました。
この Clone に使用されているマイコンは純正(328P)ではなく、上位互換品(328PB)です。購入時から焼かれているブートローダーが 328P 用のオールドバージョン(スケッチ書き込みの通信速度が現行の半分の速度)でしたので、MiniCore をインストールしてブートローダーを焼き直し、 ボードを ATmega328 として使用しています。
お試しで 5 枚購入しました。すべて DS3231SN と IC に刻印されていましたが、32kHz の出力を測定すると 32.768kHz を大幅に下回るものが 4 枚(32.661〜32.663kHz) ありました。差は 100Hz 以上(笑)、明らかに偽物です。まあ、正規ルートでこの IC を購入すると、1 IC あたり 2000yen 前後(時価)するので、フェイクであることはわかっていたのですが。 電池を入れて放置すること数日。何故か 2100年 になっているもの、ランダムにリセットされるもの、温度のズレが10度以上あるもの、3 日で 2 秒遅れるもの、とバラエティに富んでいます。残り 1 枚は 32.765Hz で時刻のズレは数日ではわからないものでした。これは中古かもしれません(刻印が他のものと違う)。5 枚中 3 枚は使用できないので、DS3231S#(SNより使用温度範囲が狭い)正規品を発注し、IC 取り外しの刑に処しました。
発注の翌日には IC が届いたので、早速取り付けて
分解能 1Hz 誤差 1ppm の精度で周波数測定できるかもしれない、というカウンターで確認
これが普通の DS3231S# です。DS3231 のデータシートにありますが、32.768kHz が出力されるのです。MIN も MAX も ありません、判で押したように 32.768kHzなのです。 これが狂っているものは、偽物か DS3231M かまたは壊れかけの中古品です(個人的見解)。
正規 IC は chip1stop(チップワンストップ)様にて 6 ピース購入いたしました。破格のお値段と迅速なるご発送ありがとうございました。
結局 RTC モジュール 1 台あたりの合計金額は 229(基板) + 959(IC) = 1,188yen となりました。ちなみに筆者のラズパイ用 RTC (seeed studio製 DS3231SN 搭載) は、購入当時(2021年) 1,299yen でした。2024年現在、これ 2,244yen に跳ね上がってます。某王手通販サイトでは 3,980yen おそるべし。
LCDもI2C接続のものを選びました。20文字×4行の表示領域を持つものです。専用のモジュールが裏側にはんだ付けされています。バックライトが眩しすぎましたので、ショートピンを外して、5.6kΩ の抵抗を取り付けました。
スケッチ
とにかく、後のことを考えると delay() の使用は NG ですので、色々考えた結果、millis() で1秒を計測後、経過時間をゼロに初期化する方法にしました。これで疑似的なマルチタスクが可能になりそうです(Windows 3.1 的な)。
時刻の設定は、筆者所有の raspberry pi 4 を使用します。筆者のラズパイはほぼ音楽専用機ですが、RTC (DS3231) を取り付けてあります。これの代わりに今回の"偽 DS3231SN" シールドを取り付け、以下のコマンドで現在時刻を設定しました。ntpサーバと同期しているので書き込み時の値は正確です。
$ sudo hwclock -w --local
--local を指定しない場合、UTC(世界協定時刻)が設定され、日本の場合だと9時間ずれます。
time_show.ino
1 : // LCD Clock for DS3231SN/M
2 : // Nano Clone (atmega328PB MiniCore board:ATmega328)
3 : // LCD2004 I2C
4 : // DS3231 Shield
5 : // Jumper Wire 8
6 :
7 : #include <DS3232RTC.h>
8 : #include <LiquidCrystal_I2C.h>
9 : LiquidCrystal_I2C lcd(0x27, 20, 04); //0x27 (value of jumper selection)
10 : DS3232RTC myRTC;
11 : const char *week_day[] = {
12 : "NOP", "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
13 : tmElements_t tm;
14 : extern volatile unsigned long timer0_millis;
15 : unsigned long interval = 1000;
16 : int status = 1;
17 :
18 : void setup() {
19 : lcd.init();
20 : lcd.backlight();
21 : lcd.setCursor(0,0);
22 : lcd.print("RealTimeClock v1.0");
23 : myRTC.begin();
24 : //Sync your display to RTC
25 : int sec0, sec1 = 1024;
26 : while(1) {
27 : myRTC.read(tm);
28 : sec0 = int(tm.Second);
29 : if (sec0 - sec1 == 1) break;
30 : sec1 = sec0;
31 : }
32 : // set | adjust time
33 : // Install the Li-battery in the RTC and replace raspberry-pi4's RTC(DS3231)
34 : // $ sudo hwclock -w --local
35 : // remove the RTC from raspberry pi immediately .
36 : }
37 :
38 : void loop() {
39 : if (status == 1){
40 : myRTC.read(tm);
41 : char buff[15];
42 : sprintf(buff, "%d/%02d/%02d %s", tm.Year + 1970,
43 : tm.Month, tm.Day, week_day[tm.Wday]);
44 : lcd.setCursor(0, 1);
45 : lcd.print(buff);
46 : sprintf(buff, "%02d:%02d:%02d", tm.Hour, tm.Minute, tm.Second);
47 : lcd.setCursor(0, 2);
48 : lcd.print(buff);
49 : char buff2[6];
50 : float temp = myRTC.temperature();
51 : temp = temp / 4.0;
52 : dtostrf(temp, 5, 2, buff2);
53 : sprintf(buff, "TEMP = %s \xdf\x43", buff2);
54 : lcd.setCursor(0, 3);
55 : lcd.print(buff);
56 : status = 0;
57 : }
58 :
59 : unsigned long tMillis = millis();
60 :
61 : if (tMillis >= interval) {
62 : status = 1;
63 : noInterrupts ();
64 : timer0_millis = 0;
65 : interrupts ();
66 : }
67 : }
avrdude: 8608 bytes of flash verified
この行数で約 1/4 のプログラム領域を消費してしまいました。この先タイマー時刻(ON / OFF)を入力するためのロータリーエンコーダーやボタンの入力処理、強制 ON / OFF 処理をコーディングするのですが、ちょっと不安になる勢いです。
25 行目からの RTC と LCD の同期ですが、特に重要ではありません。しかし、これがないと、どんなに高精度の RTC を使用したとしても、最大 1 秒の表示ズレを起動時に発生させます。筆者的には、なんだか負けたような気がして、許容できません。とはいえ、LCD の表示更新スピードが遅いので、必ず起動時のタイムラグが生じます。millis() も正確な 1 秒を刻めませんし、世の中にはどうしようもないことがありますね。
動作確認
消費電流 16mA (USB 電圧 5.134 V)