Max7219 not showing right number

I am working with the display max7219 to driver 8 digits display and when doing a simple counter, the displays jumps for example from 5 to 7 or 1 to 3 . Could not find any pattern.
This is my code

#define MAX7219_DIN 4
#define MAX7219_CS  3
#define MAX7219_CLK 2

int seg=0;

void initialise() {
digitalWrite(MAX7219_CS, HIGH);
pinMode(MAX7219_DIN, OUTPUT);
pinMode(MAX7219_CS, OUTPUT);
pinMode(MAX7219_CLK, OUTPUT);
}

void output(byte address, byte data) {

digitalWrite(MAX7219_CS, LOW);
shiftOut(MAX7219_DIN, MAX7219_CLK, MSBFIRST, address);
shiftOut(MAX7219_DIN, MAX7219_CLK, MSBFIRST, data);
digitalWrite(MAX7219_CS, HIGH);

}

void setup() {          

initialise();
output(0x0f, 0x00); //not test mode 
output(0x0c,0x01); // normal operation
output(0x09,0xff);  // code B decode, ie regular numbers
output (0x0b,0x01); // turn on just 2 digits

}

void loop() {
  seg++;
  if (seg>99)
    seg=0;
  show_digits();
  delay(1000);
}

void show_digits()
{
  int u,t;
  u=seg%10;
  t=(seg/10)%10;
  output (0x01,u); // show units in digit 1
  output (0x02,t); // show tens in digit 2
 
}

Any idea what might be wrong here?

  • I use SPI
#include <SPI.h>

/*
  Arduino pins      MAX7219 pins
  SS     10         LOAD  12
  MOSI   11         DIN   1
  MISO   12         No Connection
  SCK    13         CLK   13
*/

unsigned long TIME                 = 500ul;
char mode;
unsigned long timer1;
byte dp                            = 0;
unsigned long lastmillis           = 0;
unsigned long i                    = 0;

//unsigned long nbr                = 99999999ul;  //(8 digits) largest number before overflow
unsigned long nbr                  = 9999999ul;     //(7 digits) largest number before overflow

//7219 registers               Register addresses
const byte MAX7219_REG_NOOP        = 0x0;
// codes 1 to 8 are the digit positions 1(LSD) to 8(MSD)
const byte MAX7219_REG_DECODEMODE  = 0x9;
const byte MAX7219_REG_INTENSITY   = 0xA;
const byte MAX7219_REG_SCANLIMIT   = 0xB;
const byte MAX7219_REG_SHUTDOWN    = 0xC;
const byte MAX7219_REG_DISPLAYTEST = 0xF;


//****************************************************************
void setup ()
{
  Serial.begin(9600);
  
  pinMode (10, OUTPUT);   //set up SS pin 10
  digitalWrite(10, HIGH); //disable the 7219

  pinMode ( 2, OUTPUT);
 
  //SPI stuff
  SPI.begin ();
  clear7219();

} // end of   setup()


//======================== END OF setup ==========================
void loop ()
{
  //lets do some counting
  if (millis() - timer1 >= TIME)
  {
    timer1 = millis();
    
    i++;
    displayNumber(i);           //display the new number
  }

} //END of   loop()


//================================================================
// function to display up to eight digits on a 7-segment display
void displayNumber( unsigned long myNumber)
{
  unsigned long number = myNumber;
  for (byte digit = 1; digit < 9; digit++)
  {
    byte character = number % 10;  // get the value of the rightmost decade

    //replace leadings 0s with blanks
    if (number == 0 && digit > 0)
    {
      character = 0xF;  //value needed to blank a 7221 digit
    }

    //turn on the decimal point to act as a comma if number is > 999 or >999999
    if ((digit == 7 && myNumber > 999999) || (digit == 4 && myNumber > 999))
    {
      //add a dp
      character |= 0b10000000;
    }

    //if we have overflowed the maximum count turn on all the dp to indicate this
    if (myNumber >= nbr)
    {
      // this adds the dp at overflow
      character |= 0b10000000;
    }

    sendByte (9 - digit, character);
    number = number / 10;            //remove the LSD for the next iteration
  }

} //End of   displayNumber()


