Max7219 led driver goes blank after a few hours.

Hi,

I'm using a Max7219 to drive, 8 seven segment LEDs, using the Ledcontrol library.

Initially everything works fine, but after a few hours the display goes completely blank, I,e all LEDs go off.

However if I reset the Arduino, which re initialises the 7219, its instantly fine again.

The program has not stopped running when the display is blank, as I can still see it sending debug to the PC, every 2 secs, when it updates the temperature being shown on the led display.

I'm contemplating sending the shutdown False command to the display each time before I update the digits, but this seems like its a bit if a hack and that there is possibly another problem.

I have tried 2 displays and they are both virtually the same, well, one fails before the other, but the both fail.

Could it be supply noise that is somehow crashing the 7219?

Has anyone had similar experiences

Are there any solutions

Btw. The hardware is a nano running from 5v USB PSU, or from a PC.

Thanks

Have not seen that happen with my MAX7219s. Perhaps you have counterfeit parts that are less than durable? Where did you get them? Any chance they are overheating? What is the resistor used for current selection, and what brightness level are you selecting? Easy test would be to lower the brightness level via software, see if that helps.

Obvious approach - swap MAX7219s (obviously, you would have more than one! I just received a new batch yesterday, will have to a} test them, b} actually use some or at least check out that other fellow's code with three 7-segment displays).

If the same thing happens, it is probably RAM saturation in the Arduino.

I'm not sure if you put in any bypassing on that but if you didn't I'd try a .1uF ceramic and a 10uF electrolytic per driver IC and see if it helps.

The counterfeit MAX7219 parts do have problems. The most obvious I have seen is they are not that great in long chains - they lose their marbles sometimes in a way that is rather like what you are describing, but usually faster, once the chain gets too long. I've kept mine to like 6 and they work pretty well. Considering how much less expensive those ICs are I think I will keep on using them until I find a cheap uC with constant current ports and higher drive that I can make into my own driver. Anyone know a part like that? Too bad the tiny88 isn't like that, it would be almost ideal.

I'm not sure if you put in any bypassing on that but if you didn't I'd try a .1uF ceramic and a 10uF electrolytic per driver IC and see if it helps.

This would be my guess also. Keep things short and close.

Thanks

Devices were from eBay, part of an 8 digit ( 2 x 4 digit) module. They could well be fakes. I wasn't aware that this was a possibility.

Intensity was set to 8 which is probably maximum.

I will try to half this

I will add a smoothing cap

I also changed my code to send the init stuff each time e.g set intensity and clear display.

I will see if any of these changes fixes the problem

Cheers

Intensity goes from 0 to F. 8 is the middle.

What Current Set resistor are you using: Selecting RSET Resistor and Using External Drivers The current per segment is approximately 100 times the current in ISET. To select RSET, see Table 11. The MAX7219/MAX7221’s maximum recommended segment current is 40mA.

0.1uF and 10uF cap on VCC should be considered mandatory:

Supply Bypassing and Wiring To minimize power-supply ripple due to the peak digit driver currents, connect a 10μF electrolytic and a 0.1μF ceramic capacitor between V+ and GND as close to the device as possible. The MAX7219/MAX7221 should be placed in close proximity to the LED display, and connections should be kept as short as possible to minimize the effects of wiring inductance and electromagnetic interference. Also, both GND pins must be connected to ground.

Thanks @Crossroads

I'm using one of these http://www.ebay.com/itm/2PCS-MAX7219-EWG-8-Digit-Digital-Tube-Display-Control-Module-Red-for-arduino-M61-/291266763006?pt=LH_DefaultDomain_0&hash=item43d0da18fe

Looking at the board it has a 10uF on the top side.

