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がときどきチラつく。周囲の明るさが微妙な場合なのかな?







コメント