Arduino ESP32

【ESP32で電子工作-2】デジタル時計の作成(1)【プリント基板の作成】

インターネット時計の作成(1)
-回路作成から基板発注-

この記事は<JLCPCB>様の提供で執筆しています。

時計を表示させるための回路とプログラミング

今回は自宅に置ける、デジタル時計を作成していきます。
目標は
・ネットワークに接続して時刻の自動調整を行いつつ、平時はRTCを使ってのタイムカウントを行うような回路
・壁にかけれて、目視しやすいような時計

を目指して作っていきます。

 準備するもの

今回、時計を作るために準備した材料は以下になります。

部品銘 個数 購入先 URL
LCD
表示ユニット
TZ-250A
6 ORIGINAL MIND https://www.originalmind.co.jp/useds/38871
ESP32-WROVER DevKitC 1 秋月電子
Amazon
https://akizukidenshi.com/catalog/g/gM-15674/
https://amzn.to/3ksv8Hy
RTCモジュール
RTC-8564NB
1 秋月電子 https://akizukidenshi.com/catalog/g/gI-00233/
I2C I/Oエキスパンダー
MCP23017
3 秋月電子 https://akizukidenshi.com/catalog/g/gI-09486/
ユニバーサル基板 Cタイプ 2 秋月電子 https://akizukidenshi.com/catalog/g/gP-03229/
配線材 大量

こんな感じの材料と家にある、こまごました材料で作成しました。

LCD表示ユニットをオリジナルマインドで見つけて、勢いで購入してから何かに使いたいなーってずっと思っていて、今回の時計作成を思いつきました。
こんなLCDパネル見つけたら使ってみたくなっちゃいますね♪

回路図の設計と回路の作成

今回作成した回路図は以下のようになります。

電源はDevKitCのUSBより給電しています。
LCD表示ユニットを6枚も使用するので、ESP32では足の数が足りません。
そのため、I2C対応のI/Oエキスパンダーを使って、一つのマイコンで複数のLCDパネルを操作できるようにしています。
そして実際に作成した回路が以下のようになっています。


回路を2枚作製して重ねるようにして使います。

配線間違えて、ジャンパとかしちゃって、ぐちゃぐちゃで何とも言えない出来ですね(笑)

プログラムの作成と動作

時計を駆動させるためのプログラムを書いていきましょう。
プログラムはArduinoIDEを使用しています。
ESP32を使用して書き込む設定は「【ESP32で電子工作-1】ESP32の入出力ポートを使用してLED点滅【Lチカ】を読んでいただければわかると思います。

プログラムの流れとしては、

  1. ライブラリの読み込み、変数設定
  2. シリアル、I2C、WIFIの設定
    今回は自宅インターネットにつながってるWIFIルーターに接続しています。
  3. インターネットより現在時刻を取得
    取得した時間をRTCに書き込み
  4. I/Oエキスパンダーの設定、LCDの初期化
  5. ループ関数
    RTCより随時時間を取得してLCDに出力

簡単にザクっと説明するとこのようなプログラムを作成しました。
作成したプログラムは以下のようになります。

#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;
char *ssid = "SSID";
char *pass = "PASSWORD";

int ihour, imin, isec, i;
int h1, h2, m1, m2, s1, s2;
char hour, minute, sec;
int RegTbl[16];
byte RTC8564 = 0x51;
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.
  Serial.begin(115200);
  Wire.begin();

  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);//時間をシリアルモニタへ出力




  Wire.beginTransmission(RTC8564);
  Wire.write(0x00);
  Wire.write(0x00);// [00]Control1
  Wire.write(0x02);// [01]Control2
  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.write(0x25);// [05]Days(25日)
  Wire.write(0x01);    // [06]Weekdays(月)
  Wire.write(0x12 | 0x80); // [07]Month/Century(21世紀の12月)
  Wire.write(0x17);// [08]Years(2017年)
  Wire.endTransmission();
  delay(10);

  Wire.beginTransmission(RTC8564);
  Wire.write(0x00);
  Wire.endTransmission();
  Wire.requestFrom(RTC8564, 16);
  for (i = 0; i < 16; i++) {
    while (Wire.available() == 0 ) {}
    RegTbl[i] = Wire.read();
  }
  ihour = (BCDtoDec(RegTbl[4] & 0x3F));
  imin = (BCDtoDec(RegTbl[3] & 0x7F));
  isec = (BCDtoDec(RegTbl[2] & 0x7F));

  
  mcp0.begin();
  mcp1.begin(0x01);
  mcp2.begin(0x03);

  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();
}

