Arduino Uno R3 runs code and gets stuck in loop()

I have an Arduino Uno R3 with Atmel Atmega328P. It's not original hardware.
I have a 8x8 LED Matrix with a MAX7219 chip. It's a "plug and play" thing module.
I connected the pins correctly to the Arduino:
* Pin 10: Data In
* Pin 9: Clock
* Pin 8: Chip Select/Load

It's the way I initialized it in the code:

// LedControl(int dataPin, int clkPin, int csPin, int numDevices=1);
LedControl lc = LedControl(10, 9, 8, 1);

I am using this library: https://github.com/wayoda/LedControl.
LedControl.h - A library for controling Leds with a MAX7219/MAX7221

Unfortunately the example code for the LCDDemoMatrix.ino code does not execute correctly I think.
It does show the letters one after another and makes LEDS blink. But not like it is programmed. It should light up all LEDs at a certain point. Also it should loop through 4 different functions. The first writes the letters A-R-D-U-I-N-O one after another on the board. The second let's rows blink. The third columns. And the last one should turn on every LED one after another until all of them are turned on.
If I upload the sketch to the arduino, it looks correctly until the function single() lights up only the first row of LEDs, then it jumps to the start of the main loop() function again.
After I let the Arduino run for a while it was stuck at with all LEDs except one turned on. The LEDs didn't change their state anymore. When I upload it again. It gets stuck at just one row of LEDs lit up.

So I stripped it down to this small test:

#include "LedControl.h"

// LedControl(int dataPin, int clkPin, int csPin, int numDevices=1);
LedControl lc = LedControl(10, 9, 8, 1);

unsigned long delaytime = 500;

void setup() {
  // void shutdown(int addr, bool status);
  // If true the device goes into power-down mode. Set to false for normal operation.
  lc.shutdown(0, false);
  lc.setIntensity(0, 8);
  lc.clearDisplay(0);
}

void loop() {
  // void setLed(int addr, int row, int col, boolean state)
  lc.setLed(0, 1, 1, true);
  delay(delaytime);
  lc.clearDisplay(0);
  delay(delaytime);
}

When I upload this sketch, the LED in the second row, second column blinks every 500ms for 500ms.
However after some time the intervals change and the duration where the LED is turned of becomes shorter.

Could it be that the delay() function that is used a lot in this code makes the arduino fail?
Could it also be that my programmer or bootloader or something is broken?
I sometimes have the following error message: avrdude: stk500_recv(): programmer is not responding.
I found a thread where the solution was to change in Tools-Processor-"Atmel 328p (old bootloader)," But there is not processor option for me in the tools submenu.
This is the thread: arduino.stackexchange.

How to debug this? Can I do something with text output to the arduino IDE to check if the delay() function gives me precise intervals?

Could it be the time of the arduino that is not precise?
Could it be the upload process that uploads a 'corrupted' code?
Could it be a wrong configuration?

I'm not so experienced with Arduino, but maybe it's an obvious problem and you can help me.

I am using debian 12 and the Arduino AppImage release.

Version: 2.3.4
Date: 2024-12-03T10:51:12.539Z
CLI Version: 1.1.1

Copyright © 2025 Arduino SA

Thanks for help in advance.

This is the output in the Arduino IDE:

Sketch uses 2566 bytes (7%) of program storage space. Maximum is 32256 bytes.
Global variables use 97 bytes (4%) of dynamic memory, leaving 1951 bytes for local variables. Maximum is 2048 bytes.
"/home/lukas/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" "-C/home/lukas/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" -v -V -patmega328p -carduino "-P/dev/ttyUSB0" -b115200 -D "-Uflash:w:/home/lukas/.cache/arduino/sketches/31F04C9148E6C28C889D8FD2C42B51A9/LCDemoMatrix.ino.hex:i"

