Hi! Another topic about MAX7219 matrix panel.
The sketch is "MD_MAX72xx_Message_Serial" from the MD_MAX72xx library, here is also a simulation using Wokwi, in the circuit I added a push button. By default, scrolling message no. 1 is displayed, and I want scrolling message no. 2 to be displayed when I press the button. Basically, when I press the button, the message changes.
I thought that in order to display message no. 2, I can modify the readSerial() function like this:
void readSerial(void)
{
newMessage[BUF_SIZE] = (" Message 2! ");
newMessageAvailable = true;
}
This function appears only twice in the program, once when it is written, and the second time when it is called by the user, but it contains a variable that looks important.
There are two messages to display:
uint8_t curMessage[BUF_SIZE] = { "Message 1! " };
uint8_t newMessage[BUF_SIZE];
"currMessage" is default and is displayed at startup. "newMessage" is the new message taken from Serial Monitor and is entered by the user.
"newMessage" modifies inside the "readSerial()" function.
I thought that this function only has the role of retrieving the new message to be displayed. There is also this variable "newMessageAvailable = true;" which is set when the condition in the if statement is met, and it is the only one which appears elsewhere in the program.
As the second message will be by default, it will not change, I thought of rewriting the "readSerial" function as above, and when I press the button, the function will be called. But nothing is displayed.
What else should I include in the readSerial() function? I think the problem is here. I just think that it is an easier option by which I can insert a second message in the program. I just tried to simplify the function, basically the message is a prescribed one, it is no longer taken from the Serial Monitor.
Complete program:
// Use the MD_MAX72XX library to scroll text on the display
//
// Demonstrates the use of the callback function to control what
// is scrolled on the display text.
//
// User can enter text on the serial monitor and this will display as a
// scrolling message on the display.
// Speed for the display is controlled by a pot on SPEED_IN analog in.
#include <MD_MAX72xx.h>
#include <SPI.h>
#define IMMEDIATE_NEW 0 // if 1 will immediately display a new message
#define USE_POT_CONTROL 1
#define PRINT_CALLBACK 0
#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);
// Scrolling parameters
#if USE_POT_CONTROL
#define SPEED_IN A5
#else
#define SCROLL_DELAY 75 // in milliseconds
#endif // USE_POT_CONTROL
#define CHAR_SPACING 1 // pixels between characters
// Global message buffers shared by Serial and Scrolling functions
#define BUF_SIZE 75
uint8_t curMessage[BUF_SIZE] = { "Message 1! " };
uint8_t newMessage[BUF_SIZE];
bool newMessageAvailable = false;
uint16_t scrollDelay; // in milliseconds
const int buttonPin = 5; // push button is connected to D5
int toggleState = 1;
int lastButtonState = 1;
long unsigned int lastPress;
int debounceTime = 20;
unsigned long previousMillis = 0;
/*void readSerial(void)
{
static uint8_t putIndex = 0;
while (Serial.available())
{
newMessage[putIndex] = (char)Serial.read();
if ((newMessage[putIndex] == '\n') || (putIndex >= BUF_SIZE - 3)) // end of message character or full buffer
{
// put in a message separator and end the string
newMessage[putIndex++] = ' ';
newMessage[putIndex] = '\0';
// restart the index for next filling spree and flag we have a message waiting
putIndex = 0;
newMessageAvailable = true;
}
else if (newMessage[putIndex] != '\r')
// Just save the next char in next location
putIndex++;
}
}*/
void readSerial(void)
{
newMessage[BUF_SIZE] = (" Message 2! ");
newMessageAvailable = true;
}
void scrollDataSink(uint8_t dev, MD_MAX72XX::transformType_t t, uint8_t col)
// Callback function for data that is being scrolled off the display
{
#if PRINT_CALLBACK
Serial.print("\n cb ");
Serial.print(dev);
Serial.print(' ');
Serial.print(t);
Serial.print(' ');
Serial.println(col);
#endif
}
uint8_t scrollDataSource(uint8_t dev, MD_MAX72XX::transformType_t t)
// Callback function for data that is required for scrolling into the display
{
static uint8_t* p = curMessage;
static enum { NEW_MESSAGE, LOAD_CHAR, SHOW_CHAR, BETWEEN_CHAR } state = LOAD_CHAR;
static uint8_t curLen, showLen;
static uint8_t cBuf[15];
uint8_t colData = 0; // blank column is the default
#if IMMEDIATE_NEW
if (newMessageAvailable) // there is a new message waiting
{
state = NEW_MESSAGE;
mx.clear(); // clear the display
}
#endif
// finite state machine to control what we do on the callback
switch (state)
{
case NEW_MESSAGE: // Load the new message
memcpy(curMessage, newMessage, BUF_SIZE); // copy it in
newMessageAvailable = false; // used it!
p = curMessage;
state = LOAD_CHAR;
break;
case LOAD_CHAR: // Load the next character from the font table
showLen = mx.getChar(*p++, sizeof(cBuf) / sizeof(cBuf[0]), cBuf);
curLen = 0;
state = SHOW_CHAR;
// if we reached end of message, opportunity to load the next
if (*p == '\0')
{
p = curMessage; // reset the pointer to start of message
#if !IMMEDIATE_NEW
if (newMessageAvailable) // there is a new message waiting
{
state = NEW_MESSAGE; // we will load it here
break;
}
#endif
}
// !! deliberately fall through to next state to start displaying
case SHOW_CHAR: // display the next part of the character
colData = cBuf[curLen++];
if (curLen == showLen)
{
showLen = CHAR_SPACING;
curLen = 0;
state = BETWEEN_CHAR;
}
break;
case BETWEEN_CHAR: // display inter-character spacing (blank columns)
colData = 0;
curLen++;
if (curLen == showLen)
state = LOAD_CHAR;
break;
default:
state = LOAD_CHAR;
}
return (colData);
}
void scrollText(void)
{
static uint32_t prevTime = 0;
// Is it time to scroll the text?
if (millis() - prevTime >= scrollDelay)
{
mx.transform(MD_MAX72XX::TSL); // scroll along - the callback will load all the data
prevTime = millis(); // starting point for next time
}
}
uint16_t getScrollDelay(void)
{
#if USE_POT_CONTROL
uint16_t t;
t = analogRead(SPEED_IN);
t = map(t, 0, 1023, 25, 250);
return (t);
#else
return (SCROLL_DELAY);
#endif
}
void setup()
{
pinMode(buttonPin, INPUT); // push button as input
mx.begin();
mx.setShiftDataInCallback(scrollDataSource);
mx.setShiftDataOutCallback(scrollDataSink);
#if USE_POT_CONTROL
pinMode(SPEED_IN, INPUT);
#else
scrollDelay = SCROLL_DELAY;
#endif
newMessage[0] = '\0';
Serial.begin(57600);
Serial.print("\n[MD_MAX72XX Message Display]\nType a message for the scrolling display\nEnd message line with a newline");
}
void loop()
{
//scrollDelay = getScrollDelay();
//readSerial();
//scrollText();
int buttonState = digitalRead(buttonPin); //read the state of buttonPin and store it as buttonState (0 or 1)
unsigned long buttonMillis = millis();
if ((buttonMillis - lastPress) > debounceTime) //if the time between the last buttonChange is greater than the debounceTime
{
lastPress = buttonMillis; //update lastPress
if (buttonState == 0 && lastButtonState == 1) //if button is pressed and was released last change
{
toggleState = ! toggleState; //toggle the state
lastButtonState = 0; //record the lastButtonState
}
if (buttonState == 1 && lastButtonState == 0) //if button is not pressed, and was pressed last change
{
lastButtonState = 1; //record the lastButtonState
}
}
// if the button is pressed
if (toggleState == 0)
{
scrollDelay = getScrollDelay();
readSerial();
scrollText();
Serial.println("read");
}
// is hte button was not pressed
if (toggleState == 1)
{
scrollDelay = getScrollDelay();
scrollText();
Serial.println("scroll");
}
} // loop