インターネット時計の作成 (2)

– 基板の到着、装置の製作 –

【ESP32で電子工作‑2】デジタル時計の作成(1)【プリント基板の作成】 の続編です。まだの方はそちらからどうぞ。


発注基板の到着

前回 JLCPCB にガーバーデータをアップロードして発注をしておいたデジタル時計用基板が届きました。
さっそく開封して、部品実装→動作確認まで進めて行きます!

📦 到着までのタイムライン

前回の記事で発注を行った基板が手元に届くまでの時系列をまとめてみました。

日付 進捗
9/2 ガーバーデータをアップロード
9/3 入金確認
9/4 製造開始
9/6 完成 & 発送 🎉
9/8 手元に到着 (DHL)

発送方法にDHLを選択したというのもありますが、中国→日本でも 1 週間かからず。速さにびっくりです。 正直、2週間ぐらいは早くてもかかると思っていました…

到着した基板をチェックしていきます。

開封の儀

青いおなじみの箱で到着

青いおなじみの箱で到着

中には真空パックされた基板が 5 枚
(パック写真は興奮し過ぎて撮り忘れました…)

開封後の基板

開封後の基板

表裏ともにしっかりと仕上がっています(下記:左=表面、右=裏面)。

PCB表面
基板 表面
PCB裏面
基板 裏面

綺麗な緑色とシルクの印刷。実際に部品をはんだ付けして動かすのが楽しみです。 初めての自作基板なのでシルク・レジストの仕上がりに感動…!


基板への部品実装

基板に部品を実装していきました。回路図は前回の記事に掲載しているのでそちらを見ていただけたらと思います。

前回掲載した回路図を頼りに半田付け。ところが実装前に 設計ミス を発見し大慌てで修正しました。

  • LDO のフットプリントが間違い
  • トランジスタ+プルアップ抵抗を描き忘れ

よくあるミス… で片づけていいかはわかりませんが、部品実装する前に気づいてよかったです。

Twitter でご指摘くださった方、ありがとうございます 🙏
(回路図もこっそり直してあります)

実際に実装した基板がこちらになります。

実装済みPCB表面
実装済み基板 表面
実装済みPCB裏面
実装済み基板 裏面

0603サイズのチップ部品は手はんだだと限界ギリギリ。 今後は作業性を考えて0805サイズに切り替えるのも検討します。

そして、パターンミスの部分も何とかリカバリー(セーフ!!!)

パターンミス修正1
パターンミス修正1
パターンミス修正2
パターンミス修正2

これがいわゆる、違法建築というものですね…

修正が終わったら タカチのプラボックス へ格納。四隅を少し削ってジャストフィット!

ケースに収めた様子

ケースに収めた様子

いざ、箱に収まるといい感じでかっこいいです!!

ぶじ、基板も収まるところに収まったので実際にプログラムを書き込んで動作確認をしていきましょう。


機能追加 & ファームウェア

前回の記事では時計の表示のみを行っていましたが、今回は アラーム機能 を追加。 設定時刻になると

  • ブザー (ESP32 PWM)
  • パトライト (リレー駆動)

が作動して盛大に起こしてくれます。
使用したパトライトはオリジナルマインドの中古品コーナーで発掘したこちら↓

PATLITE WH‑24A‑Y

では、プログラムを書き込んでいきましょう。

スケッチ概要

  1. Wi‑Fi 接続して NTP 同期
  2. RTC (RX8900) に現在時刻を書き込み
  3. I²C I/O エキスパンダで LCD ×6 枚を駆動
  4. ループで RTC から時刻読出し → LCD 更新
  5. アラーム時刻になったらブザー & パトライトを ON、
       スイッチ入力で解除

ソースコード

作成したプログラムは以下のようになります。 ※長いので冒頭のみ、クリックで全文見れます。

#include <WiFi.h>
#include <Wire.h>
#include<time.h>
#include <stdlib.h>
#include <stdio.h>
#include "Adafruit_MCP23017.h"
Adafruit_MCP23017 mcp0;
Adafruit_MCP23017 mcp1;
Adafruit_MCP23017 mcp2;
const int alert = 5;
const int lump = 25;

const int switch_r = 19;
const int switch_w = 18;

