GNSS CLOCK(GPS時計)を作った

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は全部手ハンダ。エアフローを使おうかと思ったけど、クリームはんだを塗るのが結構面倒なので、一つずつ手付けした。

チップ部品などの取外しやハンダ付けに使えるホットエアー(ヒートガン)「JCD 8858」をBanggoodさんから提供を受けたので試してみ...

ソフトウェア

Arduino IDE

MiniCoreを使った。

インストールの手順等はこちらと同様。

Arduino IDEで素のATmega328Pに書き込めるようになったので、今度はATtiny85に書き込めるようにしてみる。この手の情...

クロックが非常に細かく選べる。他のパラメータはデフォルトで。

書込み装置は、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チカ、hello!, world!

当初、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でも良かった。

これだと、明時の上限は変らず、暗時の下限が上がる。明時の上限を上げるにはソフトでは無理で、電流制限抵抗を小さくするしかない。明るい窓際の日中だと見辛いので、もうちょっと明るくしたい気もする。まぁ、とりあえずはこれで。

動作の様子

GNSS clock by JO4EFC

同期が取れるまでに少し時間がかかる。長いと3分くらい。短いとあっという間。一旦同期が取れると、電源を切ってもしばらくはその状態が続くのか、再度電源を投入するとすぐに同期が取れる。

窓際でないと同期しづらい。が、一旦同期が取れたら、窓際から離れても同期が外れることはない。これはJO4EFCさんも書いている通り。

裏に取り付けたGPS受信機のLEDが明るすぎて周りに漏れる。やっぱり、外した方がいいかも。

LEDがときどきチラつく。周囲の明るさが微妙な場合なのかな?

この記事のタイトルとURLをコピーする
スポンサーリンク
スポンサーリンク
スポンサーリンク