Best way to send a number of digits to MAX7219

I would be grateful if someone could help me with this problem. I have looked at Arduino + MAX7219 + 6 digit Sevensegment - LEDs and Multiplexing - Arduino Forum and understand the receive part of this.

My question is this. I have a sketch which generates four integers RUNS (3 digits) OVERS (2 digits) WKTS (1 digit) and FIRST (3 digits). What is the best way to transmit these via the NRF24L01 so that I can display them via the MAX7219 ?

Thanks in advance.

Mathew, in the other thread, I asked you to read the forum guidelines. What I should also have asked you to do is to actually follow them. My bad. Please post your schematic, or at least a block diagram, your code so far, if any, links to the components you plan to use, what types of Arduinos you plan to use, how the circuits will be powered and so on.

To answer your question: you must do this via a second Arduino and a second NRF module. The transmitting NRF module cannot talk directly to the max7219. You need a second NRF module to receive the data and a second Arduino to re-format the received data and send it on to the max7219. I expect you will say "I already knew that". But there is no mention of a second Arduino or second NRF module in your post. Do you see why its important to give a fuller explanation of your plan?

Paul, Apologies for my mistakes, I am quite new to this. I do understand the need for 2 Arduinos and 2 NRF Modules.

Sorry I wasn't clear in my explanation.

This is the basic code for reading my button presses and generating the information. This has been tested to the serial monitor and works OK.

/*
  8 Buttons, Low to Switch.

*/

// this constant won't change:
const int  runsbuttonPin = 2;    
const int  oversbuttonPin = 3;   
const int  wktsbuttonPin = 4;    
const int  minusrunsbuttonPin = 5;    
const int  minusoversbuttonPin = 6;    
const int  minuswktsbuttonPin = 14;    
const int  inningsbuttonPin = 15;    
const int  resetbuttonPin = 16;    



// Variables will change:
int runs = 0;   
int runsbuttonState = 1;        
int runslastButtonState = 1;     
int overs = 0;   
int oversbuttonState = 1;         
int overslastButtonState = 1;     

int wkts = 0;   
int wktsbuttonState = 1;         
int wktslastButtonState = 1;     
int firstinnings = 0; 

int minusrunsbuttonState = 1;         
int minusrunslastButtonState = 1;     
int minusoversbuttonState = 1;        
int minusoverslastButtonState = 1;     
int minuswktsbuttonState = 1;         
int minuswktslastButtonState = 1;     
int inningslastButtonState = 1;     
int inningsbuttonState = 1;     
int resetbuttonState = 1;       
int resetlastButtonState = 1;       


void setup() {
  // initialize the button pin as an input:
  pinMode(runsbuttonPin, INPUT);
  pinMode(oversbuttonPin, INPUT);
  pinMode(wktsbuttonPin, INPUT);
  pinMode(minusrunsbuttonPin, INPUT);
  pinMode(minusoversbuttonPin, INPUT);
  pinMode(minuswktsbuttonPin, INPUT);
  pinMode(inningsbuttonPin, INPUT);
  pinMode(resetbuttonPin, INPUT);


  Serial.begin(9600);
}


