Arduino + MAX7219 + 6 digit Sevensegment

For my B777 Homecockpit i want to build the displays of my MCP with Arduino Mega and the MAX7219 shift registers. Each shift register controls a six-digit seven-segment display with common cathode.

Seeking a Arduino sketch that reads the values from the serial port and outputs to the respective seven-segment displays. Unfortunately I have not found on the various websites Arduino, this helps me. I dont want to use a system like MobiFlight.

I am a newbie Arduino, but have 30 years Basic / VisaulBasic experience.

The shift registers I have from the LED matrix kit

I have this code snippet found

I understand this correctly, that the digits starting from the right are? If I want to drive on the 2nd shift register the 2nd digit with "7" I have to write?

lc.setDigit(0,7,12,true);

Hi,

No, I think that is wrong. If you read this page, it says that the parameters are setDigit(address, digit, value, dp). "address" is the number of the chip, "digit" is the digit controlled by that chip and "value" is the numeral to be displayed. So your example should be:

lc.setDigit(1,1,7,false);

(remember that counts usually start from zero in C and Arduino)

Note also that the library assumes you will connect 8 digits to each chip. Because you are only connecting 6 digit displays, you can make them a little brighter by setting the "scan limit" to 6 for each chip.

for (byte i = 0; i < 4; i++) lc.setScanLimit(i, 5);

You say that digits "starting on the right are". That is only true if you wire them up that way. You can chose to wire them up left-to-right or right-to-left.

Paul

Thanks for the quick response, which helps me a lot.

Can I declare the value as a variable? The value to be read via COM.

Would that be so possible? I have read 4 values (numbers) and spend each of the numbers on a LED block:

