-->
Page 1 of 1

Wemos D1 Mini MAX7219 NTP Clock

PostPosted: Mon Jul 02, 2018 6:16 am
by CTB
What I am trying to do is create a simple NTP clock that will display the weekday, date and time on a 64x8 MAX7219 screen (2 joined 32x8 screens) by using a Wemos D1 Mini v3.

I found a sketch at https://github.com/shariramani/Magic-Sc ... Part-1.ino that does exactly that, but it uses a scroll effect to update the screen, which I want to change to a different effect. Then I found the MD Parola library which has an effect that I want to use (it's called PA_OPENING_CURSOR). As a side note, I am using the latest MD_Parola (https://github.com/MajicDesigns/MD_Parola) and MD_MAX72xx (https://github.com/MajicDesigns/MD_MAX72XX) libraries (they were updated around a month ago).

The result I want to get is:

display the weekday (e.g. Thursday)
switch (with the PA_OPENING_CURSOR effect) to the date (e.g. 12/05/2019)
switch (with the PA_OPENING_CURSOR effect again) to the time (e.g. 19:57)
repeat
By making use of the initial sketch and merging it with the Parola library examples, I've managed to reach to the sketch below (altered from the originals and heavily commented so that I can better understand the code and every step taken - newbie alert) but I've reached to a standstill as I don't know how to pass the required variables to the code that creates the swithcing effect. As you can see, the sketch currently displays the weekday/date/time (Monday/17 Jan 2345/21:59) but their values are only hard-coded (static), so they are not pulled up from the NTP server. The serial monitor of the Arduino IDE shows me that the NTP time is pulled from the NTP server correctly.

The code I have so far is:

Code: Select all/*
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();
  }
}


Could you please guide me on how to achieve this? I am completely new to Arduino programming and this is already way too complex for me. I understand that I am very close to achieving what I want but I can't figure it out with my very limited knowledge.

Thanks in advance.