void loop() {
  // read the pushbutton input pin:
  runsbuttonState = digitalRead(runsbuttonPin);

  // compare the buttonState to its previous state
  if (runsbuttonState != runslastButtonState) {
    // if the state has changed, increment the counter
    if (runsbuttonState == LOW) {
      // if the current state is LOW then the button
      // wend from on to off:
      runs++;
      Serial.println("on");
      Serial.print("runs:  ");
      Serial.println(runs);
    } else {
      // if the current state is HiGH then the button
      // wend from off to on:
      Serial.println("off");
    }
    // Delay a little bit to avoid bouncing
    delay(75);
  }
  // save the current state as the last state,
  //for next time through the loop
  runslastButtonState = runsbuttonState;

  // read the pushbutton input pin:
  minusrunsbuttonState = digitalRead(minusrunsbuttonPin);

  
  if (minusrunsbuttonState != minusrunslastButtonState) {
    
    if (minusrunsbuttonState == LOW) {
      
      runs--;
      Serial.println("on");
      Serial.print("runs:  ");
      Serial.println(runs);
    } else {
      
      Serial.println("off");
    }
   
    delay(75);
  }
  
  minusrunslastButtonState = minusrunsbuttonState;

  
  oversbuttonState = digitalRead(oversbuttonPin);

  
  if (oversbuttonState != overslastButtonState) {
    
    if (oversbuttonState == LOW) {
      
      
      overs++;
      Serial.println("on");
      Serial.print("overs:  ");
      Serial.println(overs);
    } else {
      
      Serial.println("off");
    }
    
    delay(75);

  }
  
  overslastButtonState = oversbuttonState; {


    
    minusoversbuttonState = digitalRead(minusoversbuttonPin);

    
    if (minusoversbuttonState != minusoverslastButtonState) {
      
      if (minusoversbuttonState == LOW) {
        
        overs--;
        Serial.println("on");
        Serial.print("overs:  ");
        Serial.println(overs);
      } else {
        
        Serial.println("off");
      }
      
      delay(75);

    }
    
    minusoverslastButtonState = minusoversbuttonState;

    
    wktsbuttonState = digitalRead(wktsbuttonPin);

    
    if (wktsbuttonState != wktslastButtonState) {
     
      if (wktsbuttonState == LOW) {
        
        wkts++;
        Serial.println("on");
        Serial.print("wkts:  ");
        Serial.println(wkts);
      } else {
        
        Serial.println("off");
      }
      
      delay(75);
    }
    
    wktslastButtonState = wktsbuttonState;

    
    minuswktsbuttonState = digitalRead(minuswktsbuttonPin);

    
    if (minuswktsbuttonState != minuswktslastButtonState) {
      
      if (minuswktsbuttonState == LOW) {
        
        wkts--;
        Serial.println("on");
        Serial.print("wkts:  ");
        Serial.println(wkts);
      } else {
        
        Serial.println("off");
      }
      
    }
    
    inningsbuttonState = digitalRead(inningsbuttonPin);
    
    if (inningsbuttonState != inningslastButtonState) {
      
      if (inningsbuttonState == LOW) {
        
        firstinnings = runs;
        Serial.println("on");
        Serial.print("Innings Ended Total =   ");
        Serial.println(firstinnings);
        runs = 0;
        overs = 0;
        wkts = 0;
        Serial.print("runs = ");
        Serial.println(runs);
        Serial.print("overs = ");
        Serial.println(overs);
        Serial.print("wkts = ");
        Serial.println(wkts);




      } else {
        
        Serial.println("off");
      }
      
      delay(75);

    }
    // read the pushbutton input pin:
    resetbuttonState = digitalRead(resetbuttonPin);
    // compare the buttonState to its previous state
    if (resetbuttonState != resetlastButtonState) {
      // if the state has changed, increment the counter
      if (resetbuttonState == LOW) {
        // if the current state is HIGH then the button
        // wend from off to on:

        Serial.println("on");
        Serial.print("Reset   ");
        Serial.println(firstinnings);
        runs = 0;
        overs = 0;
        wkts = 0;
        firstinnings = 0;
        Serial.print("runs = ");
        Serial.println(runs);
        Serial.print("overs = ");
        Serial.println(overs);
        Serial.print("wkts = ");
        Serial.println(wkts);

        Serial.print("innings = ");
        Serial.println(firstinnings);




      } else {
        
        Serial.println("off");
      }
      
      delay(75);



    }
  }
}

From the other thread I have modified the code for the receiver as follows

#include <LedControl.h>
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(7, 8); // CE, CSN
const byte address[6] = "00001";

/* 
 * Now we create a new LedControl. 
 * We use pins 6,5 and 4 on the Arduino for the SPI interface
 * Pin 6 is connected to the DATA IN-pin of the first MAX7221
 * Pin 5 is connected to the CLK-pin of the first MAX7221
 * Pin 4 is connected to the LOAD(/CS)-pin of the first MAX7221   
  
 */