void loop() {
.....
while (Serial.available() > 0) {

int ALT= Serial.read();

lc.setDigit(0,1,ALT,false);

int VS= Serial.read();

lc.setDigit(1,1,VS,false);

.....

Skino:
Thanks for the quick response, which helps me a lot.

Can I declare the value as a variable? The value to be read via COM.

Would that be so possible? I have read 4 values (numbers) and spend each of the numbers on a LED block:

void loop() {
.....
while (Serial.available() > 0) {

int ALT= Serial.read();

lc.setDigit(0,1,ALT,false);

int VS= Serial.read();

lc.setDigit(1,1,VS,false);

.....

Hi Skino, first of all please start using code tags when you post any code. Its the </> icon.

What you describe is almost correct, but a little more complicated. Each value read from serial must be broken down into decimal digits. However, it is possible that this breaking down has already been done for you, if the value arrives as separate digits, in ASCII form, from the serial line.

Serial.Read() will read one byte (0..255) or one ASCII character from the serial line. Your "ALT" value may arrive in one of two ways; binary encoded as 2, 3, or 4 bytes which must be combined into an int or long int, or as a series of ASCII characters, e.g. "1", "0", "0", "0", "0".

Before we can help with the code to display the ALT value on your led displays, we will need to know which format the data arrives in. Can you tell us?

Paul

The variables are created from my VB program and can both integer (4 bytes) or ASCI format have. There are 4 values for the 4 displays. Only numbers from 0 to a maximum of 40000. Only the 2nd display goes from - 5000 to 5000.

So... which will it be, 4-byte integers or ASCII strings?

ASCII please :slight_smile:

The ASCII string must contain the values for all 4 Displays and will be "distributed" on the 4 Displays?

Peter
http://boefb.webnode.com/

OK Peter,

Can you get your VB code to send 16 digits like this:

AAAAAVVVVVHHHIII

Where A = ALT, V=VERT SPD, H=HDG, I=IAS/MACH ?

If so, it should be easy to convert each ASCII digit to binary to be sent to a specific digit on a specific display:

// Send digits to ALT display
lc.setDigit(0,0,Serial.read() - '0',false);
lc.setDigit(0,1,Serial.read() - '0',false);
lc.setDigit(0,2,Serial.read() - '0',false);
lc.setDigit(0,3,Serial.read() - '0',false);
lc.setDigit(0,4,Serial.read() - '0',false);

// Send digits to VERT SPD display
lc.setDigit(1,0,Serial.read() - '0',false);
lc.setDigit(1,1,Serial.read() - '0',false);
lc.setDigit(1,2,Serial.read() - '0',false);
lc.setDigit(1,3,Serial.read() - '0',false);
lc.setDigit(1,4,Serial.read() - '0',false);

// Send digits to HDG display
lc.setDigit(2,0,Serial.read() - '0',false);
lc.setDigit(2,1,Serial.read() - '0',false);
lc.setDigit(2,2,Serial.read() - '0',false);

// Send digits to IAS/MACH display
lc.setDigit(3,0,Serial.read() - '0',false);
lc.setDigit(3,1,Serial.read() - '0',false);
lc.setDigit(3,2,Serial.read() - '0',false);

It seems to me that if your displays have only 16 digits between them, you should only need 2 x max7219 to drive them, because each max chip can drive 8 digits. On your 6-digit displays, you do not have to connect up all 6 digits. You could drive ALT and HDG with one max chip, and VERT SPD and IAS/MACH with the second max chip. If you can make your displays by combining 3-digit and 2-digit displays of identical colour (wavelength) and size, you can avoid having "wasted" digits.

Also a Mega is overkill for this - you could just use a Nano 3 for example.

That's perfect. Many Thanks. That really really helps me.

One more question. The V-value cut be 3. 4 or 5 digits. Can I turn off the unneeded Digits or do I need them with "0" padding?

Peter
http://boefb.webnode.com/

For that code I just gave, the data will need zero padding on the left of each value.

OK no problem. Many Thanks. Because certainly come even more questions when I've built everything. Promise .... :wink:

2 small problems:
Can I turn off/on a 7-segment block without the other blocks to influence them? In the AAAAAVVVVVHHHIII - String VVVVV is often turned off, so there is no indication.

Second question, I can change the brightness of the display via code?

Peter
http://boefb.webnode.com/

Yes and yes.

Here is a link to the LedControl library with a description of all the functions.

An alternative to setDigit() is setCharacter() which understands '0' to '9' and ' ' (space) so if you can get your vb code to output spaces when VERT SPD is not displayed, then the Arduino code is easy.

This works perfectly. Once again thank you for the fast and competent help.

Peter
http://boefb.webnode.com/

I have a timing problem with the code below.

#include "LedControl.h"

/*
 Now we need a LedControl to work with.
 ***** These pin numbers will probably not work with your hardware *****
 pin 12 is connected to the DataIn
 pin 11 is connected to the CLK
 pin 10 is connected to LOAD
 We have only a single MAX72XX.
 */
LedControl lc = LedControl(12, 11, 10, 4);

/* we always wait a bit between updates of the display */
unsigned long delaytime = 500;

void setup() {
  // initialize serial:
  Serial.begin(9600);
  /*
   The MAX72XX is in power-saving mode on startup,
   we have to do a wakeup call
   */
  lc.shutdown(0, false);
  lc.shutdown(1, false);
  lc.shutdown(2, false);
  lc.shutdown(3, false);
  
  /* Set the brightness to a medium values */
  lc.setIntensity(0, 5);
  lc.setIntensity(1, 5);
  lc.setIntensity(2, 5);
  lc.setIntensity(3, 5);
  
  /* and clear the display */
  lc.clearDisplay(0);
  lc.clearDisplay(1);
  lc.clearDisplay(2);
  lc.clearDisplay(3);
}


void loop() {

  if (Serial.available() > 0) {

  }
 Serial.flush();
  
  delay(600);
  
  lc.setDigit(0, 4, Serial.read() - '0', false);
  lc.setDigit(0, 3, Serial.read() - '0', false);
  lc.setDigit(0, 2, Serial.read() - '0', false);
  lc.setDigit(0, 1, Serial.read() - '0', false);
  lc.setDigit(0, 0, Serial.read() - '0', false);

  lc.setDigit(1, 4, Serial.read() - '0', false);
  lc.setDigit(1, 3, Serial.read() - '0', false);
  lc.setDigit(1, 2, Serial.read() - '0', false);
  lc.setDigit(1, 1, Serial.read() - '0', false);
  lc.setDigit(1, 0, Serial.read() - '0', false);

//  lc.setDigit(2, 4, Serial.read() - '0', false);
//  lc.setDigit(2, 3, Serial.read() - '0', false);
  lc.setDigit(2, 2, Serial.read() - '0', false);
  lc.setDigit(2, 1, Serial.read() - '0', false);
  lc.setDigit(2, 0, Serial.read() - '0', false);

  //  lc.setDigit(3, 4, Serial.read() - '0', false);
//  lc.setDigit(3, 3, Serial.read() - '0', false);
  lc.setDigit(3, 2, Serial.read() - '0', false);
  lc.setDigit(3, 1, Serial.read() - '0', false);
  lc.setDigit(3, 0, Serial.read() - '0', false);
}

When I send the string (in the form 1111122222333444 , numbers only) only once everything works without problems. Even if I send the code every few seconds everything is ok.
But I send him 2x per second get confused the numbers. I want as the last character Attach a "Z" or "*" and read only until then. I tried this code snippet. He shows no errors, but does not work either. The display is still messed up

while (Serial.available() > 0)
    {
        char recieved = Serial.read();
        inData += recieved; 

        // Process message when new line character is recieved
        if (recieved == 'Z')
        {
               // Get the code for displaying the values

            inData = ""; // Clear recieved buffer
        }

How do I solve this, which are always exactly read the 16 characters?

LCDemo7Segment.ino (2.01 KB)

Does this work well enough?

#include "LedControl.h"

/*
 Now we need a LedControl to work with.
 ***** These pin numbers will probably not work with your hardware *****
 pin 12 is connected to the DataIn
 pin 11 is connected to the CLK
 pin 10 is connected to LOAD
 We have only a single MAX72XX.
 */
LedControl lc = LedControl(12, 11, 10, 4);

/* we always wait a bit between updates of the display */
unsigned long delaytime = 500;

void setup() {
  // initialize serial:
  Serial.begin(9600);
  /*
   The MAX72XX is in power-saving mode on startup,
   we have to do a wakeup call
   */
  lc.shutdown(0, false);
  lc.shutdown(1, false);
  lc.shutdown(2, false);
  lc.shutdown(3, false);

  /* Set the brightness to a medium values */
  lc.setIntensity(0, 5);
  lc.setIntensity(1, 5);
  lc.setIntensity(2, 5);
  lc.setIntensity(3, 5);

  /* and clear the display */
  lc.clearDisplay(0);
  lc.clearDisplay(1);
  lc.clearDisplay(2);
  lc.clearDisplay(3);
}


void loop() {

  if (Serial.available() >= 16) {
    
    lc.setDigit(0, 4, Serial.read() - '0', false);
    lc.setDigit(0, 3, Serial.read() - '0', false);
    lc.setDigit(0, 2, Serial.read() - '0', false);
    lc.setDigit(0, 1, Serial.read() - '0', false);
    lc.setDigit(0, 0, Serial.read() - '0', false);

    lc.setDigit(1, 4, Serial.read() - '0', false);
    lc.setDigit(1, 3, Serial.read() - '0', false);
    lc.setDigit(1, 2, Serial.read() - '0', false);
    lc.setDigit(1, 1, Serial.read() - '0', false);
    lc.setDigit(1, 0, Serial.read() - '0', false);

    //  lc.setDigit(2, 4, Serial.read() - '0', false);
    //  lc.setDigit(2, 3, Serial.read() - '0', false);
    lc.setDigit(2, 2, Serial.read() - '0', false);
    lc.setDigit(2, 1, Serial.read() - '0', false);
    lc.setDigit(2, 0, Serial.read() - '0', false);

    //  lc.setDigit(3, 4, Serial.read() - '0', false);
    //  lc.setDigit(3, 3, Serial.read() - '0', false);
    lc.setDigit(3, 2, Serial.read() - '0', false);
    lc.setDigit(3, 1, Serial.read() - '0', false);
    lc.setDigit(3, 0, Serial.read() - '0', false);
  }
}

If not, try this:

#include "LedControl.h"

/*
 Now we need a LedControl to work with.
 ***** These pin numbers will probably not work with your hardware *****
 pin 12 is connected to the DataIn
 pin 11 is connected to the CLK
 pin 10 is connected to LOAD
 We have only a single MAX72XX.
 */
LedControl lc = LedControl(12, 11, 10, 4);

/* we always wait a bit between updates of the display */
unsigned long lastReceived = 0;
int prevAvailable = 0;

void setup() {
  // initialize serial:
  Serial.begin(9600);
  /*
   The MAX72XX is in power-saving mode on startup,
   we have to do a wakeup call
   */
  lc.shutdown(0, false);
  lc.shutdown(1, false);
  lc.shutdown(2, false);
  lc.shutdown(3, false);

  /* Set the brightness to a medium values */
  lc.setIntensity(0, 5);
  lc.setIntensity(1, 5);
  lc.setIntensity(2, 5);
  lc.setIntensity(3, 5);

  /* and clear the display */
  lc.clearDisplay(0);
  lc.clearDisplay(1);
  lc.clearDisplay(2);
  lc.clearDisplay(3);
}


void loop() {

  unsigned long timeNow = millis();
  int availableNow = Serial.available();
  
  if (availableNow > 0) {
    
    //We have received some characters
    if (availableNow < 16) {
      
      //We have not received all characters yet
      if (availableNow > prevAvailable) {
        
        //We have received more characters than last time we checked
        prevAvailable = availableNow;
        //Note time of last receipt
        lastReceived = timeNow;
      }
      else if (timeNow - lastReceived > 250) {
        
        //We have not received any more characters in quite a long time
        //We must have missed the first part of the message, so ignore what we received
        Serial.flush();
        prevAvailable = 0;
      }
    }
    else {

      //We have now received all characters, update the displays
      
      lc.setDigit(0, 4, Serial.read() - '0', false);
      lc.setDigit(0, 3, Serial.read() - '0', false);
      lc.setDigit(0, 2, Serial.read() - '0', false);
      lc.setDigit(0, 1, Serial.read() - '0', false);
      lc.setDigit(0, 0, Serial.read() - '0', false);
  
      lc.setDigit(1, 4, Serial.read() - '0', false);
      lc.setDigit(1, 3, Serial.read() - '0', false);
      lc.setDigit(1, 2, Serial.read() - '0', false);
      lc.setDigit(1, 1, Serial.read() - '0', false);
      lc.setDigit(1, 0, Serial.read() - '0', false);
  
      //  lc.setDigit(2, 4, Serial.read() - '0', false);
      //  lc.setDigit(2, 3, Serial.read() - '0', false);
      lc.setDigit(2, 2, Serial.read() - '0', false);
      lc.setDigit(2, 1, Serial.read() - '0', false);
      lc.setDigit(2, 0, Serial.read() - '0', false);
  
      //  lc.setDigit(3, 4, Serial.read() - '0', false);
      //  lc.setDigit(3, 3, Serial.read() - '0', false);
      lc.setDigit(3, 2, Serial.read() - '0', false);
      lc.setDigit(3, 1, Serial.read() - '0', false);
      lc.setDigit(3, 0, Serial.read() - '0', false);

      //Discard any extra characters received
      Serial.flush();
      prevAvailable = 0;
    }
  }
}

Thank you Paul, I'll try both versions and then inform yourself :slight_smile:

Have Version 1 in use and it works perfectly. :slight_smile: Thank you so much for the expert assistance.

A small problem yet with setChar:It will be displayed only digits. The "-" unfortunately not. Spaces are accepted, however, so I'm going on the leading zeros.

 lc.setChar(1, 4, Serial.read() - '0', false);
    lc.setChar(1, 3, Serial.read() - '0', false);
    lc.setChar(1, 2, Serial.read() - '0', false);
    lc.setChar(1, 1, Serial.read() - '0', false);
    lc.setChar(1, 0, Serial.read() - '0', false);

How can I show the "-" ?

If you are using setChar() instead of setDigit(), you should remove the

- '0'

after each use of Serial.read(). You could make that change for your whole sketch.

setDigit() expects an integer value, which is why we had to subtract the ASCII code for zero, so that the character '7' becomes the value 7, for example.

setChar() expects a character code, and should work with '0' to '9' and space and '-' and many other codes. See this page.