void loop() {
  Serial.println("LOOP");
  Wire.beginTransmission(RTC8564);
  Wire.write(0x00);
  Wire.endTransmission();
  Wire.requestFrom(RTC8564, 16);
  for (i = 0; i < 16; i++) {
    while (Wire.available() == 0 ) {}
    RegTbl[i] = Wire.read();
  }

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

  write_display0(h2);
  write_display1(h1);
  write_display2(s2);
  write_display3(s1);
  write_display4(m2);
  write_display5(m1);

  delay(100);
}

※クリックするとプログラムが表示されます

だらだらと同じようなことを繰り返し書いているので、いつか関数化してわかりやすくしたいと思っています。(遠い目)
そして、実際に時計が動いている様子はこのようになります。

 

基板以外はいい感じですね。
基板は変なところから吊るされているし、線が配線がぐちゃぐちゃっと出ていて大変美しくないです。(哀)

哀しい回路の模様はこちらです。

ということで、この時計回路をプリント基板化してすっきりさせていきたいと思います。

プリント基板作成

プリント基板製作は<JLCPCB>様に依頼します。

プリント基板を発注するために回路図とプリント基板の設計図をKiCadで作成します。
作成した設計図から発注データの作成を行い、JLCPCB様で基板の注文を行っていきます。

回路図とプリント基板の作成

時計の回路をすっきりさせるために、プリント基板の作成をしていきます。
プリント基板を作るのは初めてなので、失敗、間違い等があるかもしれません。ドキドキします。
基板の設計ですが、実際に時計を作ってみてから、いろいろと欲が出てきてしまいました。
追加の機能として目覚まし機能を付けようと思います。なので回路にブザーとランプを組み込みました。
電源は24Vの直流電源を使用して、その電源をリレーを介して、ランプの点灯をさせてみます。
そんなこんなで作成した回路が以下になります。ちなみに回路はkiCADを使用しています。

この回路図を基に作成した部品配置図が以下になります。
綺麗に配置させるのにはなかなか苦労しました。

そして、実際に配線を行った基板の3Dモデルが以下になります。

うーん、カッコいいですね!!この基板が実際に手元に来ると思うとワクワクします!!
いつか、kicadによる基板設計の記事を書こうと思います。

発注用ガーバーデータの作成

まず、発注用データの作成をしていきます。
KiCadの上部アイコンよりPLOTを選択して、「製造ファイル出力」ウィンドウを選択します。


ガーバデータに含むレイヤーに以下の7つを選択します。

レイヤー名 内容
F.Cu 表面の銅箔面
B.Cu 裏面の銅箔面
F.SilkS 表面のシルク印刷
B.SilkS 裏面のシルク印刷
F.Mask 表面のレジストマスク
B.Mask 裏面のレジストマスク
Edge.Cuts 外形レイヤ

レイヤーを選択して製造ファイル出力ボタンを押すことでガーバーデータが生成されます。
正常に生成されると、出力メッセージに以下のような文言が出力されます。

次にドリルファイルを生成します。

マップファイルのチェックが「ガーバー」になっている事、ドリル単位が「mm」になっていることに注意して「ドリルファイルを生成」ボタンを押して、ドリルファイルを生成します。
「*************.drl」ファイルが生成されます。

作成した計8つのファイルから2つのファイルの拡張子を変更します。
「*************.drl」→「*************.txt」
「*************.gm1」→「*************.gml」

拡張子の変更が行えたら、上記で生成したデータが入っているフォルダをZIPで圧縮します。
これで、発注用データの作成は完成です。

実際に発注していきましょう。

JLCPCBで基板の発注

JLCPCBで基板の発注を行っていきます。
JLCPCBにアクセスして、「Order now」を選択します。

「Add gerber file」を選択して先ほど作成したzipファイルをアップロードします。
正常にアップロードされると以下のように作成する基盤が表示されます。
今回作成する基板は5枚作製して7.90ドルで作れるみたいですね。

「SAVE TO CART」を押して、作成基板を買い物かごに入れておきます。
買い物かごに移動して、「Secure Checkout」ボタンを押して購入画面に進みます。

そこで、住所、運輸方法、支払い方法を選択すると発注完了でした。
これで、発注作業は完了です。

基板の到着が待ち遠しいですね。

自分でプリント基板を作れるなんていい時代になりました。
電子工作の幅も技術もレベルもどんどん上がっていきそうです。

基板が届いて実装できたら続編を書きたいと思います
続編書きました!!

【ESP32で電子工作-3】デジタル時計の作成(2)【プリント基板への実装】

それまで、良き電子工作ライフを!!
See You …

ブログランキング参加中

クリックしていただけると
ブログ更新の励みになります


電子工作ランキング
にほんブログ村 その他趣味ブログ 電子工作へ
にほんブログ村

スポンサーリンク

-Arduino, ESP32
-, , , , ,