LedControl lc1=LedControl(6,5,4,2); 

unsigned long delaytime=500;


void setup() {
  //wake up the MAX72XX from power-saving mode 
   lc1.shutdown(0,false);
    lc1.shutdown(1,false);
    
   //set brightness for the Leds
   lc1.setIntensity(0,15);
   lc1.setIntensity(1,15);
   lc1.setScanLimit(0, 6);
   lc1.setScanLimit(1, 3);

   //and clear the display
   lc1.clearDisplay (0);   
   lc1.clearDisplay (1);   
   
}void loop() {

  if (Serial.available() >= 9) {
   
    lc1.setDigit(0, 5, Serial.read(), false);
    lc1.setDigit(0, 4, Serial.read(), false);
    lc1.setDigit(0, 3, Serial.read(), false);
    lc1.setDigit(0, 2, Serial.read(), false);
    lc1.setDigit(0, 1, Serial.read(), false);
    lc1.setDigit(0, 0, Serial.read(), false);
   
    lc1.setDigit(1, 2, Serial.read(), false);
    lc1.setDigit(1, 1, Serial.read(), false);
    lc1.setDigit(1, 0, Serial.read(), false);

   
  }
}

In the other thread, you mention sending the data as AAAAAVVVVVHHHIII, in my instance this would be something like RRRWOOFFF, where RRR = runs, W =wkts, OO =overs, FFF = firstinnings.

My question is how to convert the four separate integers into this string for transmission.

I hope this is clearer and do appreciate your time in trying to help me.

Mike.

Apologies for calling you Matthew, Mike! Not sure where that came from.

That first sketch does not even seem to use the nrf libraries. Suggest you work on that first before you worry too much about data formats. Have you managed to get the two Arduinos to exchange any messages over RF yet? The secret to getting Arduino stuff to work is to take small steps. Use the example sketches that come with the various libraries to check that you have the hardware wired up correctly and working.

Paul,

Many thanks, I have made some progress. I proved radio comms with a simple "Hello World" sketch.

I then loaded my transmitter with the following.

/*
     Arduino Wireless Communication Tutorial
         Example 1 - Transmitter Code

     by Dejan Nedelkovski, www.HowToMechatronics.com

     Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
*/
#include <nRF24L01.h>
    #include <printf.h>
    #include <RF24.h>
    #include <RF24_config.h>
    #include <SPI.h>
    
RF24 radio(7, 8); // CE, CSN
const byte address[6] = "00001";

/*
  8 Buttons, Low to Switch.

*/

// this constant won't change:
const int  runsbuttonPin = 2;    // the pin that the pushbutton is attached to
const int  oversbuttonPin = 3;    
const int  wktsbuttonPin = 4;    
const int  minusrunsbuttonPin = 5;    
const int  minusoversbuttonPin = 6;    
const int  minuswktsbuttonPin = 14;    
const int  inningsbuttonPin = 15;    
const int  resetbuttonPin = 16;    
// Variables will change:
int runs = 0;   // counter for the number of button presses
int runsbuttonState = 1;         // current state of the button
int runslastButtonState = 1;     // previous state of the button
int overs = 0;   
int oversbuttonState = 1;         
int overslastButtonState = 1;     

int wkts = 0;   
int wktsbuttonState = 1;         
int wktslastButtonState = 1;     /
int firstinnings = 0; // First Innings score

int minusrunsbuttonState = 1;         
int minusrunslastButtonState = 1;     
int minusoversbuttonState = 1;         
int minusoverslastButtonState = 1;     
int minuswktsbuttonState = 1;         
int minuswktslastButtonState = 1;     
int inningslastButtonState = 1;     
int inningsbuttonState = 1;     
int resetbuttonState = 1;       
int resetlastButtonState = 1;
       