char *ssid = "SSID";
char *pass = "PASSWORD";
★クリックして全文コードを表示
#include <WiFi.h>
#include <WiFi.h>
#include <Wire.h>
#include<time.h>
#include <stdlib.h>
#include <stdio.h>
#include "Adafruit_MCP23017.h"
Adafruit_MCP23017 mcp0;
Adafruit_MCP23017 mcp1;
Adafruit_MCP23017 mcp2;
const int alert = 5;
const int lump = 25;

const int switch_r = 19;
const int switch_w = 18;

char *ssid = "SSID";
char *pass = "PASSWORD"

int ihour, imin, isec, i, alert_flag = 0;
int h1, h2, m1, m2, s1, s2;
char hour, minute, sec;
int RegTbl[16];
byte RTC8900 = 0x32;
struct tm timeInfo;//時刻を格納するオブジェクト
char s[20];//文字格納用

int s0_D0_Pin = 0; //データライン0 out
int s0_D1_Pin = 1; //データライン1 out
int s0_D2_Pin = 2; //データライン2 out
int s0_D3_Pin = 3; //データライン3 out
int s0_Bsy_Pin = 4; //BUSY信号 in
int s0_Rst_Pin = 5; //RESET信号 通常LOW out
int s0_Str_Pin = 6; //STROBE信号 out

int s1_D0_Pin = 8; //データライン0 out
int s1_D1_Pin = 9; //データライン1 out
int s1_D2_Pin = 10; //データライン2 out
int s1_D3_Pin = 11; //データライン3 out
int s1_Bsy_Pin = 12; //BUSY信号 in
int s1_Rst_Pin = 13; //RESET信号 通常LOW out
int s1_Str_Pin = 14; //STROBE信号 out

int s2_D0_Pin = 0; //データライン0 out
int s2_D1_Pin = 1; //データライン1 out
int s2_D2_Pin = 2; //データライン2 out
int s2_D3_Pin = 3; //データライン3 out
int s2_Bsy_Pin = 4; //BUSY信号 in
int s2_Rst_Pin = 5; //RESET信号 通常LOW out
int s2_Str_Pin = 6; //STROBE信号 out

int s3_D0_Pin = 8; //データライン0 out
int s3_D1_Pin = 9; //データライン1 out
int s3_D2_Pin = 10; //データライン2 out
int s3_D3_Pin = 11; //データライン3 out
int s3_Bsy_Pin = 12; //BUSY信号 in
int s3_Rst_Pin = 13; //RESET信号 通常LOW out
int s3_Str_Pin = 14; //STROBE信号 out

int s4_D0_Pin = 0; //データライン0 out
int s4_D1_Pin = 1; //データライン1 out
int s4_D2_Pin = 2; //データライン2 out
int s4_D3_Pin = 3; //データライン3 out
int s4_Bsy_Pin = 4; //BUSY信号 in
int s4_Rst_Pin = 5; //RESET信号 通常LOW out
int s4_Str_Pin = 6; //STROBE信号 out

int s5_D0_Pin = 8; //データライン0 out
int s5_D1_Pin = 9; //データライン1 out
int s5_D2_Pin = 10; //データライン2 out
int s5_D3_Pin = 11; //データライン3 out
int s5_Bsy_Pin = 12; //BUSY信号 in
int s5_Rst_Pin = 13; //RESET信号 通常LOW out
int s5_Str_Pin = 14; //STROBE信号 out

//データの定義
int disp_0[8] = {0, 0, 0, 0, 0, 0, 0, 1};
int disp_1[8] = {1, 0, 0, 0, 0, 0, 0, 1};
int disp_2[8] = {0, 1, 0, 0, 0, 0, 0, 1};
int disp_3[8] = {1, 1, 0, 0, 0, 0, 0, 1};
int disp_4[8] = {0, 0, 1, 0, 0, 0, 0, 1};
int disp_5[8] = {1, 0, 1, 0, 0, 0, 0, 1};
int disp_6[8] = {0, 1, 1, 0, 0, 0, 0, 1};
int disp_7[8] = {1, 1, 1, 0, 0, 0, 0, 1};
int disp_8[8] = {0, 0, 0, 0, 1, 0, 0, 1};
int disp_9[8] = {1, 0, 0, 0, 1, 0, 0, 1};
int disp_A[8] = {0, 1, 0, 0, 1, 0, 0, 1};
int disp_B[8] = {1, 1, 0, 0, 1, 0, 0, 1};
int disp_C[8] = {0, 0, 1, 0, 1, 0, 0, 1};
int disp_D[8] = {1, 0, 1, 0, 1, 0, 0, 1};
int disp_E[8] = {0, 1, 1, 0, 1, 0, 0, 1};
int disp_F[8] = {1, 1, 1, 0, 1, 0, 0, 1};

