#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>
#include <WiFiUdp.h>
#include <TimeLib.h>
int pinCS = D4; // Attach CS to this pin, DIN to MOSI and CLK to SCK (cf http://arduino.cc/en/Reference/SPI )
/**
* ESP8266 Pin
* D4 -> CS -> CS
* D5 -> HSCLK -> CLK
* D7 -> HMOSI -> DIN
* 3V -> VCC
* G -> GND
*/
int numberOfHorizontalDisplays = 4;
int numberOfVerticalDisplays = 1;
#define _DISPLAY_ROTATE 1
Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);
#ifndef STASSID
#define STASSID "█████████████████"
#define STAPSK "█████████"
#endif
const char* ssid = "fyx";
const char* password = "20000402";
WiFiUDP Udp;
const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of the message
byte packetBuffer[NTP_PACKET_SIZE]; // Buffer for I / O packets
unsigned int localPort = 8888; // Local port for listening UDP packets
static const char ntpServerName[] = "ntp.sjtu.edu.cn"; // NTP server, Shanghai Jiaotong University
const int timeZone = 8; // Time zone, Beijing time is + 8
time_t preDisplayTime = 0; // Last clock display time
String display_content = "00:00";
int days = 0;
int change_flag = 0; //display time when flag is 0, display days when flag is 1
// 3x5 char maps
uint16_t numMap3x5[] = {
32319, //0
10209, //1
24253, //2
22207, //3
28831, //4
30391, //5
32439, //6
16927, //7
32447, //8
30399 //9
};
// 4x5 char maps
uint32_t numMap4x5[] = {
476718, //0
10209, //1
315049, //2
579246, //3
478178, //4
972470, //5
480418, //6
544408, //7
349866, //8
415406 //9
};
unsigned long api_mtbs = 20000; //mean time between api requests
unsigned long api_lasttime = 20000; //last time api request has been done
#define PIXEL_SHOW HIGH
#define PIXEL_HIDE LOW
void _drawPixel(Max72xxPanel display, uint8_t x, uint8_t y, uint8_t pixel)
{
display.drawPixel(x, y, pixel);
}
void _drawLine(Max72xxPanel display, uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t pixel)
{
display.drawLine(x1, y1, x2, y2, pixel);
}
void _drawPixelHorizontalMirror(Max72xxPanel display, uint8_t x, uint8_t y, uint8_t pixel)
{
display.drawPixel(x, y, pixel);
display.drawPixel(7-x, y, pixel);
}
void _fillHeart(Max72xxPanel display, uint8_t pixel)
{
_drawPixelHorizontalMirror(display, 1, 2, pixel);
_drawPixelHorizontalMirror(display, 1, 3, pixel);
_drawPixelHorizontalMirror(display, 2, 2, pixel);
_drawPixelHorizontalMirror(display, 2, 3, pixel);
_drawPixelHorizontalMirror(display, 2, 4, pixel);
_drawPixelHorizontalMirror(display, 3, 3, pixel);
_drawPixelHorizontalMirror(display, 3, 4, pixel);
_drawPixelHorizontalMirror(display, 3, 5, pixel);
}
void drawHeart(Max72xxPanel display, int heart_fill)
{
display.fillRect(0, 0, 8, 8, PIXEL_HIDE);
_drawPixelHorizontalMirror(display, 3, 2, PIXEL_SHOW);
_drawPixelHorizontalMirror(display, 2, 1, PIXEL_SHOW);
_drawPixelHorizontalMirror(display, 1, 1, PIXEL_SHOW);
_drawPixelHorizontalMirror(display, 0, 2, PIXEL_SHOW);
_drawPixelHorizontalMirror(display, 0, 3, PIXEL_SHOW);
_drawPixelHorizontalMirror(display, 1, 4, PIXEL_SHOW);
_drawPixelHorizontalMirror(display, 2, 5, PIXEL_SHOW);
_drawPixelHorizontalMirror(display, 3, 6, PIXEL_SHOW);
if (heart_fill == 1) {
_fillHeart(display, PIXEL_SHOW);
}
else {
_fillHeart(display, PIXEL_HIDE);
}
}
void drawSplashtop(Max72xxPanel display)
{
// F
_drawLine(display, 8, 1, 8, 5, PIXEL_SHOW);
_drawLine(display, 9, 1, 10, 1, PIXEL_SHOW);
_drawLine(display, 9, 3, 10, 3, PIXEL_SHOW);
// O
_drawLine(display, 12, 1, 12, 5, PIXEL_SHOW);
_drawLine(display, 13, 1, 14, 1, PIXEL_SHOW);
_drawLine(display, 13, 5, 14, 5, PIXEL_SHOW);
_drawLine(display, 14, 2, 14, 4, PIXEL_SHOW);
//R
_drawLine(display, 16, 1, 16, 5, PIXEL_SHOW);
_drawLine(display, 17, 1, 18, 1, PIXEL_SHOW);
_drawPixel(display, 18, 2, PIXEL_SHOW);
_drawPixel(display, 17, 3, PIXEL_SHOW);
_drawLine(display, 18, 4, 18, 5, PIXEL_SHOW);
// F
_drawLine(display, 21, 1, 21, 5, PIXEL_SHOW);
_drawLine(display, 22, 1, 23, 1, PIXEL_SHOW);
_drawLine(display, 22, 3, 23, 3, PIXEL_SHOW);
// Y
_drawLine(display, 25, 1, 25, 3, PIXEL_SHOW);
_drawLine(display, 27, 1, 27, 3, PIXEL_SHOW);
_drawLine(display, 26, 4, 26, 5, PIXEL_SHOW);
// X
_drawLine(display, 29, 1, 29, 2, PIXEL_SHOW);
_drawLine(display, 29, 4, 29, 5, PIXEL_SHOW);
_drawLine(display, 31, 1, 31, 2, PIXEL_SHOW);
_drawLine(display, 31, 4, 31, 5, PIXEL_SHOW);
_drawPixel(display, 30, 3, PIXEL_SHOW);
display.write();
// Y
//_drawLine(display, 21, 1, 21, 3, PIXEL_SHOW);
//_drawLine(display, 23, 1, 23, 3, PIXEL_SHOW);
//_drawLine(display, 22, 4, 22, 5, PIXEL_SHOW);
// O
//_drawLine(display, 25, 1, 25, 5, PIXEL_SHOW);
//_drawLine(display, 26, 1, 27, 1, PIXEL_SHOW);
//_drawLine(display, 26, 5, 27, 5, PIXEL_SHOW);
//_drawLine(display, 27, 2, 27, 4, PIXEL_SHOW);
// U
//_drawLine(display, 29, 1, 29, 5, PIXEL_SHOW);
//_drawLine(display, 31, 1, 31, 5, PIXEL_SHOW);
//_drawPixel(display, 30, 5, PIXEL_SHOW);
// W
//_drawLine(display, 17, 1, 17, 2, PIXEL_SHOW);
//_drawLine(display, 18, 3, 18, 4, PIXEL_SHOW);
//_drawPixel(display, 19, 5, PIXEL_SHOW);
//_drawLine(display, 20, 2, 20, 4, PIXEL_SHOW);
//_drawPixel(display, 21, 5, PIXEL_SHOW);
//_drawLine(display, 22, 3, 22, 4, PIXEL_SHOW);
//_drawLine(display, 23, 1, 23, 2, PIXEL_SHOW);
// W
//_drawLine(display, 25, 1, 25, 2, PIXEL_SHOW);
//_drawLine(display, 26, 3, 26, 4, PIXEL_SHOW);
//_drawPixel(display, 27, 5, PIXEL_SHOW);
//_drawLine(display, 28, 2, 28, 4, PIXEL_SHOW);
//_drawPixel(display, 29, 5, PIXEL_SHOW);
//_drawLine(display, 30, 3, 30, 4, PIXEL_SHOW);
//_drawLine(display, 31, 1, 31, 2, PIXEL_SHOW);
}
void drawMapValue3x5(Max72xxPanel display, uint8_t x, uint8_t y, uint32_t val)
{
for (uint8_t i = 0; i < 20; i++)
{
if ((val >> i) & 1 == 1) {
display.drawPixel(x + (3 - i / 5) - 1, y + (4 - i % 5), PIXEL_SHOW);
}
}
}
void drawMapValue4x5(Max72xxPanel display, uint8_t x, uint8_t y, uint32_t val)
{
for (uint8_t i = 0; i < 20; i++)
{
if ((val >> i) & 1 == 1) {
display.drawPixel(x + (4 - i / 5) - 1, y + (4 - i % 5), PIXEL_SHOW);
}
}
}
int calculatDays(int year_start, int month_start, int day_start, int year_end, int month_end, int day_end){
int y2, m2, d2;
int y1, m1, d1;
m1 = (month_start + 9) % 12;
y1 = year_start - m1/10;
d1 = 365*y1 + y1/4 - y1/100 + y1/400 + (m1*306 + 5)/10 + (day_start - 1);
m2 = (month_end + 9) % 12;
y2 = year_end - m2/10;
d2 = 365*y2 + y2/4 - y2/100 + y2/400 + (m2*306 + 5)/10 + (day_end - 1);
return (d2 - d1);
}
void changeDisplay(){
if (change_flag == 0) {
int days = calculatDays(2000, 4, 2, year(), month(), day());
display_content = days;
display_content = display_content + " D";
change_flag = 1;
}
else{
display_content = displayTimeFormat(hour(), minute());
change_flag = 0;
}
}
String displayTimeFormat(int hour, int minute){
if (hour>=0 && hour<=9) {
display_content = "0";
display_content = display_content + hour;
}
else{
display_content = hour;
}
display_content = display_content + ":";
if (minute>=0 && minute<=9) {
display_content = display_content + "0";
display_content = display_content + minute;
}
else{
display_content = display_content + minute;
}
return display_content;
}
void refreshTime(){
if (timeStatus() != timeNotSet){
if (now() != preDisplayTime){
preDisplayTime = now();
display_content = displayTimeFormat(hour(), minute());
}
}
}
time_t getNtpTime()
{
IPAddress ntpServerIP;
while (Udp.parsePacket() > 0);
Serial.println("Transmit NTP Request");
WiFi.hostByName(ntpServerName, ntpServerIP);
Serial.print(ntpServerName);
Serial.print(": ");
Serial.println(ntpServerIP);
sendNTPpacket(ntpServerIP);
uint32_t beginWait = millis();
while (millis() - beginWait < 1500){
int size = Udp.parsePacket();
if (size >= NTP_PACKET_SIZE){
Serial.println("Receive NTP Response");
Udp.read(packetBuffer, NTP_PACKET_SIZE);
unsigned long secsSince1900;
secsSince1900 = (unsigned long)packetBuffer[40] << 24;
secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
secsSince1900 |= (unsigned long)packetBuffer[43];
Serial.println(secsSince1900);
Serial.println(secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR);
return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
}
}
Serial.println("No NTP Response :-(");
return 0;
}
void sendNTPpacket(IPAddress &address)
{
memset(packetBuffer, 0, NTP_PACKET_SIZE);
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
Udp.beginPacket(address, 123);
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}
void setup() {
SPI.begin();
SPI.setFrequency(10000000); // Here is 10Mhz
matrix.setIntensity(2); // Set brightness between 0 and 15
for (int i = 0; i< numberOfHorizontalDisplays; i++)
matrix.setRotation(i,_DISPLAY_ROTATE);
matrix.fillScreen(PIXEL_HIDE);
drawHeart(matrix, 1);
drawSplashtop(matrix);
WiFi.mode(WIFI_STA);
wifi_fpm_set_sleep_type(LIGHT_SLEEP_T);
WiFi.begin(ssid, password);
Serial.begin(115200);
Serial.println();
Serial.printf("Flash: %d\n", ESP.getFlashChipRealSize());
Serial.print("Connecting");
int processbar = 0;
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
drawHeart(matrix, processbar % 2);
matrix.drawPixel(8 + (processbar % 24), 7, (processbar / 24) % 2 == 0 ? PIXEL_SHOW : PIXEL_HIDE);
matrix.write();
processbar++;
}
Serial.println();
Serial.print("Connected to wifi. My address:");
IPAddress myAddress = WiFi.localIP();
Serial.println(myAddress);
WiFi.setSleepMode(WIFI_LIGHT_SLEEP, 1000);
matrix.fillScreen(PIXEL_HIDE);
drawHeart(matrix, 1);
drawSplashtop(matrix);
Udp.begin(localPort);
setSyncProvider(getNtpTime);
setSyncInterval(300); //Synchronize every 300 seconds
display_content = displayTimeFormat(hour(), minute());
}
void loop() {
// because of unsigned long, when overflow, it will be huge number
unsigned long duration = millis() - api_lasttime;
if (duration >= api_mtbs)
{
api_lasttime = millis();
if (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi Disconnected");
ESP.restart();
}
changeDisplay();
}
matrix.fillScreen(PIXEL_HIDE);
//Progress bar countdown
int x = 9;
drawHeart(matrix, 1);
Serial.println("[duration]:" + duration);
uint32_t waitBarLen = 20 - (duration / float(api_mtbs) * 20);
if (waitBarLen > 20) waitBarLen = 20;
for (uint8_t waitBar = 0; waitBar < waitBarLen; waitBar++)
{
_drawPixel(matrix, 9 + waitBar, 6, PIXEL_SHOW);
_drawPixel(matrix, 9 + waitBar, 7, PIXEL_SHOW);
}
//show contents
if (change_flag == 0) {
refreshTime();
}
Serial.println("[display_content]:" + display_content);
for (int i=0; i<display_content.length(); i++) {
if (display_content[i] >= '0' && display_content[i] <= '9')
{
drawMapValue3x5(matrix, x, 0, numMap3x5[display_content[i] - '0']);
x += 4;
} else if (display_content[i] == ':') {
matrix.drawPixel(x, 2, PIXEL_SHOW);
matrix.drawPixel(x, 4, PIXEL_SHOW);
x += 2;
} else if (display_content[i] == ' ') {
x += 1;
} else {
//matrix.drawChar(x, 0, display_content[i], PIXEL_SHOW, PIXEL_HIDE, 1);
matrix.drawLine(x, 0, x, 4, PIXEL_SHOW);
matrix.drawLine(x+1, 0, x+2, 0,PIXEL_SHOW);
matrix.drawLine(x+1, 4, x+2, 4,PIXEL_SHOW);
matrix.drawLine(x+3, 1, x+3, 3, PIXEL_SHOW);
x+=5;
}
}
matrix.write(); // Send bitmap to display
delay(1000);
}
网友评论