void setup() {

  // initialize the button pin as an input:
  pinMode(runsbuttonPin, INPUT);
  pinMode(oversbuttonPin, INPUT);
  pinMode(wktsbuttonPin, INPUT);
  pinMode(minusrunsbuttonPin, INPUT);
  pinMode(minusoversbuttonPin, INPUT);
  pinMode(minuswktsbuttonPin, INPUT);
  pinMode(inningsbuttonPin, INPUT);
  pinMode(resetbuttonPin, INPUT);

  radio.begin();
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();
  
}

void loop() {
  

  // read the runs input pin:
  runsbuttonState = digitalRead(runsbuttonPin);

  // compare the buttonState to its previous state
  if (runsbuttonState != runslastButtonState) {
    // if the state has changed, increment the counter
    if (runsbuttonState == LOW) {
      // if the current state is LOW then the button
      // wend from on to off:
      runs++;
      
      delay (10);
    } else {
      // if the current state is HiGH then the button
      // wend from off to on:
      // // Serial.println("off");
    }
    // Delay a little bit to avoid bouncing
    delay(75);
  }
  // save the current state as the last state,
  //for next time through the loop
  runslastButtonState = runsbuttonState;

  
  minusrunsbuttonState = digitalRead(minusrunsbuttonPin);

  
  if (minusrunsbuttonState != minusrunslastButtonState) {
    
    if (minusrunsbuttonState == LOW) {
      
      runs--;

      delay (10);
    } else {
      
    }
    
    delay(75);
  }
 
  minusrunslastButtonState = minusrunsbuttonState;

  
  oversbuttonState = digitalRead(oversbuttonPin);

  
  if (oversbuttonState != overslastButtonState) {
    
    if (oversbuttonState == LOW) {
      
      overs++;

      if (overs >99)
      overs = 99;

      delay (10);
    } else {
      
    }
    // Delay a little bit to avoid bouncing
    delay(75);

  }
 
  overslastButtonState = oversbuttonState; {


  
    minusoversbuttonState = digitalRead(minusoversbuttonPin);

    
    if (minusoversbuttonState != minusoverslastButtonState) {
      
      if (minusoversbuttonState == LOW) {
        
        overs--;

        delay (10);
      } else {
       
      }
      
      delay(75);

    }
    
    minusoverslastButtonState = minusoversbuttonState;

    
    wktsbuttonState = digitalRead(wktsbuttonPin);

    
    if (wktsbuttonState != wktslastButtonState) {
      
      if (wktsbuttonState == LOW) {
       
        wkts++;

        if (wkts > 9)
        wkts = 9; 

        

        delay (10);
      } else {
        
      }
      
      delay(75);
    }
    
    wktslastButtonState = wktsbuttonState;

    
    minuswktsbuttonState = digitalRead(minuswktsbuttonPin);

    
    if (minuswktsbuttonState != minuswktslastButtonState) {
      
      if (minuswktsbuttonState == LOW) {
        
        wkts--;

        delay (10);
      } else {
       
      }
      
      delay(75);
    }
    
    inningsbuttonState = digitalRead(inningsbuttonPin);
    
    if (inningsbuttonState != inningslastButtonState) {
      
      if (inningsbuttonState == LOW) {
        
        firstinnings = runs;
        runs = 0;
        overs = 0;
        wkts = 0;

        delay (10);

      } else {
        
      }
      
      delay(500);

    }
    
    resetbuttonState = digitalRead(resetbuttonPin);
    
    if (resetbuttonState != resetlastButtonState) {
      
      if (resetbuttonState == LOW) {
        
        runs = 0;
        overs = 0;
        wkts = 0;
        firstinnings = 0;

        delay (10);
        
      } else {
        
      }
      
      delay(75);
    }
   
    char cruns [4];
    sprintf(cruns, "%03d", runs);

    char cwkts [2];
    sprintf(cwkts, "%01d", wkts);

    char covers [3];
    sprintf(covers, "%02d", overs);

    char cinnings [4];
    sprintf (cinnings, "%03d", firstinnings);

       String StringRuns = String(cruns);
    String StringWkts = String(cwkts);
    String StringOvers = String(covers);
    String StringInnings = String (cinnings);
    String Output = String (StringRuns + StringWkts + StringOvers + StringInnings);


      char charBuf [Output.length() + 1] ; // charBuf is the array we send by radio

    Output.toCharArray(charBuf, Output.length() + 1);

    radio.write(&charBuf, sizeof(charBuf));


    delay(500);


  }
}

