インターネット時計の作成(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チカ】」を読んでいただければわかると思います。
プログラムの流れとしては、
- ライブラリの読み込み、変数設定
- シリアル、I2C、WIFIの設定
今回は自宅インターネットにつながってるWIFIルーターに接続しています。 - インターネットより現在時刻を取得
取得した時間をRTCに書き込み - I/Oエキスパンダーの設定、LCDの初期化
- ループ関数
RTCより随時時間を取得してLCDに出力
簡単にザクっと説明するとこのようなプログラムを作成しました。
作成したプログラムは以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 |
#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 …