Underneath there is a 1k surface mount resistor (though I'd need to use a continuity tester to work out what its connected to), there is also one other SM capacitor, but again, I don't know what its connected to

The chip has MAXIM written on it, but its probably a clone.

The 7219 is very close to the LED's so I don't think thats the issue.

I had quite long wires, 30cm between the display and the Arduino, but i have shortened them to 10cm, but I'm not sure if that would be the issue as the data rate appears to be around 50khz

Its possible that electrical noise from switching on of flourscent lighting switching on and off, is somehow getting in, and also there is the possibility of electrical noise from a big solar inverter (4kW) and various other bits of electrical equipment.

I could also have a dodgy connection, as I've noticed that when I test another of these modules by plugging pins into a Uno (the other board is soldered to a nano), that as soon as there is a glitch in the data flow, that the display stays in an incorrect state.

i.e things somehow get out of sync

Hence a "belt and braces" approach of sending the commands to wake etc, are probably necessary, as this is intended to be left going all the time to measure temperature on a hot water tank and a solar water panel

Anyway, thanks for all your help....

I have one on order, to check out a problem someone else had here - in a few weeks, I will be in a position to try it out. ;D

The [u]10k[/u] resistor is the current programming resistor for the MAX7219 (pin 18) while the 10µF and 100nF capacitors are bypass.

What concerns me is to which side of D1, the reverse-polarity protection diode, the "VCC" on the output side connects. It should connect directly to "VCC" on the input side of the board, so that the diode isolates only the local chip. Otherwise there is going to be a big problem in chaining boards.

It was unclear when you originally stated you had tried two displays, whether you had in fact swapped MAX7219 chips. As it appears you indeed did because they are integral to the display, I would now be strongly favouring a code problem.

Which again proves the rule - only when you provide full information, is it possible to provide sensible answers. :D

I bought some MAX7219s from the same vendor (G&C) like a year ago and they were all fakes. And I've got a lot of random shutdown problems with them.

The fakes have different packaging as the real ones. You can see the differences here: http://tronixstuff.com/2013/05/16/the-max7219-led-display-controller-real-or-fake/

@paulB

I agree, it's probably best to bypass the diode

I have made the code changes to set shutdown to false and clear the display before I update with the new digits, and I will run this for at least a week to see if it is a workaround on these probable fake chips

@petri

What length of wire did you use between the Arduino and the display. These chips seem sensitive to long wires e.g 50 in bundles of cables, possibly due to crosstalk

Thanks

Roger

rogerClark: What length of wire did you use between the Arduino and the display. These chips seem sensitive to long wires e.g 50 in bundles of cables, possibly due to crosstalk

It's been some time but I think I built it on a breadboard and used "standard" (about 10cm?) jumper wires. It's possible that it's more robust when built on a PCB but I haven't tested it. You could try lowering the SPI bitrate to something really low and see if it helps.

Just shorting the wires helped a lot. I checked the clock rate and its around 50khz as the library I'm using uses shifOut not true SPI

Anyway, I'll keep experimenting

OK, I have bought one of those - from the same supplier - to test it out. (Just one display.)

It has been running with no problem for about 48 hours on my “standard” matrix exercise. I have just adapted a simple test code specifically for this particular sort of display and will run it another 48 hours. You might care to try my test code and see if your display gives the same problems with this particular code.

Note - no libraries in use other than the stock IDE.

/* Loop scanner demonstration
Code for max 7219 from maxim, reduced & optimised for using multiple 7219 cascaded.
______________________________________

General notes: 

- if using only one max7219, then use maxSingle function to control
the module --- maxSingle(register (1-8), column (0-255))

- if using more then one max7219, and all should work the same, use maxAll
function --- maxAll(register (1-8), collum (0-255))

- if using more than one max7219 and want to change something on one module only,
then use maxOne function 
--- maxOne(module you want to control [1=first], register [1-8], column [0-255])

 During initiation, be sure to send every part to every max7219 and then upload it.
For example, if you have five max7219's, you have to send the scanLimit 5 times
before you load it, otherwise not every max7219 will get the data. the (fixed)
variable maxInUse keeps track of this, just tell it how many max7219 you are using.
*/

int dataIn = 2;            // "DIN" on module
int load = 3;              // "CS" on module
int clock = 4;             // "CLK" on module
const int ledPin =  13;    // LED pin number

int maxInUse = 1;          // set how many MAX7219's used
int ledState = LOW;        // initialise the LED

int e = 0;                 // just a varialble

// define max7219 registers
byte max7219_reg_noop        = 0x00;
byte max7219_reg_digit0      = 0x01;
byte max7219_reg_digit1      = 0x02;
byte max7219_reg_digit2      = 0x03;
byte max7219_reg_digit3      = 0x04;
byte max7219_reg_digit4      = 0x05;
byte max7219_reg_digit5      = 0x06;
byte max7219_reg_digit6      = 0x07;
byte max7219_reg_digit7      = 0x08;
byte max7219_reg_decodeMode  = 0x09;
byte max7219_reg_intensity   = 0x0a;
byte max7219_reg_scanLimit   = 0x0b;
byte max7219_reg_shutdown    = 0x0c;
byte max7219_reg_displayTest = 0x0f;


void putByte(byte data) {
  byte i = 8;
  byte mask;
  while(i > 0) {
    mask = 0x01 << (i - 1);      // get bitmask
    digitalWrite( clock, LOW);   // tick
    if (data & mask) {           // choose bit
      digitalWrite(dataIn, HIGH);// send 1
    } else {
      digitalWrite(dataIn, LOW); // send 0
    }
    digitalWrite(clock, HIGH);   // tock
    --i;                         // move to lesser bit
  }
}

// maxSingle is the "easy" function to use for a single max7219
void maxSingle( byte reg, byte col) {    
  digitalWrite(load, LOW);  // begin     
  putByte(reg);             // specify register
  putByte(col);             //((data & 0x01) * 256) + data >> 1); // put data   
  digitalWrite(load,HIGH); 
}

// initialize all MAX7219's
void maxAll( byte reg, byte col) {
  int c = 0;
  digitalWrite(load, LOW);
  for ( c =1; c<= maxInUse; c++) {
  putByte(reg);             // specify register
  putByte(col);             //((data & 0x01) * 256) + data >> 1); // put data
    }
  digitalWrite(load,HIGH);
}

// for adressing different MAX7219's while cascaded
void maxOne(byte maxNr, byte reg, byte col) {    
  int c = 0;
  digitalWrite(load, LOW);  // begin     
  for ( c = maxInUse; c > maxNr; c--) {
    putByte(0);             // no operation
    putByte(0);             // no operation
  }

  putByte(reg);             // specify register
  putByte(col);             //((data & 0x01) * 256) + data >> 1); // put data 

  for ( c = maxNr-1; c >= 1; c--) {
    putByte(0);             // no operation
    putByte(0);             // no operation
  }
  digitalWrite(load,HIGH); 
}

void putCol( byte colno, byte coldat) {
// Interprets colno as (zero ref) index in combined array
    byte t;
    t = colno >> 3;
    byte u;
    u = colno & 0x07;
    maxOne(t+1, u+1, coldat);
}


void dispon() {
 maxAll(max7219_reg_shutdown, 0x01);               // Display on
}  

void dispoff() {
 maxAll(max7219_reg_shutdown, 0x00);              // Display off
}  

byte irow = 0;          // Row index
byte icol = 0;          // Column index
byte pattern;           // bit mask
byte lcol;              // left border
byte rcol;              // right border
byte trow;              // top seg marker
byte brow;              // bottom seg marker
byte erow;              // past seg marker      

int s_vert;             // Vertical switch
int s_horz;             // Horizontal switch

void worker () {

  if (pattern == 0) {
    pattern = trow;            // pattern must be set
    icol = lcol;
  }
  if (s_vert != 0) {
    if (s_vert == -1) {                     // moving downward
      pattern = pattern >> 1;
      if (pattern == brow) {                   // hit the lower limit
        s_vert = 0; s_horz = -1;
      }
    } else {
      pattern = pattern >> 1;               // moving upward
      if (pattern == erow) {                // hit the upper limit
        s_vert = 0; s_horz = 1;
        pattern = trow;
      }
    }
    putCol(icol,pattern);              // Show the column.
    return;
  }

  if (s_horz != 0) {
    putCol(icol,0);                    // blank previous column.
    if (s_horz == 1) {                     // moving right
      icol--;
      if (icol == rcol) {                      // hit the side
        s_horz = 0; s_vert = -1;
      }
    } else {
      icol++;                               // moving left
      if (icol == lcol) {                      // hit the side
        s_horz = 0; s_vert = 1;
      }
    }
    putCol(icol,pattern);              // Show the column.
  }
 }
  
// the follow variable is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 60;           // interval at which to step (milliseconds)
long previousMillis = 0;      // will store last time LED was updated


void setup () {

  pinMode(dataIn, OUTPUT);
  pinMode(clock,  OUTPUT);
  pinMode(load,   OUTPUT);
  pinMode(ledPin, OUTPUT);      

  //Serial begin(9600);
  digitalWrite(13, HIGH);  

//initiation of the max 7219
  maxAll(max7219_reg_displayTest, 0x00); // no display test
  maxAll(max7219_reg_scanLimit, 0x07);   // all columns in use   
  maxAll(max7219_reg_decodeMode, 0x00);  // using a LED matrix (not digits)
  maxAll(max7219_reg_shutdown, 0x01);    // not in shutdown mode
  for (e=1; e<=8; e++) {                 // empty registers, turn all LEDs off 
    maxAll(e,0);
  }
  maxAll(max7219_reg_intensity, 0x08 & 0x0f);  // middle argument is intensity value
                                               // range: 0x00 to 0x0f
                                                 
  pattern = 0;
  s_vert = 0;
  s_horz = 1;

// define edges of loop
  lcol = 7;              // left border
  rcol = 0;              // right border
  trow = 0x40;           // top seg marker
  brow = 0x08;           // bottom seg marker      
  erow = 0x01;           // past seg marker      
      
}  

void loop () {

  unsigned long currentMillis = millis();
 
// Active waiting for next event
  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) { ledState = HIGH;  } else { ledState = LOW; }
    // Timed process:
    
    worker();

    // set the LED according to ledState:
    digitalWrite(ledPin, ledState);
    }

}

