Max7219 behaves strange when resetting arduino

Hi!

I’m building a wack-a-mole game with arduino and inorder to keep track of the score I made the decision to use two seven segment displays. These have a forward voltage per segment of 7.2v and draw 10mA of current per segment, so I use highside drivers to supply the displays with the necessary voltage. This seems to work just fine but whenever I upload code to the arduino (or when I reset it or unplug power to it), the max 7219 behaves in a “strange” way. Most of the time the displays flickers and display two 8’s (with low brightness) and on rare occasions, the program actually works. It’s hard to describe with words, so I created this video:

As you can see, sometimes the screen freezes and i’m unsure of what is causing it. Here is the code the arduino is running in the video. It’s just some test counter to see if the circuit works or not.

#include <SPI.h>
#define CSpin 40


void setup() {
  SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
  digitalWrite(CSpin, HIGH);
  pinMode(CSpin, OUTPUT);
  SPI.begin();


  digitalWrite(CSpin, LOW);//come out of shutdown
  SPI.transfer(0x0C);
  SPI.transfer(0x01);
  digitalWrite(CSpin, HIGH);

  digitalWrite(CSpin, LOW);//decode 8 digits
  SPI.transfer(0x09);
  SPI.transfer(0xFF);
  digitalWrite(CSpin, HIGH);

  for (int i = 1; i < 9; i++) {//set all digits OFF
    digitalWrite(CSpin, LOW);
    SPI.transfer(i);
    SPI.transfer(0x0F);
    digitalWrite(CSpin, HIGH);
  }

  digitalWrite(CSpin, LOW);//intensity MAX
  SPI.transfer(0x0A);
  SPI.transfer(0x0F);
  digitalWrite(CSpin, HIGH);

  digitalWrite(CSpin, LOW);//scan limit 
  SPI.transfer(0x0B);
  SPI.transfer(0x01);
  digitalWrite(CSpin, HIGH);
  SPI.endTransaction ();
}

void loop() {
  SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
  for (byte num = 0; num < 10; num++) {
    for (byte i = 1; i < 3; i++) {
      digitalWrite(CSpin, LOW);
      SPI.transfer(i);
      SPI.transfer(num);
      digitalWrite(CSpin, HIGH);
      delay(1);
    }
    delay(500);
  }
  SPI.endTransaction ();
}

The circuit itself is connected as the attached schematic below suggests. However I have not connected the pushbuttons and leds for the buttons to the breadboard as i’m testing the displays right now. I have read other forum threads about max7219s behaving in weird ways, but thus far I have not found a thread where the problem matches what i’m experiencing. Some have suggested putting a 100uF, 10uF and a 0.1uF capacitors across the max7219 Vcc and ground to smooth out ripple in the supply voltage. I have done this, but it makes no difference.

Here are some things I have thought of which are probably unrelated to this (but might be worth mentioning). I accidently applied 12v to pin 52 (SCK) or 51 (MOSI), can’t remember which, but it probably caused some damage. But why does the arduino still work if thats the case? I have also noticed that whenever I connect the arduino to usb port (while leaving the rest of the circuit unpowerd), there is 4.5v ~between the Vin pin and ground. The voltage regulator (U4 in the schematic) that is connected to these pins gets hot, which doesn’t make sense. Is it pushing current through the output of the voltage regulator that normally powers it?

Any help would be massively appreciated!

Jesper

In your initialisation, write a zero to the 'Display Test' register (0x0F) to get it out of Display Test mode and into Normal Operation mode.

It’s certainly possible that only part of the ATmega chip was damaged by the 12V, associated with just that pin, or the whole port or the SPI circuits. The rest of the chip could still appear to working fine.

The circuit itself is connected as the attached schematic below suggests.

Wow, you seem to have made life really hard for yourself with your component choices. How much are you willing to change things to simplify the circuit?

Looks like your 7 seg displays are common cathode? Common anode is much easier to deal with for >5V forward voltages. Would that be a possibility?

The other 8 LEDs: why are you not running them from the max chip?

Those MOSFETs look overkill for your needs. They could handle 10A easily, you only need 1/1000 of that.

In your setup() code, you are sending data using the SPI without calling beginTransaction() first. (You only call it in loop()). Will you use SPI to communicate with any other chips in this project? If not, just call beginTransaction() after SPI.begin() in setup() and don’t bother with endTransaction().

Hi Paul!

I originally bought the max7219 and the displays (common cathode) unaware of the fact that the IC could not output more than 5v from the segment drivers, so I had to cobble together a solution with the components I had already bought.

The mosfets were the cheapest I could find here in sweden (5.5kr/piece~0.6 dollars/piece), but they are indeed overkill.

The other eight leds are apart of a dome pushbutton set, and i figured I would use the max chip to run the display and the arduino to turn those leds on and off. Haven't really thought another solution yet. Althought they are supposed to run of 12v (the led comes with some current limiting resitor from the factory) so I don't know how that would work. That part of the circuit is more of a placeholder than anything else, I don't think I would need the transistors even.