With my test receiver connected to my laptop via USB, I successfully printed the string of 9 digits on the serial monitor.

Next step is to transmit to my MAX7219 circuit which I have tested with a sketch that just cycles the digits.

Good progress. I can suggest an improvement to make that code shorter, simpler to understand and more efficient:

This part

   char cruns [4];
    sprintf(cruns, "%03d", runs);

    char cwkts [2];
    sprintf(cwkts, "%01d", wkts);

    char covers [3];
    sprintf(covers, "%02d", overs);

    char cinnings [4];
    sprintf (cinnings, "%03d", firstinnings);

       String StringRuns = String(cruns);
    String StringWkts = String(cwkts);
    String StringOvers = String(covers);
    String StringInnings = String (cinnings);
    String Output = String (StringRuns + StringWkts + StringOvers + StringInnings);


      char charBuf [Output.length() + 1] ; // charBuf is the array we send by radio

    Output.toCharArray(charBuf, Output.length() + 1);

becomes

   char charBuf [10] ; // charBuf is the array we send by radio
    sprintf(charBuf, "%03d%01d%02d%03d", runs, wkts, overs, firstinnings);

This reduces the memory use from

Sketch uses 7,234 bytes (23%) of program storage space. Maximum is 30,720 bytes.
Global variables use 267 bytes (13%) of dynamic memory, leaving 1,781 bytes for local variables. Maximum is 2,048 bytes.

to

Sketch uses 5,438 bytes (17%) of program storage space. Maximum is 30,720 bytes.
Global variables use 259 bytes (12%) of dynamic memory, leaving 1,789 bytes for local variables. Maximum is 2,048 bytes.

This is because using the String class is very inefficient, and in this case, no benefit.

Sounds like you are almost there. The Led control library has a function to "print" an ASCII character, and the data arrives from the radio module like that, so the last steps should be simple.

Thanks I will give that a try.

Paul,

Thanks for that suggestion to shorten the code. That works well.

I am now stuck on how to transform the information received by the radio to the set digit commands. This code works to print the received data on the serial monitor. What is the best way to extract the correct digits to send to the MAX7219?

#include <SPI.h>
    #include <nRF24L01.h>
    #include <printf.h>
    #include <RF24.h>
    #include <RF24_config.h>
    #include <LedControl.h>
RF24 radio(7, 8); // CE, CSN
const byte address[6] = "00001";

/* 
 * Now we create a new LedControl. 
 * We use pins 6,5 and 4 on the Arduino for the SPI interface
 * Pin 6 is connected to the DATA IN-pin of the first MAX7221
 * Pin 5 is connected to the CLK-pin of the first MAX7221
 * Pin 4 is connected to the LOAD(/CS)-pin of the first MAX7221   
  
 */
LedControl lc1 = LedControl(6,5,4,2); 

unsigned long delaytime=500;


void setup() {
  //wake up the MAX72XX from power-saving mode 
   lc1.shutdown(0,false);
    lc1.shutdown(1,false);
    
   //set brightness for the Leds
   lc1.setIntensity(0,15);
   lc1.setIntensity(1,15);
   lc1.setScanLimit(0, 6);
   lc1.setScanLimit(1, 3);

   //and clear the display
   lc1.clearDisplay (0);   
   lc1.clearDisplay (1);  

    //initialise serial:
    Serial.begin (9600);
    radio.begin();
      radio.openReadingPipe(0, address);
      radio.setPALevel(RF24_PA_LOW);
      radio.startListening();
   
}void loop() {

  if (radio.available() ) {
char text[32] = "";
radio.read (&text, sizeof(text));

Serial.println (text);
  }
}

