JO4EFC氏から基板を分けてもらったGNSS CLOCK(GPS時計、高精度温度計付き)。
なかなか手が回らず、放置状態にしてしまっていたが、ようやく作った。
なんとなく、「クイズタイムショック」を思い出させてくれる。
ハードウェア
変更部品
基本的には、オリジナルのまま。手持ち部品の都合で少しだけ変えたので、そのメモ。
- レギュレータの保護ダイオード。
チップ品を持っていないので、リード部品で。チップ用のランドに付けるのは大変なのでレギュレータに直接付けたが、黒いので目立たずに済んでいる。念のためショットキーバリアで。
基板が黒いので、フラックスを拭き取るのに使ったティッシュペーパーの繊維の残りが目立つ…。
- C5
C5の22μFは、手持ち部品の都合で10μFを二つ。C5のランドに二段か重ねにしようかと思ったが、隣のR19のランドにもう一つの10μFを取り付け、その上に100kΩを乗せた。
焦点がやや後ろになっている…。拡大するとハンダ付けのあらが色々見える…。
肝心の動作を見てみると、10μFでも良かったかも。ここは、周囲の明るさに応じてLED等の明るさを調整するための検出部で、暗くなったときにLEDなどの照度をゆっくり落としていくためのもののよう。22μFを10μFにしたら、ジワーーーーーーっと暗くなるのが、ジワーーっと暗くなるくらいの違いじゃなかいかな?
- GPS受信機
オリジナルでは延長ケーブル付きのものが使われているけれど、時計本体の裏に取り付けることを想定して下の写真のものを採用。
AliExpressで見つけた安いもの。確証はなかったけど、なんとなく良さそうなものを見繕って入手。
端子が一つ多い。enable端子みたい。販売ページでは、High、Floating、Lowでの説明が書かれていたけれど、イマイチ理解できず。とりあえず、フローティング(未配線)で試したら動いた。
LEDがものすごく眩しい。「暗くできないか?」と販売元に問い合わせてみたら「外せ」という回答。いや、外したいわけじゃないんだけど…。まぁ、そういう機構はないんだろうな。LEDの側に抵抗があれば変えてみるところだけど、残念ながらそういうものはない。
それから、これは結構発熱する。ほんのり温かい程度ではあるが、温度センサには影響しそう。なので、できるだけ離れた場所に取り付けた。
組立て
温度センサは指示通り少々浮かせた。ハンダ付け前に足をちょっと曲げて下に空間ができるように。
LEDは全部手ハンダ。エアフローを使おうかと思ったけど、クリームはんだを塗るのが結構面倒なので、一つずつ手付けした。
ソフトウェア
Arduino IDE
MiniCoreを使った。
インストールの手順等はこちらと同様。
クロックが非常に細かく選べる。他のパラメータはデフォルトで。
書込み装置は、USBasp。
ポイントは、最初に一度「ブートローダを書き込む」を行うこと。これでフューズビットが「外部クロック、分周なし」に設定される(みたい)。Arduinoのブートローダの設定がそうなので、これを利用する(単にフューズビットの設定のために使う)。この後で「書込み装置を使って書き込む」を行うと、Arduinoブートローダの領域は上書きされて潰れる。もしくは、avrdude等でフューズビットの書き込みを行っても良いのだけど、「ブートローダを書き込む」はArduino IDEで行えるので、これが楽。
Lチカ、hello, world!
まずは、最初の一歩。GPSのステータスLEDとLCDを使って「Lチカ」と「hello, world!」。
#define BACK_LIGHT 3
#define LED1 5
#define LED2 6
#define WAIT_TIME 500
#include <Wire.h>
#include <I2CLiquidCrystal.h>
I2CLiquidCrystal lcd(40, (bool)false); //true = 5V, false = 3.3V
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(BACK_LIGHT, OUTPUT);
digitalWrite(LED1, HIGH);
digitalWrite(LED2, HIGH);
digitalWrite(BACK_LIGHT, HIGH);
lcd.begin(16, 2);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("hello, world!");
}
void loop() {
static int i = 0;
digitalWrite(LED_BUILTIN, HIGH);
digitalWrite(LED1, HIGH);
digitalWrite(LED2, LOW);
digitalWrite(BACK_LIGHT, HIGH);
delay(WAIT_TIME);
digitalWrite(LED_BUILTIN, LOW);
digitalWrite(LED1, LOW);
digitalWrite(LED2, HIGH);
digitalWrite(BACK_LIGHT, LOW);
delay(WAIT_TIME);
lcd.setCursor(0, 1);
lcd.print(i++);
}
当初、Lチカはできるけれど、LCDへの表示ができなかった。原因がどうにもわからず、もしかしたらLCD用のライブラリが違うのかと思い、JO4EFCさんに問い合わせ。しかし、私が使っているもので間違いないとのこと。
となると、問題はハードウェア。I2Cの信号をオシロで見てみたら、「lcd.begin(16, 2);」を行ったととたんに約100kHz位の矩形波が出っぱなし。SCKもSDAも同じ(位相も同じ)。I2CのホストはATmega328Pなので、おかしいのはこれ。LチカができてI2Cだけが壊れるなどという不思議な壊れ方をするわけもなく、とりあえずATmega328Pにハンダゴテを当て直したら動いてくれた。目視では良さそうだったんだけど、ハンダ不良だったようだ。
ソースコード
では、いよいよ本番のソフト。これも基本的には開発者のブログで公開されているものそのまま。
しかしながら、使用したLEDがやや暗かったので、下駄を履かせるように改造(緑だけは充分明るかったので下駄はなし)。また、LCDのバックパネルももう少し明るい方がいいかなと思ったので、LEDと同じ下駄を採用。
LCDのコントラストも色々いじってみたけど、結局はオリジナルとほぼ同じ(40→45、見た目は変らず。40に戻してもよいのだけど、面倒なのでそのまま)。
コードの差分は以下の通り。
--- gnssclock.ino.orig 2021-03-06 23:45:28.349854748 +0900
+++ gnssclock.ino 2021-03-06 23:51:32.739795214 +0900
@@ -4,12 +4,15 @@
#include <TimeLib.h>
TinyGPSPlus gps;
-I2CLiquidCrystal lcd(40, (bool)false); //true = 5V, false = 3.3V
+//I2CLiquidCrystal lcd(40, (bool)false); //true = 5V, false = 3.3V
+I2CLiquidCrystal lcd(45, (bool)false); //true = 5V, false = 3.3V
+
unsigned long t = 0;
unsigned long t2 = 0;
byte day_old = 0;
byte hourPin;
byte duty = 255;
+byte duty2 = 255;
bool GPSstatus = 0;
bool GPSstatusB4 = 0;
bool tempSet = 0;
@@ -105,7 +108,8 @@
digitalWrite(9, 0);
digitalWrite(10, 0);
}
- analogWrite(hourPin, duty);
+ //analogWrite(hourPin, duty);
+ analogWrite(hourPin, duty2);
if (h < 3) {
pinMode(2, INPUT);
@@ -238,14 +242,25 @@
else {
lumi = analogRead(6);
}
+
if (lumi > 15) {
duty = lumi / 4;
}
else {
duty = 4;
}
- analogWrite(3, duty); //LCD backlight illuminance adjustment (0-255)
- analogWrite(hourPin, duty); //hour LED illuminance adjustment (0-255)
+
+ {
+ float duty2_tmp;
+
+ duty2_tmp = (float)duty * 8.0;
+ duty2 = (byte)((duty2_tmp > 255) ? 255 : duty2_tmp);
+ }
+
+ //analogWrite(3, duty); //LCD backlight illuminance adjustment (0-255)
+ analogWrite(3, duty2); //LCD backlight illuminance adjustment (0-255)
+ //analogWrite(hourPin, duty); //hour LED illuminance adjustment (0-255)
+ analogWrite(hourPin, duty2); //hour LED illuminance adjustment (0-255)
Wire.beginTransmission(HT16K33);
Wire.write(0b11100000 | lumi / 64); //minute and second LED illuminance adjustment (0-15)
Wire.endTransmission();
@@ -404,7 +419,8 @@
LED_hour(0);
getTemp();
setLuminance();
- analogWrite(5, duty); //status LED
+ // analogWrite(5, duty); //status LED
+ analogWrite(5, duty2); //status LED
}
LED_clear();
@@ -431,7 +447,8 @@
}
getTemp();
setLuminance();
- analogWrite(5, duty); //status LED
+ // analogWrite(5, duty); //status LED
+ analogWrite(5, duty2); //status LED
delay(25);
}
}
@@ -454,7 +471,8 @@
}
else {
GPSstatus = 0;
- analogWrite(5, duty);
+ // analogWrite(5, duty);
+ analogWrite(5, duty2);
digitalWrite(6, LOW);
}
明るさ調整は、見ての通り、元のdutyに対して下駄を履かせたものがduty2。dutyを8倍し、かつ、255の上限を付けた。当初は、1.2倍とかで試したのでfloatで計算しているけれど、実際に試してみると小数点以下は効かない(違いがわからない)のでintでも良かった。
これだと、明時の上限は変らず、暗時の下限が上がる。明時の上限を上げるにはソフトでは無理で、電流制限抵抗を小さくするしかない。明るい窓際の日中だと見辛いので、もうちょっと明るくしたい気もする。まぁ、とりあえずはこれで。
動作の様子
同期が取れるまでに少し時間がかかる。長いと3分くらい。短いとあっという間。一旦同期が取れると、電源を切ってもしばらくはその状態が続くのか、再度電源を投入するとすぐに同期が取れる。
窓際でないと同期しづらい。が、一旦同期が取れたら、窓際から離れても同期が外れることはない。これはJO4EFCさんも書いている通り。
裏に取り付けたGPS受信機のLEDが明るすぎて周りに漏れる。やっぱり、外した方がいいかも。
LEDがときどきチラつく。周囲の明るさが微妙な場合なのかな?
コメント