int disp_H[8] = {1, 0, 0, 0, 0, 1, 0, 1};
int disp_I[8] = {0, 1, 0, 0, 0, 1, 0, 1};
int disp_J[8] = {1, 1, 0, 0, 0, 1, 0, 1};
int disp_L[8] = {1, 0, 1, 0, 0, 1, 0, 1};

int disp_O[8] = {0, 0, 0, 0, 1, 1, 0, 1};
int disp_P[8] = {1, 0, 0, 0, 1, 1, 0, 1};
int disp_S[8] = {0, 0, 1, 0, 1, 1, 0, 1};
int disp_U[8] = {0, 1, 1, 0, 1, 1, 0, 1};

int disp_BL[8] = {0, 0, 1, 0, 0, 0, 1, 1};
int disp_RR[8] = {0, 1, 1, 0, 0, 0, 1, 1};
int disp_RL[8] = {1, 1, 1, 0, 0, 0, 1, 1};


// DECIMAL -> BCD
byte dec2bcd( byte data )
{
  return ((( data / 10) << 4) + (data % 10));
}

// BCD -> DECIMAL

byte BCDtoDec(byte data) {
  return ((data >> 4) * 10) + (data & 0x0F) ;
}


void init_pin() {
  //各ピンLowにセット
  mcp0.digitalWrite(s0_D0_Pin, LOW);
  mcp0.digitalWrite(s0_D1_Pin, LOW);
  mcp0.digitalWrite(s0_D2_Pin, LOW);
  mcp0.digitalWrite(s0_D3_Pin, LOW);
  mcp0.digitalWrite(s0_Str_Pin, LOW);
  mcp0.digitalWrite(s0_Rst_Pin, LOW);
  mcp0.digitalWrite(s1_D0_Pin, LOW);
  mcp0.digitalWrite(s1_D1_Pin, LOW);
  mcp0.digitalWrite(s1_D2_Pin, LOW);
  mcp0.digitalWrite(s1_D3_Pin, LOW);
  mcp0.digitalWrite(s1_Str_Pin, LOW);
  mcp0.digitalWrite(s1_Rst_Pin, LOW);
  delay(100);
  mcp1.digitalWrite(s2_D0_Pin, LOW);
  mcp1.digitalWrite(s2_D1_Pin, LOW);
  mcp1.digitalWrite(s2_D2_Pin, LOW);
  mcp1.digitalWrite(s2_D3_Pin, LOW);
  mcp1.digitalWrite(s2_Str_Pin, LOW);
  mcp1.digitalWrite(s2_Rst_Pin, LOW);
  mcp1.digitalWrite(s3_D0_Pin, LOW);
  mcp1.digitalWrite(s3_D1_Pin, LOW);
  mcp1.digitalWrite(s3_D2_Pin, LOW);
  mcp1.digitalWrite(s3_D3_Pin, LOW);
  mcp1.digitalWrite(s3_Str_Pin, LOW);
  mcp1.digitalWrite(s3_Rst_Pin, LOW);
  delay(100);
  mcp2.digitalWrite(s4_D0_Pin, LOW);
  mcp2.digitalWrite(s4_D1_Pin, LOW);
  mcp2.digitalWrite(s4_D2_Pin, LOW);
  mcp2.digitalWrite(s4_D3_Pin, LOW);
  mcp2.digitalWrite(s4_Str_Pin, LOW);
  mcp2.digitalWrite(s4_Rst_Pin, LOW);
  mcp2.digitalWrite(s5_D0_Pin, LOW);
  mcp2.digitalWrite(s5_D1_Pin, LOW);
  mcp2.digitalWrite(s5_D2_Pin, LOW);
  mcp2.digitalWrite(s5_D3_Pin, LOW);
  mcp2.digitalWrite(s5_Str_Pin, LOW);
  mcp2.digitalWrite(s5_Rst_Pin, LOW);
  delay(100);
  //リセットかける
  mcp0.digitalWrite(s0_Rst_Pin, HIGH);
  mcp0.digitalWrite(s1_Rst_Pin, HIGH);
  delay(100);
  mcp1.digitalWrite(s2_Rst_Pin, HIGH);
  mcp1.digitalWrite(s3_Rst_Pin, HIGH);
  delay(100);
  mcp2.digitalWrite(s4_Rst_Pin, HIGH);
  mcp2.digitalWrite(s5_Rst_Pin, HIGH);
  delay(1000);
  mcp0.digitalWrite(s0_Rst_Pin, LOW);
  mcp0.digitalWrite(s1_Rst_Pin, LOW);
  delay(100);
  mcp1.digitalWrite(s2_Rst_Pin, LOW);
  mcp1.digitalWrite(s3_Rst_Pin, LOW);
  delay(100);
  mcp2.digitalWrite(s4_Rst_Pin, LOW);
  mcp2.digitalWrite(s5_Rst_Pin, LOW);
  delay(1000);
}