(You can chain multiple displays and change “lcol” to 15, 23 etc.)

Well, I can’t fault my display - moving on to other projects. :smiley:

Initially tried to attach a video of this, but there is a ridiculous restriction of file size (used to be 4 MB). Waste of time.

Never mind - VLC is a wonder!

looper2.mpg (477 KB)

rogerClark: However if I reset the Arduino, which re initialises the 7219, its instantly fine again.

That screams to me "code crash", apparently most commonly according to advice here, RAM allocation overflow. (Stack overflow?)

Yes, the diode is wired wrongly, or at least the output end Vcc comes from the wrong end of the diode. If chaining these, you would need to take the successive Vcc from the input end.

I also have a few of those same MAX7219, with 8 digit display.
I think they are too hot, and then go to off.

Shutdown Mode When the MAX7219 is in shutdown mode, the scan oscillator is halted, all segment current sources are pulled to ground, and all digit drivers are pulled to V+, thereby blanking the display. The MAX7221 is identical, except the drivers are high-impedance. Data in the digit and control registers remains unaltered. Shutdown can be used to save power or as an alarm to flash the display by successively entering and leaving shutdown mode. For minimum supply current in shutdown mode, logic inputs should be at ground or V+ (CMOS-logic levels). Typically, it takes less than 250µs for the MAX7219/ MAX7221 to leave shutdown mode. The display driver can be programmed while in shutdown mode, and shutdown mode can be overridden by the display-test function. Maxim Integ

SEE Table-2 and Table-3 on page 7 for register address map and format info

is there a solution for it?

If they are getting too hot then reduce the current drive by altering the current set resistor.