But to answer your question, I would gladly simplify the design if it's possible.

Hi Jobi Wan!
Your suggestion worked! (or so it seems rigth now) Now the displays only flicker when starting the arduino and when I press the reset button, but the randomness of the displays working or not is gone. Although I stumbled upon another issue.

Whenever I try to write two different numbers on the display, lets say the 2 and 3 for example, “leftover” segments are dimly lit while the correct segments are lit as they should.

I wrote this code in the loop to display the example numbers (#2 on digit 1 and #3 on digit 2). I have attatched a image of what it looks like for me.

 SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
  digitalWrite(CSpin, LOW);
  SPI.transfer (0x01);
  SPI.transfer(B00000010); 
  digitalWrite(CSpin, HIGH);
  digitalWrite(CSpin, LOW);
  SPI.transfer (0x02);
  SPI.transfer(B00000011); 
  digitalWrite(CSpin, HIGH);
  SPI.endTransaction ();

Do you think there is something wrong with the code, or is it hardware related?

That is 'ghosting'. In this case, it's not the code. The MAX7219 takes care of the multiplexing.

I think the problem is that you don't switch your MOSFETs fast enough. When a segment pin goes high, you pull the gate low pretty hard, but when the segment pin goes low again, the gate has to recharge through 10kΩ. This leaves the segment on for a while while the next digit is already active.

It may help but probably not enough to lower those 10k resistors to (say) 2k. Using smaller MOSFETs with less gate capacitance could help. You could look at source driver chips like TD62783.

If you're going to swap out components anyway, then this might be a good point to see what PaulRB had in mind.

I don’t think I would need the transistors even.

With 12V LEDs (meaning LEDs with built-in series resistors designed for 12V supply) if you connect them between an Arduino output and ground, they will be very dim. If you connect them between 12V and an Arduino pin, you will damage the Arduino. You need a driver transistor between the Arduino output and the led so that the pin is not exposed to 12V. But what I was trying to explain is that you could connect these 8 LEDs to the max chip as though they were another digit. You already have the high-side driver transistors for that.

I don’t think the OP is interested in how I would have designed the circuit. I can usually tell. If I ask questions and they go unanswered, I take that to mean “thanks, but I’m ok”.

PaulRB: With 12V LEDs (meaning LEDs with built-in series resistors designed for 12V supply) if you connect them between an Arduino output and ground, they will be very dim. If you connect them between 12V and an Arduino pin, you will damage the Arduino.

Yes your right. My mistake.

you could connect these 8 LEDs to the max chip as though they were another digit. You already have the high-side driver transistors for that.

So I would connect each anode of every led to a segment and connect all the cathodes to digit 3 for example? Right now I only have seven highside drivers because I don't use the decimal. I assume I would have to add another highside driver for that?

Would I have the same problem with ghosting as I do right now on the 7 segment displays if I connected the 8 leds to the max chip?

I don't think the OP is interested in how I would have designed the circuit. I can usually tell. If I ask questions and they go unanswered, I take that to mean "thanks, but I'm ok".

I'm sorry if it came across that way. I'm planning to build 5 games in total, and if I can produce the same game with less complexity, great. How would you design the circuit?

Jobi-Wan: That is 'ghosting'. In this case, it's not the code. The MAX7219 takes care of the multiplexing.

I will change the 10k resistors to see if it helps. This might be a bandaid fix, but could you add a delay in the code so you give the mosfets more time to recharge the gate?

I'll read about the source driver chip you mentioned and look into getting smaller mosfets.

If you're going to swap out components anyway, then this might be a good point to see what PaulRB had in mind.

Yep

If you want to avoid adding an 8th transistor, you could add 7 LEDs to digit3 and one to digit4. I guess you will get the ghosting effect until you find a way to fix that. No code change will help fix the ghosting because all the multiplex timing is done by the max chip and the Arduino cannot affect it.

I would design the circuit using some common anode displays. I would drive them, and the other LEDs, with tpic6c595 or tpic6b595 (whichever is cheaper) shift registers. Although this would require 3 chips rather than one, no transistors would be needed, so there would be far fewer components in total. Also, the LEDs can be brighter, since no multiplexing is going on.

Pull-up resistors for the switches are not needed if the Arduino's internal pull-ups are used.

It may be that neither voltage regulator is needed. The Arduino's built-in regulator is susceptible to overheating if powered by 12V and large currents are drawn at 5V from it. But in your circuit, all the large currents are drawn from the 12V supply, so very little more than what is needed by the Arduino itself, so overheating should not be a problem.

JesperB:
… but could you add a delay in the code so you give the mosfets more time to recharge the gate?

No, the MAX7219 does the multiplexing. You have no influence on the frequency or dead time.

Here is an idea, although probably wasteful and not very elegant:

In your init, you write 1 to the scan limit register, so you only scan the first 2 digits (0 and 1). You could scan 4 digits (0,1,2,3), and connect your displays to 0 and 2 or to 1 and 3, two that are not next to each other, and make sure all segments are off for the digits in between.

If/when you want to add your other LEDs to the MAX7219, you can do the same thing: Set the scan limit to scan all digits, but use only the even (or only the odd) ones.

This will of course make your displays appear less bright.

Paul, your solution seems better than what I have at the moment. Just by quickly looking through the sites where I source my components, your circuit would cost less which would be great. Plus I wouldn't have to deal with the multiplexing for the displays. I'll try to redesign the circuit and post it here later.

Jobi-Wan I tried your suggestion about the resistors, and it worked quite well but I can still see some ghosting. I’ll try the circuit idea from PaulRB since it should solve this problem aswell.

I have attached an image where all but one of the 10k resitors in the highside drivers are replaced with 2k ones, too see the difference in ghosting side by side. It’s hard to tell on the image but it certainly made a difference.

Another thought: if you want to use your existing common cathode displays, here are two possible ways:

  • Use mic5981 chips, one per digit. Like tpic6c595 but can drive common cathode. Difficult to find.
  • Use 74hc595 + udn2981 to drive each digit. Easier to find, but two chips for each digit.

Hi Paul!
I just finished the schematic for the circuit with three tpic6b595 and common anode displays. I have attatched it below.

Am I correct in thinking I would have to clock 24bits to the shift registers, and then pull RCK (latch) high to display the new information (when numbers on the display changes or when I need to update leds D1-D9) everytime I need to update any data on the displays/leds?

One final note on the new circuit design. I read online that you could “daisy chain” buttons with resistors and connect all of them to one analog input on the arduino (and use analogRead () to differentiat between them) to save pins for other uses. Do you think this is a good idea?

PaulRB:
Another thought: if you want to use your existing common cathode displays, here are two possible ways:

  • Use mic5981 chips, one per digit. Like tpic6c595 but can drive common cathode. Difficult to find.
  • Use 74hc595 + udn2981 to drive each digit. Easier to find, but two chips for each digit.

I’ll look into this if the circuit above doesn’t work. Right now the tpic solution seems like a good choice.

|500x376

Looks pretty good. Thought you had forgotten the series resistors for the LEDs until I noticed the note at the bottom. It's normal to draw the series resistors in on a schematic, even if you don't need to add them as extra components in reality.

You should always put a 0.1uF ceramic decoupling cap physically near the power pins of each chip (between 5V and ground). The Nano has them on-board already.

Also at least one electrolyitc cap, e.g. 470uF, to stabilise the power when LEDs switch on and off, would be wise. As the LEDs are all powered from 12V, this cap should be between 12V and ground and rated for at least 18V.

All these caps can be shown anywhere you like on the schematic, of course. The point of a schematic is that components can be placed in whatever arrangement makes the circuit easy to read and understand, and does not have to represent the physical layout of the actual components.

Your resistor ladder idea should be ok as long as two buttons will never be pressed at once. But I guess the player will only have one mole-whacking hammer. Another way to read the buttons would be with a 74hc164 parallel-in-serial-out shift register. Connect this to the same SCK & LATCH lines as the tpic chips and connect the serial-out pin to MISO pin on the Nano. You can then read the buttons while simultaneously updating the LEDs & displays.

What you have not mentioned yet is how the moles pop up. Solenoids? Servos?

PaulRB:
What you have not mentioned yet is how the moles pop up. Solenoids? Servos?

Sadly, it is not quite that elegant. The pushbuttons with the integrated LEDs simply light up. And no hammer is used. :astonished:

Paul__B: Sadly, it is not quite that elegant. The pushbuttons with the integrated LEDs simply light up. And no hammer is used. :astonished:

Yes your right. The player simply presses buttons that light up to play the game. Not as fun I suppose, but it will do for now. I think it would be fun to play though if I do some clever coding which influence the way players interact with the game. Maybe I can create a better verison in the future.

As for what you mentioned PaulRB, I will make sure to add those components to the schematic so I do things the right way.

PaulRB: Your resistor ladder idea should be ok as long as two buttons will never be pressed at once. But I guess the player will only have one mole-whacking hammer.

I did not realise this. Thanks for saving me some headache haha. I had originally planned for the players to start the game by pressing any two buttons simultaneously, but this will not work I now realize. I will either go the route you mentioned with the PISO shift register, or just connect them like I did before, since I still have pins left on the arduino. Since the latter costs less, I think I will do it that way.

It is possible to make a resistor ladder that can recognise multiple pressed at once. It involves using pairs of resistors with values R and 2R, for example 1K and 2K, and the buttons need to be SPDT, not just SPST. In other words, the buttons need to have 3 pins (normally closed, normally open and common), not just 2.

R2r-netzwerk.png

I'll save that schematic incase I have a shortage of pins. I actually could use it since my "buttons" are limit switches. Also, I have ordered all of the parts now.

Thanks alot for all the guidance and help PaulRB and Jobi-Wan.