void write_display0(int disp_data) {
  int i;
  int val = 0;
  int data[8];

  switch (disp_data) {
    case 0:    memcpy(data, disp_0, sizeof(int) * 8);    break;
    case 1:    memcpy(data, disp_1, sizeof(int) * 8);    break;
    case 2:    memcpy(data, disp_2, sizeof(int) * 8);    break;
    case 3:    memcpy(data, disp_3, sizeof(int) * 8);    break;
    case 4:    memcpy(data, disp_4, sizeof(int) * 8);    break;
    case 5:    memcpy(data, disp_5, sizeof(int) * 8);    break;
    case 6:    memcpy(data, disp_6, sizeof(int) * 8);    break;
    case 7:    memcpy(data, disp_7, sizeof(int) * 8);    break;
    case 8:    memcpy(data, disp_8, sizeof(int) * 8);    break;
    case 9:    memcpy(data, disp_9, sizeof(int) * 8);    break;
  }

  while (mcp0.digitalRead(s0_Bsy_Pin) != LOW)
    continue;
  //LOWDATA書き込み
  mcp0.digitalWrite(s0_D0_Pin, data[0]);
  mcp0.digitalWrite(s0_D1_Pin, data[1]);
  mcp0.digitalWrite(s0_D2_Pin, data[2]);
  mcp0.digitalWrite(s0_D3_Pin, data[3]);
  mcp0.digitalWrite(s0_Str_Pin, HIGH);
  while (mcp0.digitalRead(s0_Bsy_Pin) != HIGH)
    continue;
  mcp0.digitalWrite(s0_Str_Pin, LOW);
  while (mcp0.digitalRead(s0_Bsy_Pin) != LOW)
    continue;
  mcp0.digitalWrite(s0_D0_Pin, data[4]);
  mcp0.digitalWrite(s0_D1_Pin, data[5]);
  mcp0.digitalWrite(s0_D2_Pin, data[6]);
  mcp0.digitalWrite(s0_D3_Pin, data[7]);
  delay(10);
  mcp0.digitalWrite(s0_Str_Pin, HIGH);
  while (mcp0.digitalRead(s0_Bsy_Pin) != HIGH)
    continue;
  mcp0.digitalWrite(s0_Str_Pin, LOW);

}

void write_display1(int disp_data) {
  int i;
  int val = 0;
  int data[8];

  switch (disp_data) {
    case 0:    memcpy(data, disp_0, sizeof(int) * 8);    break;
    case 1:    memcpy(data, disp_1, sizeof(int) * 8);    break;
    case 2:    memcpy(data, disp_2, sizeof(int) * 8);    break;
    case 3:    memcpy(data, disp_3, sizeof(int) * 8);    break;
    case 4:    memcpy(data, disp_4, sizeof(int) * 8);    break;
    case 5:    memcpy(data, disp_5, sizeof(int) * 8);    break;
    case 6:    memcpy(data, disp_6, sizeof(int) * 8);    break;
    case 7:    memcpy(data, disp_7, sizeof(int) * 8);    break;
    case 8:    memcpy(data, disp_8, sizeof(int) * 8);    break;
    case 9:    memcpy(data, disp_9, sizeof(int) * 8);    break;
  }

  while (mcp0.digitalRead(s1_Bsy_Pin) != LOW)
    continue;
  mcp0.digitalWrite(s1_D0_Pin, data[0]);
  mcp0.digitalWrite(s1_D1_Pin, data[1]);
  mcp0.digitalWrite(s1_D2_Pin, data[2]);
  mcp0.digitalWrite(s1_D3_Pin, data[3]);
  mcp0.digitalWrite(s1_Str_Pin, HIGH);
  while (mcp0.digitalRead(s1_Bsy_Pin) != HIGH)
    continue;
  mcp0.digitalWrite(s1_Str_Pin, LOW);
  while (mcp0.digitalRead(s1_Bsy_Pin) != LOW)
    continue;
  mcp0.digitalWrite(s1_D0_Pin, data[4]);
  mcp0.digitalWrite(s1_D1_Pin, data[5]);
  mcp0.digitalWrite(s1_D2_Pin, data[6]);
  mcp0.digitalWrite(s1_D3_Pin, data[7]);
  delay(10);

  mcp0.digitalWrite(s1_Str_Pin, HIGH);
  while (mcp0.digitalRead(s1_Bsy_Pin) != HIGH)
    continue;
  mcp0.digitalWrite(s1_Str_Pin, LOW);
}



