Painel led 8x8 com max7912

Boas,

Estou com alguma dificuldade em fazer um código para ter um painel led com 3 mensagens, accionadas por um botão.

Consegui visualizar uma mensagem no painel, agora precisava incorporar um botão para aparecer novas mensagens (3 no mínimo).

Agradecia uma ajudinha…

O meu código:

#include <MD_MAX72xx.h>
#include <SPI.h>

#define USE_POT_CONTROL 1
#define PRINT_CALLBACK  0

#define PRINT(s, v) { Serial.print(F(s)); Serial.print(v); }


#define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 8

        
#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  50  // 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
char curMessage[BUF_SIZE];
char newMessage[BUF_SIZE];
bool newMessageAvailable = false;

uint16_t  scrollDelay;  // in milliseconds

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 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 char   *p = curMessage;
  static uint8_t  state = 0;
  static uint8_t  curLen, showLen;
  static uint8_t  cBuf[8];
  uint8_t colData;

  // finite state machine to control what we do on the callback
  switch(state)
  {
    case 0: // Load the next character from the font table
      showLen = mx.getChar(*p++, sizeof(cBuf)/sizeof(cBuf[0]), cBuf);
      curLen = 0;
      state++;

      // if we reached end of message, reset the message pointer
      if (*p == '\0')
      {
        p = curMessage;     // reset the pointer to start of message
        if (newMessageAvailable)  // there is a new message waiting
        {
          strcpy(curMessage, newMessage); // copy it in
          newMessageAvailable = false;
        }
      }
      // !! deliberately fall through to next state to start displaying

    case 1: // display the next part of the character
      colData = cBuf[curLen++];
      if (curLen == showLen)
      {
        showLen = CHAR_SPACING;
        curLen = 0;
        state = 2;
      }
      break;

    case 2: // display inter-character spacing (blank column)
      colData = 0;
      if (curLen == showLen)
        state = 0;
      curLen++;
      break;

    default:
      state = 0;
  }

  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::TSR);  // 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()
{
  mx.begin();
  mx.setShiftDataInCallback(scrollDataSource);
  mx.setShiftDataOutCallback(scrollDataSink);

#if USE_POT_CONTROL
  pinMode(SPEED_IN, INPUT);
#else
  scrollDelay = SCROLL_DELAY;
#endif

  strcpy(curMessage, " ChiPDouro  **  Fechado   **  ");
  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();
}

Hello,

I have some difficulty making a code to have a led panel with 3 messages, triggered by a button.

I was able to view a message in the panel, now I needed to incorporate a button to appear new messages (minimum 3).

I would appreciate a little help …

This example you used allows you to enter the message from the serial monitor. You can enter as many as you like.

If you want to select from 3 predefined messages, then you will need to do wht following:

  1. when the switch is pressed, set the new message in the same buffer as the the serial message is being placed.
  2. Set the global variable to tell the main that a new message is available.

The rest of the code will work as it does now.

Hello

Thanks for the tip, since I'm very beginner to Arduino programming, would it be possible to help me in building the code? Please!

marco_c:
This example you used allows you to enter the message from the serial monitor. You can enter as many as you like.

If you want to select from 3 predefined messages, then you will need to do wht following:

  1. when the switch is pressed, set the new message in the same buffer as the the serial message is being placed.
  2. Set the global variable to tell the main that a new message is available.

The rest of the code will work as it does now.

Hello

Thanks for the tip, since I'm very beginner to Arduino programming, would it be possible to help me in building the code? Please!

I guess you should show what you have done so far that is not just the example program from the library.

In case you have not done anything then I would suggest that you start with a simple sketch that just prints 3 different messages to the serial monitor when you press a switch. This will inform you about reading a switch and how to keep track of what messages need to be printed. The easier example is better to learn from, without complication of using the MD_MAX72xx library.

marco_c:
I guess you should show what you have done so far that is not just the example program from the library.

In case you have not done anything then I would suggest that you start with a simple sketch that just prints 3 different messages to the serial monitor when you press a switch. This will inform you about reading a switch and how to keep track of what messages need to be printed. The easier example is better to learn from, without complication of using the MD_MAX72xx library.

Hello

I’ve been adapting the example to what I want, but I just can’t get the paneling to appear correctly.
I don’t know where the problem is.
The message appears from left to right in a mirror and what I wanted was from right to left (TSR) … where did I go wrong, here my code:

#include <MD_MAX72xx.h>
#include <SPI.h>

#include <MD_UISwitch.h>

#define PRINT(s, v)   { Serial.print(F(s)); Serial.print(v); }       
#define PRINTC(s, v)  { Serial.print(F(s)); Serial.print((char)v); }  
#define PRINTS(s)     { Serial.print(F(s)); } 
//--------------------                        
#define PRINT(s, v)   
#define PRINTC(s, v)  
#define PRINTS(s)     

// --------------------
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW // modulo usado
#define MAX_DEVICES 8 // numero de modulos