avrdude: Version 6.3-20190619
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "/home/lukas/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf"
         User configuration file is "/home/lukas/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : /dev/ttyUSB0
         Using Programmer              : arduino
         Overriding Baud Rate          : 115200
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : Arduino
         Description     : Arduino
         Hardware Version: 3
         Firmware Version: 4.4
         Vtarget         : 0.3 V
         Varef           : 0.3 V
         Oscillator      : 28.800 kHz
         SCK period      : 3.3 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: reading input file "/home/lukas/.cache/arduino/sketches/31F04C9148E6C28C889D8FD2C42B51A9/LCDemoMatrix.ino.hex"
avrdude: writing flash (2566 bytes):

Writing | ################################################## | 100% 0.39s

avrdude: 2566 bytes of flash written

avrdude done.  Thank you.

LCDemoMatrix.ino:


//We always have to include the library
#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(10,9,8,1);

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

void setup() {
  /*
   The MAX72XX is in power-saving mode on startup,
   we have to do a wakeup call
   */
  lc.shutdown(0,false);
  /* Set the brightness to a medium values */
  lc.setIntensity(0,8);
  /* and clear the display */
  lc.clearDisplay(0);
}

/*
 This method will display the characters for the
 word "Arduino" one after the other on the matrix. 
 (you need at least 5x7 leds to see the whole chars)
 */
void writeArduinoOnMatrix() {
  /* here is the data for the characters */
  byte a[5]={B01111110,B10001000,B10001000,B10001000,B01111110};
  byte r[5]={B00111110,B00010000,B00100000,B00100000,B00010000};
  byte d[5]={B00011100,B00100010,B00100010,B00010010,B11111110};
  byte u[5]={B00111100,B00000010,B00000010,B00000100,B00111110};
  byte i[5]={B00000000,B00100010,B10111110,B00000010,B00000000};
  byte n[5]={B00111110,B00010000,B00100000,B00100000,B00011110};
  byte o[5]={B00011100,B00100010,B00100010,B00100010,B00011100};

  /* now display them one by one with a small delay */
  lc.setRow(0,0,a[0]);
  lc.setRow(0,1,a[1]);
  lc.setRow(0,2,a[2]);
  lc.setRow(0,3,a[3]);
  lc.setRow(0,4,a[4]);
  delay(delaytime);
  lc.setRow(0,0,r[0]);
  lc.setRow(0,1,r[1]);
  lc.setRow(0,2,r[2]);
  lc.setRow(0,3,r[3]);
  lc.setRow(0,4,r[4]);
  delay(delaytime);
  lc.setRow(0,0,d[0]);
  lc.setRow(0,1,d[1]);
  lc.setRow(0,2,d[2]);
  lc.setRow(0,3,d[3]);
  lc.setRow(0,4,d[4]);
  delay(delaytime);
  lc.setRow(0,0,u[0]);
  lc.setRow(0,1,u[1]);
  lc.setRow(0,2,u[2]);
  lc.setRow(0,3,u[3]);
  lc.setRow(0,4,u[4]);
  delay(delaytime);
  lc.setRow(0,0,i[0]);
  lc.setRow(0,1,i[1]);
  lc.setRow(0,2,i[2]);
  lc.setRow(0,3,i[3]);
  lc.setRow(0,4,i[4]);
  delay(delaytime);
  lc.setRow(0,0,n[0]);
  lc.setRow(0,1,n[1]);
  lc.setRow(0,2,n[2]);
  lc.setRow(0,3,n[3]);
  lc.setRow(0,4,n[4]);
  delay(delaytime);
  lc.setRow(0,0,o[0]);
  lc.setRow(0,1,o[1]);
  lc.setRow(0,2,o[2]);
  lc.setRow(0,3,o[3]);
  lc.setRow(0,4,o[4]);
  delay(delaytime);
  lc.setRow(0,0,0);
  lc.setRow(0,1,0);
  lc.setRow(0,2,0);
  lc.setRow(0,3,0);
  lc.setRow(0,4,0);
  delay(delaytime);
}