//================================================================
// Clear the bubble display
void clear7219()
{
  //SPI.setBitOrder(MSBFIRST);              // MAX7219 requires most signifigant bit first
  sendByte (MAX7219_REG_SCANLIMIT, 7);      // show 8 digits zero relative
  //Change next line to 0xFF from 0x7F if you want all positions to display a number
  sendByte (MAX7219_REG_DECODEMODE, 0xFF);  // in the MSD use bit patterns not digits
  sendByte (MAX7219_REG_DISPLAYTEST, 0);    // no display test
  sendByte (MAX7219_REG_INTENSITY, 0x9);    // character intensity: range: 0 to 15
  sendByte (MAX7219_REG_SHUTDOWN, 1);       // not in shutdown mode (ie. start it up)
  i = 0UL;                                  // clear the digits. Leading 0s will be blanked.
  displayNumber(i);

} //End of   clear7219()


//================================================================
//write a byte to the 7219 register in question
void sendByte (const byte reg, const byte data)
{
  digitalWrite (SS, LOW);  //enable 7219
  SPI.transfer (reg);      //select the 7219 register
  SPI.transfer (data);     //send the data for this register
  digitalWrite (SS, HIGH); //disable 7219

} //End of   sendbyte()


//================================================================


Post a schematic or at least say you have decoupling capacitors deployed.

a7

No capacitor at all . Just arduino Nano powered by USB and display connected to arduino.
But changed my code and use a library that worked great GitHub - ozhantr/DigitLedDisplay: MAX7219/MAX7221 Digital Tube 7-Segment LED Display Arduino Library . The downside is that you can not use the decimal point. So, now working on another one Ledcontrol .
Thanks for the help Alto777 and Larry as well

I don't argue with success, but I do wonder why the library works since at its heart is

	digitalWrite(CS_PIN, LOW);
	shiftOut(DIN_PIN, CLK_PIN, MSBFIRST, address);
	shiftOut(DIN_PIN, CLK_PIN, MSBFIRST, data);
	digitalWrite(CS_PIN, HIGH);

which as far as I can see is identicamal to what you do.

a7

Segment e is bad.

You can learn from the examples:

IDE File menu -> Examples LedController -> LCDemo7Segment

void scrollDigits() {
  for(int i=0; i<13; i++) {
    lc.setDigit(0,3,i,false);

Notice lc.setDigit(0,3,i,false); try change false to true. There's you DP.

Chances that the counting starts to work as well with that example?

Hi @zenonmb ,

And remember the MAX7219 doesn't use the conventional bit position to segment correspondece.
While most seven segments displays are based in the segments sorted as Dp|g|f|e|d|c|b|a, sent MSb or LSb depending of the display controller, the MAX7219 expects the segments to be sent in this sequence: Dp|a|b|c|d|e|f|g MSb. Good reason for a library or oneself to loose the decimal point.

Good Luck!

Gaby.//

I would. That library calls pinMode() and digitalWrite() in the constructor where there is no guarantee the hardware has been properly initialized and/or will be changed by the Arduino framework. Those calls need to be moved to a .begin() method.

I would not use that library

1 Like

What other libraries can you recommend?

you can test my MAX7219 library:

I would use the HW SPI interface on the SPI pins.
My library supports printouts with the common print interface

lc.print("HELP");

Cool, I will. Does it handle colon and degree dots? I got me a 4 digit display to mainly show clock and temperature the old fashioned way.

you can easily print a float and you will get the decimal point at the correct digit.

lc.print(temp, 1); // print a float with one decimal

The degree sign is a printable character and is part of the included font table.

Handling of a colon depends on how it is wired on your display. Is it part of an otherwise used digit or an a separate digit.

Both colon dots and the degree dot counts as one digit.

when you post a link and/or a datasheet of what you have available we can check how to handle them, because usually we see 7 segments and a decimal point per digit...

With LedControl it is addressed as Digit 0 ... 3 and Digit 4 is the colon + degree

It has been a long confusion for me as to what to call this "point" of a 7-segment display unit -- "point" or "dot" or "decimal point"?

Decimal point. Usually referred to as DP

1 Like

Then its straight forward. Use print for the positions 0..3 and set digit for L1 L2 L3. You might need to experiment which bitmap needs to send but basically you can use the same functions as in the older LedControl.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.