The command I was alluding to in my last post was

lc1.setChar(addr,digit,value.dp)

That accepts an ASCII character, so no need to do any conversions. But it only prints a single character, so you will need to repeat it for each character/digit, or use a little for() loop.

More Success!

I added the following code to the end of the previous and it works.

String Input = (text);

char runshundred = Input.charAt(0);
char runsten = Input.charAt(1);
char runsunit = Input.charAt(2);
char wktsunit = Input.charAt(3);
char oversten = Input.charAt (4);
char oversunit = Input.charAt (5);
char firsthundred = Input.charAt (6);
char firstten = Input.charAt (7);
char firstunit = Input.charAt (8);

  
    lc1.setChar(0, 5, (oversunit), false);
    lc1.setChar(0, 4, (oversten), false);
    lc1.setChar(0, 3, (wktsunit), false);
    lc1.setChar(0, 2, (runsunit), false);
    lc1.setChar(0, 1, (runsten), false);
    lc1.setChar(0, 0, (runshundred), false);
   
    lc1.setChar(1, 2, (firstunit), false);
    lc1.setChar(1, 1, (firstten), false);
    lc1.setChar(1, 0, (firsthundred), false);
  
  }
}

I expect there is a better way of doing it, but at least this works.

I still have a bit more work to do, so may have more questions. Thanks so far for your help.

mwtheplumber:
I expect there is a better way of doing it, but at least this works.

Great to hear you got it working!

Last time you used String class, tried to show you that by doing that you had made the code longer, less readable, less efficient, and to no benefit. Do you need a little more convincing?

Paul,

I am always willing to learn. At my age sometimes it takes a while to grasp things :slight_smile:

Any suggestions welcome.

If you want to be really short:

    for (int i = 0; i < 9; i++) {
      lc1.setChar(i / 6, i % 6, text[i], false);
    }

but its a bit cryptic!

A little longer but perhaps easier for a beginner to understand:

    lc1.setChar(0, 5, text[5], false);
    lc1.setChar(0, 4, text[4], false);
    lc1.setChar(0, 3, text[3], false);
    lc1.setChar(0, 2, text[2], false);
    lc1.setChar(0, 1, text[1], false);
    lc1.setChar(0, 0, text[0], false);
    lc1.setChar(1, 2, text[8], false);
    lc1.setChar(1, 1, text[7], false);
    lc1.setChar(1, 0, text[6], false);

Did you know that a single max7219 can drive 9 digits? There is a little hack you can do.

Normally, up to 8 digits of common cathode displays are used with max7219. But if you are not using the decimal points, you can connect a single common anode digit as well.

    byte extraDigit = pgm_read_byte_near(charTable + (byte) text[8]);

    for (int i = 0; i < 8; i++) {
      lc1.setChar(0, i, text[i], bitRead(extraDigit, i));
    }

(untested!)

Paul, Now I think I understand, I can use the text[x] directly into the setChar statement. That makes sense.

My next task is to blank leading zeroes, I am thinking that by changing the leading zero to an ASCII 0, this would send a blank space to the led control.

Will let you know ho I get on.

sprintf(charBuf, "%3d%1d%2d%3d", runs, wkts, overs, firstinnings);

The "0"s that were in the format string before were causing the leading zeros. Without them, you get leading spaces.

Brilliant, thanks. I can see I have a lot to learn. Each bit of progress brings a feeling of satisfaction.

mwtheplumber:
I would be grateful if someone could help me with this problem. I have looked at Arduino + MAX7219 + 6 digit Sevensegment - LEDs and Multiplexing - Arduino Forum and understand the receive part of this.

My question is this. I have a sketch which generates four integers RUNS (3 digits) OVERS (2 digits) WKTS (1 digit) and FIRST (3 digits). What is the best way to transmit these via the NRF24L01 so that I can display them via the MAX7219 ?

Thanks in advance.

Just use google