Using MD MAX and Parola libraries. I'm trying to make a clock using max7219 and 8x8 leds.
I start with minimal print example and ad RTC. I can display hours, minutes and seconds as their own, but trying to make hh:mm:ss display they just group and stack to the left corner.
Any ideas how to display them in row instead on top of each other?
Code:
// Program to demonstrate the MD_Parola library
//
// Simplest program that does something useful - Hello!
// Uses the Arduino Print Class extension
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#include <MD_Parola.h>
#include <MD_DS3231.h>
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// Hardware SPI connection
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
void setup(void)
{
P.begin();
}
void loop(void)
{
RTC.readTime();
P.print(RTC.h);
P.print(RTC.m);
P.print(RTC.s);
delay(1000);
}
// Program to demonstrate the MD_Parola library
//
// Simplest program that does something useful - Hello!
// Uses the Arduino Print Class extension
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#include <MD_Parola.h>
#include <MD_DS3231.h>
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// Hardware SPI connection
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
void setup(void)
{
P.begin();
}
char buf[20];
void loop(void)
{
RTC.readTime();
sprintf(buf,"%02d%02d%02d",RTC.h, RTC.m,RTC.s);
P.print(buf);
delay(1000);
}
On Wokwi it looks like this:
Be aware that the sketch on Wokwi is different to your version due to the available simulation components ...!!!
Be aware that unfortunately the formatting of float variables is switched off in the compiler directives as uses by Arduino IDE. There are work arounds for that:
// Use the MD_MAX72XX library to Print some text on the display
//
// Demonstrates the use of the library to print text.
//
// User can enter text on the serial monitor and this will display as a
// message on the display.
#include <MD_MAX72xx.h>
#include <SPI.h>
#include <MD_DS3231.h>
#include "SafeString.h"
cSF(myMessage_SS,8);
#define PRINT(s, v) { Serial.print(F(s)); Serial.print(v); }
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 4
#define CLK_PIN 13 // or SCK
#define DATA_PIN 11 // or MOSI
#define CS_PIN 10 // or SS
// SPI hardware interface
MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary pins
//MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
// Text parameters
#define CHAR_SPACING 1 // pixels between characters
// Global message buffers shared by Serial and Scrolling functions
#define BUF_SIZE 75
char message[BUF_SIZE] = "Hello!";
bool newMessageAvailable = true;
void printText(uint8_t modStart, uint8_t modEnd, char *pMsg)
// Print the text string to the LED matrix modules specified.
// Message area is padded with blank columns after printing.
{
uint8_t state = 0;
uint8_t curLen;
uint16_t showLen;
uint8_t cBuf[8];
int16_t col = ((modEnd + 1) * COL_SIZE) - 1;
mx.control(modStart, modEnd, MD_MAX72XX::UPDATE, MD_MAX72XX::OFF);
do // finite state machine to print the characters in the space available
{
switch(state)
{
case 0: // Load the next character from the font table
// if we reached end of message, reset the message pointer
if (*pMsg == '\0')
{
showLen = col - (modEnd * COL_SIZE); // padding characters
state = 2;
break;
}
// retrieve the next character form the font file
showLen = mx.getChar(*pMsg++, sizeof(cBuf)/sizeof(cBuf[0]), cBuf);
curLen = 0;
state++;
// !! deliberately fall through to next state to start displaying
case 1: // display the next part of the character
mx.setColumn(col--, cBuf[curLen++]);
// done with font character, now display the space between chars
if (curLen == showLen)
{
showLen = CHAR_SPACING;
state = 2;
}
break;
case 2: // initialize state for displaying empty columns
curLen = 0;
state++;
// fall through
case 3: // display inter-character spacing or end of message padding (blank columns)
mx.setColumn(col--, 0);
curLen++;
if (curLen == showLen)
state = 0;
break;
default:
col = -1; // this definitely ends the do loop
}
} while (col >= (modStart * COL_SIZE));
mx.control(modStart, modEnd, MD_MAX72XX::UPDATE, MD_MAX72XX::ON);
}
void setup() {
mx.begin();
Serial.begin(115200);
Serial.print("\n[MD_MAX72XX Message Display]\nType a message for the display\nEnd message line with a newline");
}
void loop() {
myMessage_SS = "Hello";
//PRINT(myMessage_SS,"1");
printText(0, MAX_DEVICES-1, myMessage_SS.c_str());
delay(1000);
//PRINT(myMessage_SS,"2");
myMessage_SS = "World";
printText(0, MAX_DEVICES-1, myMessage_SS.c_str());
delay(1000);
RTC.readTime();
myMessage_SS = RTC.h;
myMessage_SS += ":";
myMessage_SS += RTC.m;
printText(0, MAX_DEVICES-1, myMessage_SS.c_str());
delay(1000);
}
bad power connection. I made a custom UNO board and at the moment of filming it was powered through ICSP header with loose jumper wires from programmer. It has "raspberry pi" DS3231 RTC Either on pins or soldered directly, and CR2032 holder soldered on PCB to keep clock running.
Also has RX/TX pins and other pins available, but mostly why i made this was that i needed a board that can be screwed behind these 1X4 matrices.
Changed it to USB-C power and now running just fine. (C used only for power)
And here is the non-blocking state-machine variant
// Use the MD_MAX72XX library to Print some text on the display
//
// Demonstrates the use of the library to print text.
//
// User can enter text on the serial monitor and this will display as a
// message on the display.
#include <MD_MAX72xx.h>
#include <SPI.h>
#include <MD_DS3231.h>
#include "SafeString.h"
const byte ShowHello = 0;
const byte wait1 = 1;
const byte ShowWorld = 2;
const byte wait2 = 3;
const byte ShowTime = 4;
const byte wait3 = 5;
const char myStateNames[][16] = {
"ShowHello",
"wait1",
"ShowWorld",
"wait2",
"ShowTime",
"wait3"
};
byte myStateVar = ShowHello;
unsigned long myWaitTimer;
cSF(myMessage_SS,8);
#define PRINT(s, v) { Serial.print(F(s)); Serial.print(v); }
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 4
#define CLK_PIN 13 // or SCK
#define DATA_PIN 11 // or MOSI
#define CS_PIN 10 // or SS
// SPI hardware interface
MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary pins
//MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
// Text parameters
#define CHAR_SPACING 1 // pixels between characters
// Global message buffers shared by Serial and Scrolling functions
#define BUF_SIZE 75
char message[BUF_SIZE] = "Hello!";
bool newMessageAvailable = true;
void printText(uint8_t modStart, uint8_t modEnd, char *pMsg)
// Print the text string to the LED matrix modules specified.
// Message area is padded with blank columns after printing.
{
uint8_t state = 0;
uint8_t curLen;
uint16_t showLen;
uint8_t cBuf[8];
int16_t col = ((modEnd + 1) * COL_SIZE) - 1;
mx.control(modStart, modEnd, MD_MAX72XX::UPDATE, MD_MAX72XX::OFF);
do // finite state machine to print the characters in the space available
{
switch(state)
{
case 0: // Load the next character from the font table
// if we reached end of message, reset the message pointer
if (*pMsg == '\0')
{
showLen = col - (modEnd * COL_SIZE); // padding characters
state = 2;
break;
}
// retrieve the next character form the font file
showLen = mx.getChar(*pMsg++, sizeof(cBuf)/sizeof(cBuf[0]), cBuf);
curLen = 0;
state++;
// !! deliberately fall through to next state to start displaying
case 1: // display the next part of the character
mx.setColumn(col--, cBuf[curLen++]);
// done with font character, now display the space between chars
if (curLen == showLen)
{
showLen = CHAR_SPACING;
state = 2;
}
break;
case 2: // initialize state for displaying empty columns
curLen = 0;
state++;
// fall through
case 3: // display inter-character spacing or end of message padding (blank columns)
mx.setColumn(col--, 0);
curLen++;
if (curLen == showLen)
state = 0;
break;
default:
col = -1; // this definitely ends the do loop
}
} while (col >= (modStart * COL_SIZE));
mx.control(modStart, modEnd, MD_MAX72XX::UPDATE, MD_MAX72XX::ON);
}
void setup() {
mx.begin();
Serial.begin(115200);
}
void loop() {
myStateMachine();
}
void myStateMachine() {
printStateOnChange(myStateVar);
switch (myStateVar) {
case ShowHello:
myMessage_SS = "Hello";
printText(0, MAX_DEVICES-1, myMessage_SS.c_str() );
myStateVar = wait1;
break;
case wait1:
if (TimePeriodIsOver(myWaitTimer,1000) ) {
myStateVar = ShowWorld;
}
break;
case ShowWorld:
myMessage_SS = "World";
printText(0, MAX_DEVICES-1, myMessage_SS.c_str() );
myStateVar = wait2;
break;
case wait2:
if (TimePeriodIsOver(myWaitTimer,1000) ) {
myStateVar = ShowTime;
}
break;
case ShowTime:
RTC.readTime();
myMessage_SS = RTC.h;
myMessage_SS += ":";
myMessage_SS += RTC.m;
printText(0, MAX_DEVICES-1, myMessage_SS.c_str() );
myStateVar = wait3;
break;
case wait3:
if (TimePeriodIsOver(myWaitTimer,1000)) {
myStateVar = ShowHello;
}
break;
}
}
// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - startOfPeriod >= TimePeriod ) {
// more time than TimePeriod has elapsed since last time if-condition was true
startOfPeriod = currentMillis; // a new period starts right here so set new starttime
return true;
}
else return false; // actual TimePeriod is NOT yet over
}
void printStateOnChange(byte p_actualState) {
static byte lastState;
if (lastState != p_actualState) {
Serial.print("state changed from ");
Serial.print(myStateNames[lastState]);
Serial.print(" to ");
Serial.print(myStateNames[p_actualState]);
Serial.println();
lastState = p_actualState;
}
}