Hi, I would like to create my own MAX7219 LED driver library to get a better understanding and reduce the code compared to using a premade library. With existing libraries, the LED module containing of four 8x8 dot matrices works fine. But my code only works sometimes and I do not understand why it does not work all the time. Sometimes means after a reset of the Mega 2560, the LEDs turn off instead of illuminating correctly. At the moment it is working very often, but sometimes not even after many resets. I think the reason could be that the data I send sometimes gets corrupted before arriving at the MAX7219. Could I somehow improve on that? With an oscilloscope it looks like I am sending the intended bytes, however. Here is the code:
/*
MAX7219 dot matrix display control with Arduino.
IMPORTANT: The LEDs will stay on until you set them off!
IMPORTANT: To set displays in series, first pull clock to low, then send 2 bytes for the last display in series, then 2 bytes for the display before this one and so on. AFTER this pull clock high to make the changes visible!
*/
#include "SPI.h" // The MAX7219 does not use real SPI, because there is no MISO. But we still use the hardware SPI pins of the Arduino for better performance.
int ss_pin = 53; // This is the slave select pin of the Arduino Mega 2560.
void setup()
{
pinMode(ss_pin, OUTPUT); // This pin is used for chip select. The datasheet tells us that if this pin gets pulled low, the data transfer starts.
SPI.begin(); // Wakes the SPI bus up.
SPI.setBitOrder(MSBFIRST); // As declared in the data sheet. This means if we want to send for example 10000000, it is sent starting with the 1 from the left, not the 0 at the end.
SPI.setClockDivider(SPI_CLOCK_DIV16); // SPI uses with DIV16 for example 1/16 of the system frequency. For the Arduino Mega 2560 this means 1 MHz (one clock high per 0.001 ms).
}
void transmit(int address1, int data1, int address2, int data2, int address3, int data3, int address4, int data4)
/*
This function sends data to the MAX7219. As the datasheet states, using 1 to 8 for the address refers to the led segments and the data defines how the leds are turned on.
If 0 is used for the address after sending a 16 bit command, that command is sent to the next MAX7219 in the chain.
The numbering from 1 to 4 refers to the displays in series.
*/
{
digitalWrite(ss_pin, LOW); // Starts the transmission.
SPI.transfer(address4); // Sends one byte of data, so integers from 0 to 255 can be sent here.
SPI.transfer(data4);
SPI.transfer(address3);
SPI.transfer(data3);
SPI.transfer(address2);
SPI.transfer(data2);
SPI.transfer(address1);
SPI.transfer(data1);
digitalWrite(ss_pin, HIGH); // Ends the transmission.
delay(100);
}
void loop()
{
delay(2000);
transmit(255,0,255,0,255,0,255,0); // By default the display is in test mode which will light all leds. With this command test mode is turned off.
transmit(249,0,249,0,249,0,249,0); // Use no decode mode for all digits.
transmit(251,255,251,255,251,255,251,255); // Use all digits.
while(true){
for (int i = 1; i <= 8; i++) {
transmit(i,0,i,0,i,1,i,0); //digit i turns on column 1 on display 3
delay(100);
}
for (int i = 1; i <= 8; i++) {
transmit(i,0,i,0,i,0,i,0); //digit i turns off column 1
delay(100);
}
}
}