void write_display2(int disp_data) {
  int i;
  int val = 0;
  int data[8];
  switch (disp_data) {
    case 0:    memcpy(data, disp_0, sizeof(int) * 8);    break;
    case 1:    memcpy(data, disp_1, sizeof(int) * 8);    break;
    case 2:    memcpy(data, disp_2, sizeof(int) * 8);    break;
    case 3:    memcpy(data, disp_3, sizeof(int) * 8);    break;
    case 4:    memcpy(data, disp_4, sizeof(int) * 8);    break;
    case 5:    memcpy(data, disp_5, sizeof(int) * 8);    break;
    case 6:    memcpy(data, disp_6, sizeof(int) * 8);    break;
    case 7:    memcpy(data, disp_7, sizeof(int) * 8);    break;
    case 8:    memcpy(data, disp_8, sizeof(int) * 8);    break;
    case 9:    memcpy(data, disp_9, sizeof(int) * 8);    break;
  }
  while (mcp1.digitalRead(s2_Bsy_Pin) != LOW)
    continue;
  //LOWDATA書き込み

  mcp1.digitalWrite(s2_D0_Pin, data[0]);
  mcp1.digitalWrite(s2_D1_Pin, data[1]);
  mcp1.digitalWrite(s2_D2_Pin, data[2]);
  mcp1.digitalWrite(s2_D3_Pin, data[3]);
  mcp1.digitalWrite(s2_Str_Pin, HIGH);
  while (mcp1.digitalRead(s2_Bsy_Pin) != HIGH)
    continue;
  mcp1.digitalWrite(s2_Str_Pin, LOW);
  while (mcp1.digitalRead(s2_Bsy_Pin) != LOW)
    continue;
  mcp1.digitalWrite(s2_D0_Pin, data[4]);
  mcp1.digitalWrite(s2_D1_Pin, data[5]);
  mcp1.digitalWrite(s2_D2_Pin, data[6]);
  mcp1.digitalWrite(s2_D3_Pin, data[7]);
  delay(10);
  mcp1.digitalWrite(s2_Str_Pin, HIGH);
  while (mcp1.digitalRead(s2_Bsy_Pin) != HIGH)
    continue;
  mcp1.digitalWrite(s2_Str_Pin, LOW);

}

void write_display3(int disp_data) {
  int i;
  int val = 0;
  int data[8];

  switch (disp_data) {
    case 0:    memcpy(data, disp_0, sizeof(int) * 8);    break;
    case 1:    memcpy(data, disp_1, sizeof(int) * 8);    break;
    case 2:    memcpy(data, disp_2, sizeof(int) * 8);    break;
    case 3:    memcpy(data, disp_3, sizeof(int) * 8);    break;
    case 4:    memcpy(data, disp_4, sizeof(int) * 8);    break;
    case 5:    memcpy(data, disp_5, sizeof(int) * 8);    break;
    case 6:    memcpy(data, disp_6, sizeof(int) * 8);    break;
    case 7:    memcpy(data, disp_7, sizeof(int) * 8);    break;
    case 8:    memcpy(data, disp_8, sizeof(int) * 8);    break;
    case 9:    memcpy(data, disp_9, sizeof(int) * 8);    break;
  }

  while (mcp1.digitalRead(s3_Bsy_Pin) != LOW)
    continue;
  mcp1.digitalWrite(s3_D0_Pin, data[0]);
  mcp1.digitalWrite(s3_D1_Pin, data[1]);
  mcp1.digitalWrite(s3_D2_Pin, data[2]);
  mcp1.digitalWrite(s3_D3_Pin, data[3]);
  mcp1.digitalWrite(s3_Str_Pin, HIGH);

  while (mcp1.digitalRead(s3_Bsy_Pin) != HIGH)
    continue;
  mcp1.digitalWrite(s3_Str_Pin, LOW);
  while (mcp1.digitalRead(s3_Bsy_Pin) != LOW)
    continue;
  mcp1.digitalWrite(s3_D0_Pin, data[4]);
  mcp1.digitalWrite(s3_D1_Pin, data[5]);
  mcp1.digitalWrite(s3_D2_Pin, data[6]);
  mcp1.digitalWrite(s3_D3_Pin, data[7]);
  delay(10);

  mcp1.digitalWrite(s3_Str_Pin, HIGH);
  while (mcp1.digitalRead(s3_Bsy_Pin) != HIGH)
    continue;
  mcp1.digitalWrite(s3_Str_Pin, LOW);

}



