我想做的是使用Wemos D1 Mini v3创建一个简单的NTP时钟,该时钟将在64x8 MAX7219屏幕(2个加入的32x8屏幕)上显示工作日,日期和时间。
我在网上发现a sketch确实可以做到这一点,但是它使用滚动效果来更新屏幕,我想将其更改为其他效果。然后我发现了MD Parola库,它具有我要使用的效果(称为PA_OPENING_CURSOR)。附带说明一下,我正在使用最新的MD_Parola和MD_MAX72xx库(它们大约在一个月前更新)。
我想要得到的结果是:
通过使用初始草图并将其与Parola库示例合并,我设法到达了下面的草图(从原始草图更改并进行了评论,以便我可以更好地理解代码和所采取的每个步骤-新手警报),但由于不知道如何将所需的变量传递给产生切换效果的代码,我陷入了停滞状态。如您所见,该草图当前显示工作日/日期/时间(星期一/ 2345/21 Jan / 17:21:59),但它们的值仅是硬编码(静态)的,因此不会从NTP服务器上拉出。 Arduino IDE的串行监视器向我显示NTP时间已从NTP服务器正确提取。
到目前为止,我的代码是:
/*
NTP CLOCK and DATE Scroller
*/
//___________________________________________________________LIBRARIES USED
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <ESP8266WebServer.h>
#include <TimeLib.h>
//___________________________________________________________PINS DEFINITIONS
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 8
#define CLK_PIN D5 // or SCK
#define DATA_PIN D7 // or MOSI
#define CS_PIN D4 // or SS
//___________________________________________________________ARBITRARY PINS DEFINITIONS
MD_Parola p = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
//___________________________________________________________USER CONTROL (POTENTIOMETER)
#define USE_UI_CONTROL 0 // set to 1 if we are implementing the user interface pot
#if USE_UI_CONTROL
#define SPEED_IN A0
uint8_t frameDelay = 25; // default frame delay value
#endif
//___________________________________________________________SPEED DEFINITION
#define SPEED_TIME 25 // Lower number means faster speed
#define PAUSE_TIME 2000
//___________________________________________________________DEBUGGING
#define DEBUG 1 // Change to 1/0 to turn on/off debug statements to the serial output
#if DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTX(x) Serial.println(x, HEX)
#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTX(x)
#endif
//___________________________________________________________WEB SERVER SETUP
ESP8266WebServer server(80);
const char ssid[] = "My_SSID_here"; // your network SSID (name)
const char pass[] = "My_Password_here"; // your network password
//___________________________________________________________NTP SERVER and TIMEZONE
static const char ntpServerName[] = "3.uk.pool.ntp.org";
const float timeZone = 1.0; // UK Standard Time
WiFiUDP Udp;
unsigned int localPort = 8888; // local port to listen for UDP packets
time_t getNtpTime();
void sendNTPpacket(IPAddress &address);
static boolean isLongFormat = false;
String myTime;
String myDate;
//___________________________________________________________TIME AND DATE FUNCTION
void timeDisplay() {
// Populate myTime String
myTime = hour();
if (hour() < 10) {
myTime = "0" + myTime;
}
if (minute() < 10) {
myTime = myTime + " : 0" + minute();
}
else {
myTime = myTime + " : " + minute();
}
myTime = (" " + myTime + " ");
PRINT("\nMyTime: ", myTime);
int myTime_len = myTime.length() + 1;
char myTime_charArray[myTime_len];
myTime.toCharArray(myTime_charArray, myTime_len);
PRINT("\nMyTime_charArray: ", myTime_charArray );
}
void dateDisplay() {
// Populate myDate String
myDate = myDate + " " + day() + " " + monthShortStr(month()) + " " + year() ;
myDate = (" " + myDate + " ");
PRINT("\nMyDate: " , myDate);
// covert from string/float to char array
int myDate_len = myDate.length() + 1;
char myDate_charArray[myDate_len];
myDate.toCharArray(myDate_charArray, myDate_len);
PRINT("\nMyDate_charArray: ", myDate_charArray);
}
//___________________________________________________________DEFINE THE TEXT TO DISPLAY
// Global variables
uint8_t curText;
char *pc[] =
{
"Monday",
"17 Jan 2345",
"21 : 59",
};
//___________________________________________________________DEFINE THE TEXT EFFECT
uint8_t inFX, outFX;
textEffect_t effect[] =
{
PA_OPENING_CURSOR,
};
//___________________________________________________________USER CONTROL ACTIONS (IF USED)
#if USE_UI_CONTROL
void doUI(void)
{
// set the speed if it has changed
{
int16_t speed = map(analogRead(SPEED_IN), 0, 1023, 0, 250);
if (speed != (int16_t)p.getSpeed())
{
p.setSpeed(speed);
p.setPause(speed);
frameDelay = speed;
PRINT("\nChanged speed to ", p.getSpeed());
}
}
}
#endif // USE_UI_CONTROL
//___________________________________________________________void setup
void setup()
{
p.begin();
#if DEBUG
Serial.begin(115200);
delay(1000);
#endif
Serial.begin(115200);
PRINTS("\nLet's see if this thing will EVER work...");
PRINTS("\n ");
delay(1000);
PRINT("\nConnecting to the WiFi Network named > ", ssid);
WiFi.begin(ssid, pass);
delay(1000);
PRINTS("\n ");
PRINTS("\nConnection established successfully");
PRINTS("\n ");
PRINT("\nThe IP address assigned to your device by your WiFi router is ", WiFi.localIP());
PRINTS("\n ");
PRINTS("\nStarting UDP...");
PRINTS("\n ");
Udp.begin(localPort);
PRINT("\nLocal port: ", Udp.localPort());
PRINTS("\n ");
PRINTS("\nWaiting for synchronisation...");
PRINTS("\n ");
PRINTS("\n ");
setSyncProvider(getNtpTime);
setSyncInterval(120); // NTP re-sync interval in seconds
#if USE_UI_CONTROL
pinMode(SPEED_IN, INPUT);
doUI();
#endif // USE_UI_CONTROL
p.begin();
p.setInvert(false);
p.displayText(pc[curText], PA_CENTER, SPEED_TIME, PAUSE_TIME, effect[inFX], effect[outFX]);
}
//___________________________________________________________NTP CODE
const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets
time_t getNtpTime()
{
IPAddress ntpServerIP; // NTP server's ip address
while (Udp.parsePacket() > 0) ; // discard any previously received packets
Serial.println("Transmited request to the NTP server:");
WiFi.hostByName(ntpServerName, ntpServerIP);
Serial.print(" "); 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(" ");
Serial.println("The NTP server responded successfully");
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer
unsigned long secsSince1900;
// convert four bytes starting at location 40 to a long integer
secsSince1900 = (unsigned long)packetBuffer[40] << 24;
secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
secsSince1900 |= (unsigned long)packetBuffer[43];
return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
}
}
Serial.println("No NTP Response :-(");
return 0; // return 0 if unable to get the time
}
// send an NTP request to the time server at the given address
void sendNTPpacket(IPAddress &address)
{
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 30; // 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;
// all NTP fields have been given values, now
// you can send a packet requesting a timestamp:
Udp.beginPacket(address, 123); //NTP requests are to port 123
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}
//___________________________________________________________void loop
void loop()
{
#if DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTD(x) Serial.println(x, DEC)
#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTD(x)
#endif
#if USE_UI_CONTROL
doUI();
#endif // USE_UI_CONTROL
if (p.displayAnimate()) // animates and returns true when an animation is completed
{
// Set the display for the next string.
curText = (++curText) % ARRAY_SIZE(pc);
p.setTextBuffer(pc[curText]);
// When we have gone back to the first string, set a new exit effect
// and when we have done all those set a new entry effect.
if (curText == 0)
{
outFX = (++outFX) % ARRAY_SIZE(effect);
if (outFX == 0)
p.setTextEffect(effect[inFX], effect[outFX]);
}
// Tell Parola we have a new animation
p.displayReset();
}
}
您能指导我如何实现这一目标吗?我是Arduino编程的新手,这对我来说已经太复杂了。我了解我已经很接近实现自己想要的目标,但是我凭有限的知识无法弄清楚。
谢谢。