#include <Wire.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <Fonts/FreeSans9pt7b.h> // Small Font
#include <WiFiUdp.h>
#include <NTPClient.h>
#include "nixie_font.h"
#if defined(ESP8266)
#include "ESP8266WiFi.h"
#elif defined(ESP32)
#include "WiFi.h"
#endif
#if defined(ESP8266)
#define TFT_CS -1
#define TFT_DC D0 //GPIO 16
#define TFT_MOSI D7 //GPIO 13
#define TFT_CLK D5 //GPIO 14
#define TFT_RST D6 //GPIO 12
#define TFT_LED D8 //GPIO 15
#elif defined(ESP32)
#define TFT_CS 2
#define TFT_DC 5
#define TFT_MOSI 23
#define TFT_CLK 18
#define TFT_RST 4
#define TFT_LED 19
#else
#error "This ain't a ESP8266 or ESP32"
#endif
#define UTC_OFFSET 9 //time offset
//Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST);
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
//Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
const char* ssid = "Wokwi-GUEST"; // SSID of local network
const char* password = ""; // Password on network
WiFiClient client;
WiFiUDP udp;
//NTPClient(UDP& udp, const char* poolServerName, int timeOffset, int updateInterval);
NTPClient timeClient(udp, "kr.pool.ntp.org", 3600*UTC_OFFSET, 3600*1000*1); //update every 1 hour
unsigned long lastUpdate = 0;
byte h = 24;
byte m = 60;
byte s = 60;
byte dy = 60;
void setup() {
pinMode(TFT_LED, OUTPUT);
digitalWrite(TFT_LED, HIGH); // HIGH to Turn on;
tft.begin();
tft.setRotation(3);
tft.fillScreen(ILI9341_BLACK);
tft.setFont(&FreeSans9pt7b);
tft.setCursor(0, 25);
Serial.begin(115200);
tft.println("Connecting");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
tft.print(".");
}
Serial.println("");
Serial.println("Connected!!");
tft.println("");
tft.println("Connected!!");
delay(1000);
tft.fillScreen(ILI9341_BLACK);
}
void loop() {
timeClient.update();
if (h != timeClient.getHours()) { //Hours
h = timeClient.getHours();
tft.drawRGBBitmap (64*0+2, dy, nixie[h/10], 60, 118);
tft.drawRGBBitmap (64*1+2, dy, nixie[h%10], 60, 118);
}
if (s != timeClient.getSeconds()) { //도트 점멸
s = timeClient.getSeconds();
if(s%2) tft.drawRGBBitmap (64*2+2, dy, nixie[10], 60, 118);
else tft.drawRGBBitmap (64*2+2, dy, nixie[11], 60, 118);
}
if (m != timeClient.getMinutes()) { //Minutes
m = timeClient.getMinutes();
tft.drawRGBBitmap (64*3+2, dy, nixie[m/10], 60, 118);
tft.drawRGBBitmap (64*4+2, dy, nixie[m%10], 60, 118);
}
delay(100);
}
/*
Nixie는 아래 사진처럼 진공관처럼 생긴 유리관 안에 여러개의 숫자모양의 금속판을 겹쳐 놓고
이를 금속망으로 둘러 싼 모습을 하고 있다. 내부는 네온가스로 채워져 있고 숫자모양의
금속판을 음극, 바깥쪽의 금속망을 양극에 연결하고 170V 이상의 전압을 가하면
네온램프처럼 방전에 의해 음극판이 붉은 색으로 발광한다. 진공관처럼 히터가 없기 때문에
전력소모가 적고 당시 기준으로는 반응이 빨라 컴퓨터나 계측기 등 여러가지 표시장치에 사용되었다.
7-segment LED나 도트매트릭스 LED처럼 여러개의 발광 소자를 조합해 숫자를 표시하는
것이 아니라 각 숫자가 독립적인 금속판으로 만들어져 있어 숫자의 모양을 원래 형태에 가깝게
아름답게 표현할 수 있다. 또한 색깔도 아날로그 느낌의 따뜻한 주홍색으로 진공관 같은
모양과 더불어 과거의 향수를 불러일으켜 장식용으로 더할 나위 없어 최근 시계로 만들어져
비싼 가격에 거래되고 있다. 다만 생산과 사용이 중단 된 지 오래되어 시장에서 쉽게 구할 수 없고,
이베이 같은 곳에서 일부 재고가 유통되기는 하지만 가격이 꽤 비싸게 거래된다는 단점이 있다.
닉시관으로 시계를 만들어보면 좋겠지만 구하기 어렵고, 가격도 비쌀 뿐 아니라 170V이상의
고전압을 다루어야하기 때문에 전기 전자에 대한 지식과 경험이 필요하므로 여기서는 Color TFT LCD를
이용하여 닉시관 모양의 숫자가 표시되는 시계를 만들어보기로 한다.
컬러 이미지를 다루어야하므로 빠른 속도와 더불어 큰 메모리가 필요하다. 따라서
ESP32 보드가 권장되며, ESP8266도 이미지를 갱신하는 속도가 조금 느리기는 하지만
사용이 가능하다. TFT LCD는 240x320 해상도의 ILI9341 드라이버 IC와
SPI 통신을 사용하는 제품을 사용한다. 같은 해상도의 ST7789 드라이버를 사용하는
제품도 사용 가능하며 해당 드라이버의 라이브러리를 추가하고 소스코드를 약간 수정하면 된다.
하드웨어 연결은 소스코드와 #define으로 정의된 부분과 그림을 참조하여 연결하면 된다.
Adafruit의 ILI9341 라이브러리는 주석처리된 부분처럼
Adafruit_ILI9341(CS pin, DC pin, MOSI pin, CLK pin, RST pin);
의 형태로 모든 핀을 사용자가 재정의하여 지정하는 것도 가능하지만 디스플레이 속도가
많이 느려지므로 CS pin과 DC pin, RST pin만 사용자가 지정하는 방식으로 사용하는 것이 좋다.
간혹 TFT LCD 중에는 CS pin이 생략된 경우가 있는데 당황하지 말고 핀 번호 대신 -1을 넣어주면
된다. D1 MINI 같은 ESP8266 보드들은 보드에 인쇄된 핀 번호와 GPIO 번호가 다르므로
보드에 인쇄된 핀번호를 사용하려면 반드시 D1, D2 같이 D를 붙여서 사용해야 한다.
TFT LCD를 사용하기 위해 아래와 같이 그래픽 라이브러리와 폰트를 포함시킨다.
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <Fonts/FreeSans9pt7b.h> // Small Font
닉시 이미지를 배열로 만들어 놓은 nixie_font.h 파일을 다운 받아 소스코드가 저장된
폴더에 옮겨 놓고 #include "nixie_font.h"로 포함시킨다.
아래 내용은 와이파이 접속과 관련된 라이브러리들이다. #if defined()~#endif 문은
선택적 컴파일 명령으로 ESP8266과 ESP32가 사용하는 와이파이 라이브러리가 다르기
때문에 보드에 따라 다른 라이브러리를 포함시키기 위한 구문이다.
#include <WiFiUdp.h>
#include <NTPClient.h>
#if defined(ESP8266)
#include "ESP8266WiFi.h"
#elif defined(ESP32)
#include "WiFi.h"
#endif
NTP Server에서 시간을 얻어 오는 방법 등은 앞선 예제에서 활용해 본 방법과 같다.
화면에 시계 이미지를 표시하는 함수는
drawRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], int16_t w, int16_t h)
인데 표시할 위치값 x와 y, 이미지 데이터의 배열, 이미지의 폭과 높이를 인수로 받는다.
&& 자신만의 이미지를 배열로 만드는 법 &&
http://www.rinkydinkelectronics.com/t_imageconverter565.php
*/