void write_display4(int disp_data) {
  int i;
  int val = 0;
  int data[8];

  switch (disp_data) {
    case 0:    memcpy(data, disp_0, sizeof(int) * 8);    break;
    case 1:    memcpy(data, disp_1, sizeof(int) * 8);    break;
    case 2:    memcpy(data, disp_2, sizeof(int) * 8);    break;
    case 3:    memcpy(data, disp_3, sizeof(int) * 8);    break;
    case 4:    memcpy(data, disp_4, sizeof(int) * 8);    break;
    case 5:    memcpy(data, disp_5, sizeof(int) * 8);    break;
    case 6:    memcpy(data, disp_6, sizeof(int) * 8);    break;
    case 7:    memcpy(data, disp_7, sizeof(int) * 8);    break;
    case 8:    memcpy(data, disp_8, sizeof(int) * 8);    break;
    case 9:    memcpy(data, disp_9, sizeof(int) * 8);    break;
  }

  while (mcp2.digitalRead(s4_Bsy_Pin) != LOW)
    continue;
  //LOWDATA書き込み
  mcp2.digitalWrite(s4_D0_Pin, data[0]);
  mcp2.digitalWrite(s4_D1_Pin, data[1]);
  mcp2.digitalWrite(s4_D2_Pin, data[2]);
  mcp2.digitalWrite(s4_D3_Pin, data[3]);
  mcp2.digitalWrite(s4_Str_Pin, HIGH);
  while (mcp2.digitalRead(s4_Bsy_Pin) != HIGH)
    continue;
  mcp2.digitalWrite(s4_Str_Pin, LOW);
  while (mcp2.digitalRead(s4_Bsy_Pin) != LOW)
    continue;
  mcp2.digitalWrite(s4_D0_Pin, data[4]);
  mcp2.digitalWrite(s4_D1_Pin, data[5]);
  mcp2.digitalWrite(s4_D2_Pin, data[6]);
  mcp2.digitalWrite(s4_D3_Pin, data[7]);
  delay(10);
  mcp2.digitalWrite(s4_Str_Pin, HIGH);
  while (mcp2.digitalRead(s4_Bsy_Pin) != HIGH)
    continue;
  mcp2.digitalWrite(s4_Str_Pin, LOW);
}

void write_display5(int disp_data) {
  int i;
  int val = 0;
  int data[8];

  switch (disp_data) {
    case 0:    memcpy(data, disp_0, sizeof(int) * 8);    break;
    case 1:    memcpy(data, disp_1, sizeof(int) * 8);    break;
    case 2:    memcpy(data, disp_2, sizeof(int) * 8);    break;
    case 3:    memcpy(data, disp_3, sizeof(int) * 8);    break;
    case 4:    memcpy(data, disp_4, sizeof(int) * 8);    break;
    case 5:    memcpy(data, disp_5, sizeof(int) * 8);    break;
    case 6:    memcpy(data, disp_6, sizeof(int) * 8);    break;
    case 7:    memcpy(data, disp_7, sizeof(int) * 8);    break;
    case 8:    memcpy(data, disp_8, sizeof(int) * 8);    break;
    case 9:    memcpy(data, disp_9, sizeof(int) * 8);    break;
  }

  while (mcp2.digitalRead(s5_Bsy_Pin) != LOW)
    continue;
  mcp2.digitalWrite(s5_D0_Pin, data[0]);
  mcp2.digitalWrite(s5_D1_Pin, data[1]);
  mcp2.digitalWrite(s5_D2_Pin, data[2]);
  mcp2.digitalWrite(s5_D3_Pin, data[3]);
  mcp2.digitalWrite(s5_Str_Pin, HIGH);
  while (mcp2.digitalRead(s5_Bsy_Pin) != HIGH)
    continue;
  mcp2.digitalWrite(s5_Str_Pin, LOW);
  while (mcp2.digitalRead(s5_Bsy_Pin) != LOW)
    continue;
  mcp2.digitalWrite(s5_D0_Pin, data[4]);
  mcp2.digitalWrite(s5_D1_Pin, data[5]);
  mcp2.digitalWrite(s5_D2_Pin, data[6]);
  mcp2.digitalWrite(s5_D3_Pin, data[7]);
  delay(10);

  mcp2.digitalWrite(s5_Str_Pin, HIGH);
  while (mcp2.digitalRead(s5_Bsy_Pin) != HIGH)
    continue;
  mcp2.digitalWrite(s5_Str_Pin, LOW);

}