// pin no arduino para o clk, din, cs do mudulo (max72xx)
#define CLK_PIN   13  // CLK
#define DATA_PIN  11  // DIN
#define CS_PIN    10  // CS

MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);                     
//MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES); 

// --------------------
// Mode keyswitch parameters and object
//
#define MODE_SWITCH 9 // Digital Pin

MD_UISwitch_Digital  ks = MD_UISwitch_Digital(MODE_SWITCH, LOW);

// --------------------
// Constantes
//milliseconds
#define UNIT_DELAY      25
#define SCROLL_DELAY    (5 * UNIT_DELAY)

#define CHAR_SPACING     1  
#define BUF_SIZE        75  

// ========== General Variables ===========
//
uint32_t prevTime = 10;    

// ========== Text routines ===========
//
// Tabela de Texto
char *msgTab[] =
{
  " CHIPDOURO ** Aberto ** ",
  " ENCERRADO ",
  " FECHADO ",
  " VOLTO JA",
  " Estamos de ferias",
  " Em remodelacao ",
};

bool scrollText(bool bInit, char *pmsg)

{
  static char   curMessage[BUF_SIZE];
  static char   *p = curMessage;
  static uint8_t  state = 0;
  static uint8_t  curLen, showLen;
  static uint8_t  cBuf[8];
  uint8_t         colData;

   if (bInit)
  {
    PRINTS("\n--- Initializing ScrollText");
    resetMatrix();
    strcpy(curMessage, pmsg);
    state = 0;
    p = curMessage;
    bInit = false;
  }

 
  if (millis()-prevTime < SCROLL_DELAY)
  
    return(bInit);

 
  mx.transform(MD_MAX72XX::TSL);  //Scroll da esquerda para a direita, texto em espelho
  //mx.transform(MD_MAX72XX::TSR); //apenas liga a 1 coluna do 1 modulo.
  
  prevTime = millis();       

  PRINT("\nScroll FSM S:", state);
  switch (state)
  {
    case 0: // Load the next character from the font table
      PRINTC("\nLoading ", *p);
      showLen = mx.getChar(*p++, sizeof(cBuf)/sizeof(cBuf[0]), cBuf);
      curLen = 0;
      state = 1;

    case 1: 
      colData = cBuf[curLen++];
      mx.setColumn(0, colData);
      if (curLen == showLen)
      {
        showLen = ((*p != '\0') ? CHAR_SPACING : mx.getColumnCount()-1);
        curLen = 0;
        state = 2;
      }
      break;

    case 2: 
      mx.setColumn(0, 0);
      if (++curLen == showLen)
      {
        state = 0;
        bInit = (*p == '\0');
      }
      break;

    default:
      state = 0;
  }

  return(bInit);
}

// ========== Control routines ===========
//
void resetMatrix(void)
{
  mx.control(MD_MAX72XX::INTENSITY, MAX_INTENSITY/10);
  mx.control(MD_MAX72XX::UPDATE, MD_MAX72XX::ON);
  mx.clear();
  prevTime = 0;
}

void runMatrixAnimation(void)

{
  static  uint8_t state = 0;
  static  uint8_t mesg = 0;
  static  boolean bRestart = true;
 static boolean bInMessages = false;
  boolean changeState = false;

  changeState = (ks.read() == MD_UISwitch::KEY_PRESS);

  if (changeState)
  {
    if (bInMessages) 
    {
      mesg++;
      if (mesg >= sizeof(msgTab)/sizeof(msgTab[0]))
      {
        mesg = 0;
     bInMessages = false;
        state++;
      }
    }
    else
      state++;

    bRestart = true;
  };
 
  switch(state)
  {
    case  0: bInMessages = true; bRestart = scrollText(bRestart, msgTab[mesg]); break;
    
    default: state = 0;
  }
}

void setup()
{
  mx.begin();
  prevTime = millis();

  ks.begin();

  Serial.begin(57600);

  PRINTS("\n[MD_MAX72XX codigo]");
}

void loop()
{
  runMatrixAnimation();
}

I would appreciate a little help …

So this is now a completely different code from what you had in the first post?

but I just can't get the paneling to appear correctly

I do not understand this? What is paneling (a translation issue, perhaps) and what is not appearing correctly? What do you expect to see and what do you see?

The logic in runMatrixAnimation() makes no sense. I think you have taken bits from other code without really understanding what they do compared to what you are trying to achieve.

What I would expect to see in runMatrixAnimation() is in 2 parts:

  1. If the switch is pressed change the message number (mesg) to the next one.
  2. If the message is larger than the maximum message, then set it to 0 to start again.
  3. Set a flag for the next part of the program (bRestart) to indicate that it needs to change message.

then in the second part ALWAYS
4. Call scrollText() to animate the text.

bRestart does not need to be static, but it needs to be initialised to false every time.

state is not needed, InMessages is not needed.