/*
  This function lights up a some Leds in a row.
 The pattern will be repeated on every row.
 The pattern will blink along with the row-number.
 row number 4 (index==3) will blink 4 times etc.
 */
void rows() {
  for(int row=0;row<8;row++) {
    delay(delaytime);
    lc.setRow(0,row,B10100000);
    delay(delaytime);
    lc.setRow(0,row,(byte)0);
    for(int i=0;i<row;i++) {
      delay(delaytime);
      lc.setRow(0,row,B10100000);
      delay(delaytime);
      lc.setRow(0,row,(byte)0);
    }
  }
}

/*
  This function lights up a some Leds in a column.
 The pattern will be repeated on every column.
 The pattern will blink along with the column-number.
 column number 4 (index==3) will blink 4 times etc.
 */
void columns() {
  for(int col=0;col<8;col++) {
    delay(delaytime);
    lc.setColumn(0,col,B10100000);
    delay(delaytime);
    lc.setColumn(0,col,(byte)0);
    for(int i=0;i<col;i++) {
      delay(delaytime);
      lc.setColumn(0,col,B10100000);
      delay(delaytime);
      lc.setColumn(0,col,(byte)0);
    }
  }
}

/* 
 This function will light up every Led on the matrix.
 The led will blink along with the row-number.
 row number 4 (index==3) will blink 4 times etc.
 */
void single() {
  for(int row=0;row<8;row++) {
    for(int col=0;col<8;col++) {
      delay(delaytime);
      lc.setLed(0,row,col,true);
      delay(delaytime);
      for(int i=0;i<col;i++) {
        lc.setLed(0,row,col,false);
        delay(delaytime);
        lc.setLed(0,row,col,true);
        delay(delaytime);
      }
    }
  }
}

void loop() { 
  writeArduinoOnMatrix();
  rows();
  columns();
  single();
}

Great idea to cut the example down to the bare essentials. So in your second, cut down example, what happens if instead of using:

lc.clearDisplay(0);

in void loop, you use:

lc.setLed(0, 1, 1, false);

to turn the LED off ?

1 Like

Hello, thank you for your answer.

I replaced lc.clearDisplay(0) by lc.setLed(0, 1, 1, false) as you suggested. It now seems to stay the same duration and fixes the problem.

Now when I try this in the main loop instead:

void mySetDisplay(bool state) {
  for (int a = 0; a<8; a++) {
    for (int b = 0; b<8; b++) {
      lc.setLed(0, a, b, state);
    }
  }
}

void loop() { 
  mySetDisplay(true);
  delay(500);
  mySetDisplay(false);
  delay(500);
}

When I upload the sketch with these changes the matrix flashes very fast on and off (faster than 500ms. Maybe 10 times in one second) and then it stays turned off.

I am sure there is something you have to be careful when using micro controllers. But I have no ideas what it could be. Maybe the loop? Do I have to calculate the time, that the code needs to execute and avoid loops, that change the LEDs too fast? Or maybe should I avoid the duration() function?

@BitSeeker do you think in the simple, cut down example it blinks irregularly because clearDisplay() has another execution time than the setLed() function? I'm wondering how I can go from the cut-down example to a more complex sketch with more operation, that still works as expected.

With my 3rd example with the mySetDisplay() function, I'd expect the whole matrix to blink on and off with a 500ms interval.

I would suggest using millis() instead of delay() inside the void loop() function to trigger your timed actions. To clear all leds does indeed take more time to clear just the one, but delay is also a blocking action, which means that nothing can happen while the MCU sleeps for the delay period. With millis() an action is triggered at a given interval, but the MCU can keep running and doing whatever tasks are needed without having to pause. This guide might be helpful:

I haven't tested this example, but maybe something like this:

#include "LedControl.h"

// LedControl(int dataPin, int clkPin, int csPin, int numDevices=1);
LedControl lc = LedControl(10, 9, 8, 1);