void setup() {
  // initialize the digital pin as an output.
  delay(1000);
  Serial.begin(115200);
  Wire.begin();
  pinMode(lump, OUTPUT);
  pinMode(switch_w, OUTPUT);
  pinMode(switch_r, INPUT);
  gpio_set_pull_mode(GPIO_NUM_19, GPIO_PULLDOWN_ONLY);

  ledcSetup(0, 1000, 8);
  ledcAttachPin(alert, 0);

  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  if (WiFi.begin(ssid, pass) != WL_DISCONNECTED) {
    ESP.restart();
  }
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
  }
  Serial.println("Connected to the WiFi network!");
  delay(1000);
  configTime(9 * 3600L, 0, "ntp.nict.jp", "time.google.com", "ntp.jst.mfeed.ad.jp");//NTPの設定
  getLocalTime(&timeInfo);//tmオブジェクトのtimeInfoに現在時刻を入れ込む
  delay(1);
  ihour = timeInfo.tm_hour;
  imin = timeInfo.tm_min;
  isec = timeInfo.tm_sec;
  sprintf(s, " %04d/%02d/%02d %02d:%02d:%02d",
          timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday,
          timeInfo.tm_hour, timeInfo.tm_min, timeInfo.tm_sec);//人間が読める形式に変換
  Serial.println(s);//時間をシリアルモニタへ出力

  mcp0.begin();
  mcp1.begin(0x04);
  mcp2.begin(0x06);

  mcp0.pinMode(s0_D0_Pin, OUTPUT);
  mcp0.pinMode(s0_D1_Pin, OUTPUT);
  mcp0.pinMode(s0_D2_Pin, OUTPUT);
  mcp0.pinMode(s0_D3_Pin, OUTPUT);
  mcp0.pinMode(s0_Bsy_Pin, INPUT);
  mcp0.pinMode(s0_Str_Pin, OUTPUT);
  mcp0.pinMode(s0_Rst_Pin, OUTPUT);

  mcp0.pinMode(s1_D0_Pin, OUTPUT);
  mcp0.pinMode(s1_D1_Pin, OUTPUT);
  mcp0.pinMode(s1_D2_Pin, OUTPUT);
  mcp0.pinMode(s1_D3_Pin, OUTPUT);
  mcp0.pinMode(s1_Bsy_Pin, INPUT);
  mcp0.pinMode(s1_Str_Pin, OUTPUT);
  mcp0.pinMode(s1_Rst_Pin, OUTPUT);

  mcp1.pinMode(s2_D0_Pin, OUTPUT);
  mcp1.pinMode(s2_D1_Pin, OUTPUT);
  mcp1.pinMode(s2_D2_Pin, OUTPUT);
  mcp1.pinMode(s2_D3_Pin, OUTPUT);
  mcp1.pinMode(s2_Bsy_Pin, INPUT);
  mcp1.pinMode(s2_Str_Pin, OUTPUT);
  mcp1.pinMode(s2_Rst_Pin, OUTPUT);

  mcp1.pinMode(s3_D0_Pin, OUTPUT);
  mcp1.pinMode(s3_D1_Pin, OUTPUT);
  mcp1.pinMode(s3_D2_Pin, OUTPUT);
  mcp1.pinMode(s3_D3_Pin, OUTPUT);
  mcp1.pinMode(s3_Bsy_Pin, INPUT);
  mcp1.pinMode(s3_Str_Pin, OUTPUT);
  mcp1.pinMode(s3_Rst_Pin, OUTPUT);

  mcp2.pinMode(s4_D0_Pin, OUTPUT);
  mcp2.pinMode(s4_D1_Pin, OUTPUT);
  mcp2.pinMode(s4_D2_Pin, OUTPUT);
  mcp2.pinMode(s4_D3_Pin, OUTPUT);
  mcp2.pinMode(s4_Bsy_Pin, INPUT);
  mcp2.pinMode(s4_Str_Pin, OUTPUT);
  mcp2.pinMode(s4_Rst_Pin, OUTPUT);

  mcp2.pinMode(s5_D0_Pin, OUTPUT);
  mcp2.pinMode(s5_D1_Pin, OUTPUT);
  mcp2.pinMode(s5_D2_Pin, OUTPUT);
  mcp2.pinMode(s5_D3_Pin, OUTPUT);
  mcp2.pinMode(s5_Bsy_Pin, INPUT);
  mcp2.pinMode(s5_Str_Pin, OUTPUT);
  mcp2.pinMode(s5_Rst_Pin, OUTPUT);

  init_pin();


  Wire.beginTransmission(RTC8900);
  Wire.write(0x00);
  Wire.write(byte(dec2bcd(isec)));// [02]Seconds(15秒)
  Wire.write(byte(dec2bcd(imin))); // [03]Minutes(20分)
  Wire.write(byte(dec2bcd(ihour)));// [04]Hours(12時)
  Wire.endTransmission();
  Wire.beginTransmission(RTC8900);
  Wire.write(0x00);
  Wire.endTransmission();
  Wire.requestFrom(RTC8900, 16);
  for (i = 0; i < 16; i++) {
    while (Wire.available() == 0 ) {}
    RegTbl[i] = Wire.read();
  }
  ihour = (BCDtoDec(RegTbl[2] & 0x3F));
  imin = (BCDtoDec(RegTbl[1] & 0x7F));
  isec = (BCDtoDec(RegTbl[0] & 0x7F));
  WiFi.disconnect();
}

// the loop routine runs over and over again forever:
void loop() {
  //アラームの設定
  if (ihour == 7 && imin = 0 && isec == 0) {
    alert_flag = 1;
    digitalWrite(lump, HIGH);
    digitalWrite(switch_w, HIGH);
    ledcWrite(0, 127);
  }
  if (alert_flag == 1 && digitalRead(switch_r) == 1) {
    alert_flag = 0;
    digitalWrite(lump, LOW);
    digitalWrite(switch_w, LOW);
    ledcWrite(0, 0);
  }
  Serial.println("LOOP");
  Wire.beginTransmission(RTC8900);
  Wire.write(0x00);
  Wire.endTransmission();
  Wire.requestFrom(RTC8900, 16);
  for (i = 0; i < 16; i++) {
    while (Wire.available() == 0 ) {}
    RegTbl[i] = Wire.read();
  }

  ihour = (BCDtoDec(RegTbl[2] & 0x3F));
  imin = (BCDtoDec(RegTbl[1] & 0x7F));
  isec = (BCDtoDec(RegTbl[0] & 0x7F));
  h1 = ihour / 10;
  h2 = ihour % 10;
  m1 = imin / 10;
  m2 = imin % 10;
  s1 = isec / 10;
  s2 = isec % 10;

  //LCDの表示
  write_display0(h1);
  write_display1(h2);
  write_display2(m2);
  write_display3(m1);
  write_display4(s2);
  write_display5(s1);

  delay(50);
}

相変わらず、長々と書いていますが参考になれば幸いです。

動作テスト

壁に掛けてみた様子。配線はまだ雑ですが、前回のユニバーサル基板 ver. と比べると雲泥の差でスッキリ✨

壁掛け設置

壁掛け設置

動作動画はこちら↓

時計もアラームも想定通りに動かすことができましたね。 これで、寝坊もしないし、朝は緊急感のある起床ができると思います!!


今後の展望

  • ケーブルを多芯でまとめてさらに美しく
  • アラーム/時刻設定を ブラウザ UI → 将来はクラウド連携へ
  • センサ値の表示やスマートリモコン化など、
      温湿度センサーや赤外線送受信モジュールを組み合わせて、スマートホーム連携にも対応させたい。

プリント基板を作れるようになると電子工作の世界が一気に広がりますね。
それでは Good Hack Life!

See You …