bool status = true;
unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 500;

void setup()
{
  lc.shutdown(0, false);
  lc.setIntensity(0, 8);
  lc.clearDisplay(0);
  startMillis = millis();  //initial start time
}

void mySetDisplay(bool state) {
  for (int a = 0; a<8; a++) {
    for (int b = 0; b<8; b++) {
      lc.setLed(0, a, b, state);
    }
  }
}

void loop() { 
  currentMillis = millis();  //get the current millis
  if (currentMillis - startMillis >= period)  //test whether the period has elapsed
  {
    mySetDisplay(status);
    status = ~status;  // Flip status
    startMillis = currentMillis;  //IMPORTANT to save the start time of the current LED state.
  }
}

I will let you correct anything that I might have missed... :wink:
Based on the linked guide. Hopefully you get the idea.
You can, of course, also have more than one time period defined for different actions or use multiples =, i.e (period * 2), (period * 3) or whatever and have additional if statements to test for them.

I've read that (Using millis() for timing. A beginners guide) That was also something I thought about, I forgot to mention.
Unfortunately it doesn't change the weird behavior.

However I found a lot of related topics in this forum that describe the same problem.
Like this:

ledcontrol and max7219

I actually wanted to avoid the datasheet of the max7219 and try to figure out everything. I was hoping I could just use a ready to use library. But I think it's not uncommon that this chip is not working "out of the box".

I will try to use the SPI way in this answer.

I am very confused. In some threads I read something about the capacitor. I'm not into electronics, so I don't know how to make the circuit yourself. But I am using a ready to use module made by TRU Components.

I must admit I did wonder why the SPI pins (10 thru 13)) were not being used. The LedControl library does not seem to specify that they need to be and looking at the coder it seems to use bitbang (or emulated) SPI protocol which is likely going to be much slower and more taxing on the MCU.

There seem to be a number of libraries about but there for the MAX7219, but there is one that can be installed through the library manager within the IDE called 8x8 Matrix by Soldered. This one does appears to use SPI proper. Once it has been installed, then you can try running the examples (File -> Examples -> 8x8 Matrix Soldered) and build up from there. I have no affiliation with the author, just found this in the IDE.

I guess you can try both approaches and see which one works best.

1 Like

Thanks for the hint. I found several SPI libraries for the MAX7219 now.
For some reason the letters in the examples from the library by Soldered are mirror-inverted.

I just learned now that pins 11-13 are SPI pins. I don't know what SPI is, but it seems to be the proper interface to use, instead of the "bit banging".

I found this in the datasheet of the MAX7219. I add this just for the sake of completion.

I found this:
ledcontrol.h faq

Why don't you use the hardware SPI-Bus of the Arduino?
When I wrote the first version of the library I didn't knew much about the Arduino or AVR processors in general and I knew nothing about writing code for the hardware SPI-bus on an ATMega. But I knew how the SPI protocol works and how I could make this work using simple digitalWrite() commands. I turned out the library code is fast enough for common use cases, so there is no need for doing Hi-Speed communications.
Other strong points in favour of the (admittedly trivial) code design are - Use any three free IO-Pins of your board for the hardware - Simple to debug. Much easier than managing 3 differnt SPI devices connected to the same hardware bus - Library is easily portable to other platforms, since it uses only two very basic functions from the Arduino language

Yes, the max7219 is used to drive those 8x8 led martix displays, but can also be used for 7-segment displays. There is also a 'max7219' by Jonathan Evans accesasible through the library manager that deals with 7-segment displays and displaying characters on them. Examples are also provided.

Regarding the quote, I take the authors point about the flexibility being able to use any 3 pins.

my version of the MAX7219 library supports the much faster SPI interface. If you have a typcial 7 digit display, using the common print interface is very easy with this version:

https://werner.rothschopf.net/201904_arduino_ledcontrol_max7219.htm