16x16 LED Matrix using MAX7219 for Arduino

Hi ALL!

i want to build a 16x16 LED Matrix using MAX7219 for Arduino but i have problems in programming. Can any one help me? can some one have the solution?

you can contact us to my email: sgharbi11@gmail.com

to connect the max to each other i use this shematic : http://blog.carr3r.com/content/public/upload/schema-matrix_0_o.png

and i use this codee control the 168 matrix but ihave no idea how to control a 1616 matrix can any one help me:

#include "MaxMatrix.h"
#include "avr/pgmspace.h"

PROGMEM prog_uchar CH[] = {
3, 8, B00000000, B00000000, B00000000, B00000000, B00000000, // space
1, 8, B01011111, B00000000, B00000000, B00000000, B00000000, // !
3, 8, B00000011, B00000000, B00000011, B00000000, B00000000, // "
5, 8, B00010100, B00111110, B00010100, B00111110, B00010100, // #
4, 8, B00100100, B01101010, B00101011, B00010010, B00000000, // $
5, 8, B01100011, B00010011, B00001000, B01100100, B01100011, // %
5, 8, B00110110, B01001001, B01010110, B00100000, B01010000, // &
1, 8, B00000011, B00000000, B00000000, B00000000, B00000000, // '
3, 8, B00011100, B00100010, B01000001, B00000000, B00000000, // (
3, 8, B01000001, B00100010, B00011100, B00000000, B00000000, // )
5, 8, B00101000, B00011000, B00001110, B00011000, B00101000, // *
5, 8, B00001000, B00001000, B00111110, B00001000, B00001000, // +
2, 8, B10110000, B01110000, B00000000, B00000000, B00000000, // ,
4, 8, B00001000, B00001000, B00001000, B00001000, B00000000, // -
2, 8, B01100000, B01100000, B00000000, B00000000, B00000000, // .
4, 8, B01100000, B00011000, B00000110, B00000001, B00000000, // /
4, 8, B00111110, B01000001, B01000001, B00111110, B00000000, // 0
3, 8, B01000010, B01111111, B01000000, B00000000, B00000000, // 1
4, 8, B01100010, B01010001, B01001001, B01000110, B00000000, // 2
4, 8, B00100010, B01000001, B01001001, B00110110, B00000000, // 3
4, 8, B00011000, B00010100, B00010010, B01111111, B00000000, // 4
4, 8, B00100111, B01000101, B01000101, B00111001, B00000000, // 5
4, 8, B00111110, B01001001, B01001001, B00110000, B00000000, // 6
4, 8, B01100001, B00010001, B00001001, B00000111, B00000000, // 7
4, 8, B00110110, B01001001, B01001001, B00110110, B00000000, // 8
4, 8, B00000110, B01001001, B01001001, B00111110, B00000000, // 9
2, 8, B01010000, B00000000, B00000000, B00000000, B00000000, // :
2, 8, B10000000, B01010000, B00000000, B00000000, B00000000, // ;
3, 8, B00010000, B00101000, B01000100, B00000000, B00000000, // <
3, 8, B00010100, B00010100, B00010100, B00000000, B00000000, // =
3, 8, B01000100, B00101000, B00010000, B00000000, B00000000, // >
4, 8, B00000010, B01011001, B00001001, B00000110, B00000000, // ?
5, 8, B00111110, B01001001, B01010101, B01011101, B00001110, // @
4, 8, B01111110, B00010001, B00010001, B01111110, B00000000, // A
4, 8, B01111111, B01001001, B01001001, B00110110, B00000000, // B
4, 8, B00111110, B01000001, B01000001, B00100010, B00000000, // C
4, 8, B01111111, B01000001, B01000001, B00111110, B00000000, // D
4, 8, B01111111, B01001001, B01001001, B01000001, B00000000, // E
4, 8, B01111111, B00001001, B00001001, B00000001, B00000000, // F
4, 8, B00111110, B01000001, B01001001, B01111010, B00000000, // G
4, 8, B01111111, B00001000, B00001000, B01111111, B00000000, // H
3, 8, B01000001, B01111111, B01000001, B00000000, B00000000, // I
4, 8, B00110000, B01000000, B01000001, B00111111, B00000000, // J
4, 8, B01111111, B00001000, B00010100, B01100011, B00000000, // K
4, 8, B01111111, B01000000, B01000000, B01000000, B00000000, // L
5, 8, B01111111, B00000010, B00001100, B00000010, B01111111, // M
5, 8, B01111111, B00000100, B00001000, B00010000, B01111111, // N
4, 8, B00111110, B01000001, B01000001, B00111110, B00000000, // O
4, 8, B01111111, B00001001, B00001001, B00000110, B00000000, // P
4, 8, B00111110, B01000001, B01000001, B10111110, B00000000, // Q
4, 8, B01111111, B00001001, B00001001, B01110110, B00000000, // R
4, 8, B01000110, B01001001, B01001001, B00110010, B00000000, // S
5, 8, B00000001, B00000001, B01111111, B00000001, B00000001, // T
4, 8, B00111111, B01000000, B01000000, B00111111, B00000000, // U
5, 8, B00001111, B00110000, B01000000, B00110000, B00001111, // V
5, 8, B00111111, B01000000, B00111000, B01000000, B00111111, // W
5, 8, B01100011, B00010100, B00001000, B00010100, B01100011, // X
5, 8, B00000111, B00001000, B01110000, B00001000, B00000111, // Y
4, 8, B01100001, B01010001, B01001001, B01000111, B00000000, // Z
2, 8, B01111111, B01000001, B00000000, B00000000, B00000000, // [
4, 8, B00000001, B00000110, B00011000, B01100000, B00000000, // \ backslash
2, 8, B01000001, B01111111, B00000000, B00000000, B00000000, // ]
3, 8, B00000010, B00000001, B00000010, B00000000, B00000000, // hat
4, 8, B01000000, B01000000, B01000000, B01000000, B00000000, // _
2, 8, B00000001, B00000010, B00000000, B00000000, B00000000, // `
4, 8, B00100000, B01010100, B01010100, B01111000, B00000000, // a
4, 8, B01111111, B01000100, B01000100, B00111000, B00000000, // b
4, 8, B00111000, B01000100, B01000100, B00101000, B00000000, // c
4, 8, B00111000, B01000100, B01000100, B01111111, B00000000, // d
4, 8, B00111000, B01010100, B01010100, B00011000, B00000000, // e
3, 8, B00000100, B01111110, B00000101, B00000000, B00000000, // f
4, 8, B10011000, B10100100, B10100100, B01111000, B00000000, // g
4, 8, B01111111, B00000100, B00000100, B01111000, B00000000, // h
3, 8, B01000100, B01111101, B01000000, B00000000, B00000000, // i
4, 8, B01000000, B10000000, B10000100, B01111101, B00000000, // j
4, 8, B01111111, B00010000, B00101000, B01000100, B00000000, // k
3, 8, B01000001, B01111111, B01000000, B00000000, B00000000, // l
5, 8, B01111100, B00000100, B01111100, B00000100, B01111000, // m
4, 8, B01111100, B00000100, B00000100, B01111000, B00000000, // n
4, 8, B00111000, B01000100, B01000100, B00111000, B00000000, // o
4, 8, B11111100, B00100100, B00100100, B00011000, B00000000, // p
4, 8, B00011000, B00100100, B00100100, B11111100, B00000000, // q
4, 8, B01111100, B00001000, B00000100, B00000100, B00000000, // r
4, 8, B01001000, B01010100, B01010100, B00100100, B00000000, // s
3, 8, B00000100, B00111111, B01000100, B00000000, B00000000, // t
4, 8, B00111100, B01000000, B01000000, B01111100, B00000000, // u
5, 8, B00011100, B00100000, B01000000, B00100000, B00011100, // v
5, 8, B00111100, B01000000, B00111100, B01000000, B00111100, // w
5, 8, B01000100, B00101000, B00010000, B00101000, B01000100, // x
4, 8, B10011100, B10100000, B10100000, B01111100, B00000000, // y
3, 8, B01100100, B01010100, B01001100, B00000000, B00000000, // z
3, 8, B00001000, B00110110, B01000001, B00000000, B00000000, // {
1, 8, B01111111, B00000000, B00000000, B00000000, B00000000, // |
3, 8, B01000001, B00110110, B00001000, B00000000, B00000000, // }
4, 8, B00001000, B00000100, B00001000, B00000100, B00000000, // ~
4, 8, B00100110, B00100011, B00110001, B00110101, B00111000, B00110111, 00111011, //? 
};

int data = 7;    // DIN pin of MAX7219 module
int load = 8;    // CS pin of MAX7219 module
int clock = 10;  // CLK pin of MAX7219 module

int maxInUse = 9;    //change this variable to set how many MAX7219's you'll use

MaxMatrix m(data, load, clock, maxInUse); // define module

byte buffer[10];



void setup(){
  m.init(); // module initialize
  m.setIntensity(7); // dot matix intensity 0-15
  Serial.begin(9600); // serial communication initialize
}

void loop(){
  
  // this is the code if you want to entering a message via serial console
  while (Serial.available() > 0){
    byte c = Serial.read();
    Serial.println(c, DEC);
    printCharWithShift(c, 100);
  }
  delay(100);
  m.shiftLeft(false, true);
  
  
  // print the active sentences
  printStringWithShift(" hi all! " , 200);
  printStringWithShift(" A 8*8 MATRIX ... " , 200);
}

void printCharWithShift(char c, int shift_speed){
  if (c < 32) return;
  c -= 32;
  memcpy_P(buffer, CH + 7*c, 7);
  m.writeSprite(72, 0, buffer);
  m.setColumn(72 + buffer[0], 0);
  
  for (int i=0; i<buffer[0]+1; i++) 
  {
    delay(shift_speed);
    m.shiftLeft(false, false);
  }
}

void printStringWithShift(char* s, int shift_speed){
  while (*s != 0){
    printCharWithShift(*s, shift_speed);
    s++;
  }
}

void printString(char* s)
{
  int col = 0;
  while (*s != 0)
  {
    if (*s < 32) continue;
    char c = *s - 32;
    memcpy_P(buffer, CH + 7*c, 7);
    m.writeSprite(col, 0, buffer);
    m.setColumn(col + buffer[0], 0);
    col += buffer[0] + 1;
    s++;
  }
}

Please read the first bullet point Forum Etiquette

Maybe rather than asking for a solution, you could describe the problem you're having?
What is the difference you perceive between controlling a 16x8 matrix and a 16x16 matrix (or a 32x8 matrix).
you just connect your second 16x8 matrix after the first one, shift some more data into it, and that's it. How you physically position it (32x8 or 16x16) doesn't really matter.

racemaniac:
How you physically position it (32x8 or 16x16) doesn't really matter.

It does if you want to scroll text around.

racemaniac:
Maybe rather than asking for a solution, you could describe the problem you're having?

I quite agree.

Also you need to post a link to those modules you are using.

In your code you have:-

int maxInUse = 9;    //change this variable to set how many MAX7219's you'll use

In your wiring I see only four.

#include "MaxMatrix.h"

You need to include a link to this file so we can see what it does.

It looks like the code might require the matrices to be all in a line not in a two by two grid.
The data will be sent out in the order 1,2 ,3,4 so if they are physically laid out like that schematic the scrolling will look very odd.

my issue is: when i connected the shift according this schematic:

and upload the code at the top i have a scrolling message like this:the "A" mirrored on the two down matrix :

but i want to have a scrolling text like this:

Can someone help me?

Grumpy_Mike:
In your code you have:-

int maxInUse = 9;    //change this variable to set how many MAX7219's you'll use

In your wiring I see only four.

#include "MaxMatrix.h"

You need to include a link to this file so we can see what it does.

It looks like the code might require the matrices to be all in a line not in a two by two grid.
The data will be sent out in the order 1,2 ,3,4 so if they are physically laid out like that schematic the scrolling will look very odd.

i change it to 4 but nothing have change and this is the libraries: MaxMatrix.h :

/*
 * MaxMatrix
 * Version 1.0 Feb 2013
 * Copyright 2013 Oscar Kin-Chung Au
 */

#ifndef _MaxMatrix_H_
#define _MaxMatrix_H_

#include "Arduino.h"

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

class MaxMatrix
{
  private:
    byte data;
    byte load;
    byte clock;
    byte num;
    byte buffer[80];
    
    void reload();
	
  public:
    MaxMatrix(byte data, byte load, byte clock, byte num);
    
    void init();
    void clear();
    void setCommand(byte command, byte value);
    void setIntensity(byte intensity);
    void setColumn(byte col, byte value);
    void setColumnAll(byte col, byte value);
    void setDot(byte col, byte row, byte value);
    void writeSprite(int x, int y, const byte* sprite);
    
    void shiftLeft(bool rotate = false, bool fill_zero = true);
    void shiftRight(bool rotate = false, bool fill_zero = true);
    void shiftUp(bool rotate = false);
    void shiftDown(bool rotate = false);
};

#endif

and this is the second libraries: "MaxMatrix.cpp" :

/*
 * MaxMatrix
 * Version 1.0 Feb 2013
 * Copyright 2013 Oscar Kin-Chung Au
 */


#include "Arduino.h"
#include "MaxMatrix.h"

MaxMatrix::MaxMatrix(byte _data, byte _load, byte _clock, byte _num) 
{
	data = _data;
	load = _load;
	clock = _clock;
	num = _num;
	for (int i=0; i<80; i++)
		buffer[i] = 0;
}

void MaxMatrix::init()
{
	pinMode(data,  OUTPUT);
	pinMode(clock, OUTPUT);
	pinMode(load,  OUTPUT);
	digitalWrite(clock, HIGH); 

	setCommand(max7219_reg_scanLimit, 0x07);      
	setCommand(max7219_reg_decodeMode, 0x00);  // using an led matrix (not digits)
	setCommand(max7219_reg_shutdown, 0x01);    // not in shutdown mode
	setCommand(max7219_reg_displayTest, 0x00); // no display test
	
	// empty registers, turn all LEDs off
	clear();
	
	setIntensity(0x0f);    // the first 0x0f is the value you can set
}

void MaxMatrix::setIntensity(byte intensity)
{
	setCommand(max7219_reg_intensity, intensity);
}

void MaxMatrix::clear()
{
	for (int i=0; i<8; i++) 
		setColumnAll(i,0);
		
	for (int i=0; i<80; i++)
		buffer[i] = 0;
}

void MaxMatrix::setCommand(byte command, byte value)
{
	digitalWrite(load, LOW);    
	for (int i=0; i<num; i++) 
	{
		shiftOut(data, clock, MSBFIRST, command);
		shiftOut(data, clock, MSBFIRST, value);
	}
	digitalWrite(load, LOW);
	digitalWrite(load, HIGH);
}


void MaxMatrix::setColumn(byte col, byte value)
{
	int n = col / 8;
	int c = col % 8;
	digitalWrite(load, LOW);    
	for (int i=0; i<num; i++) 
	{
		if (i == n)
		{
			shiftOut(data, clock, MSBFIRST, c + 1);
			shiftOut(data, clock, MSBFIRST, value);
		}
		else
		{
			shiftOut(data, clock, MSBFIRST, 0);
			shiftOut(data, clock, MSBFIRST, 0);
		}
	}
	digitalWrite(load, LOW);
	digitalWrite(load, HIGH);
	
	buffer[col] = value;
}

void MaxMatrix::setColumnAll(byte col, byte value)
{
	digitalWrite(load, LOW);    
	for (int i=0; i<num; i++) 
	{
		shiftOut(data, clock, MSBFIRST, col + 1);
		shiftOut(data, clock, MSBFIRST, value);
		buffer[col * i] = value;
	}
	digitalWrite(load, LOW);
	digitalWrite(load, HIGH);
}

void MaxMatrix::setDot(byte col, byte row, byte value)
{
    bitWrite(buffer[col], row, value);

	int n = col / 8;
	int c = col % 8;
	digitalWrite(load, LOW);    
	for (int i=0; i<num; i++) 
	{
		if (i == n)
		{
			shiftOut(data, clock, MSBFIRST, c + 1);
			shiftOut(data, clock, MSBFIRST, buffer[col]);
		}
		else
		{
			shiftOut(data, clock, MSBFIRST, 0);
			shiftOut(data, clock, MSBFIRST, 0);
		}
	}
	digitalWrite(load, LOW);
	digitalWrite(load, HIGH);
}

void MaxMatrix::writeSprite(int x, int y, const byte* sprite)
{
	int w = sprite[0];
	int h = sprite[1];
	
	if (h == 8 && y == 0)
		for (int i=0; i<w; i++)
		{
			int c = x + i;
			if (c>=0 && c<80)
				setColumn(c, sprite[i+2]);
		}
	else
		for (int i=0; i<w; i++)
			for (int j=0; j<h; j++)
			{
				int c = x + i;
				int r = y + j;
				if (c>=0 && c<80 && r>=0 && r<8)
					setDot(c, r, bitRead(sprite[i+2], j));
			}
}

void MaxMatrix::reload()
{
	for (int i=0; i<8; i++)
	{
		int col = i;
		digitalWrite(load, LOW);    
		for (int j=0; j<num; j++) 
		{
			shiftOut(data, clock, MSBFIRST, i + 1);
			shiftOut(data, clock, MSBFIRST, buffer[col]);
			col += 8;
		}
		digitalWrite(load, LOW);
		digitalWrite(load, HIGH);
	}
}

void MaxMatrix::shiftLeft(bool rotate, bool fill_zero)
{
	byte old = buffer[0];
	int i;
	for (i=0; i<80; i++)
		buffer[i] = buffer[i+1];
	if (rotate) buffer[num*8-1] = old;
	else if (fill_zero) buffer[num*8-1] = 0;
	
	reload();
}

void MaxMatrix::shiftRight(bool rotate, bool fill_zero)
{
	int last = num*8-1;
	byte old = buffer[last];
	int i;
	for (i=79; i>0; i--)
		buffer[i] = buffer[i-1];
	if (rotate) buffer[0] = old;
	else if (fill_zero) buffer[0] = 0;
	
	reload();
}

void MaxMatrix::shiftUp(bool rotate)
{
	for (int i=0; i<num*8; i++)
	{
		bool b = buffer[i] & 1;
		buffer[i] >>= 1;
		if (rotate) bitWrite(buffer[i], 7, b);
	}
	reload();
}

void MaxMatrix::shiftDown(bool rotate)
{
	for (int i=0; i<num*8; i++)
	{
		bool b = buffer[i] & 128;
		buffer[i] <<= 1;
		if (rotate) bitWrite(buffer[i], 0, b);
	}
	reload();
}

Is there anything in the documentation that suggest the library you use is capable of supporting your display configuration?
I think your problem is expecting your library to magically know that you've put 2 displays on top of each other, and then make the letters a lot taller, apparantly it won't.

Maybe you should learn to code this yourself. Creating your own program that controls a few max chips and scrolls text isn't that hard, you'll learn a lot, and be able to make your display any shape you like once you understand it :).

Similar discussion in this thread.

Might want to try the parola library as well
https://parola.codeplex.com/
"Parola is a modular scrolling text display using MAX7219/21 LED matrix display controllers. The display is made up of any number of identical modules that are plugged together to create a wider/longer display. Text left, right or center justification in the display
Text scrolling, entry and exit effects
Control display parameters and animation speed
Support for hardware SPI interface
Multiple virtual displays (zones) in each string of LED modules
User defined fonts and/or individual characters substitutions"

but i want to have a scrolling text like this

Then you will have to write your own code for this along with your own font definition.
Forget the libraries, they will not do it for you.

It also looks like you have mounted the bottom two matrices up side down. While you could compensate for that in software it makes the font definitions very difficult to do.
You need to wire the matrices so they are in the correct orientation.

Is the wiring fixed and you can't change it? If so then it might be a deliberate ploy by the person setting you this assignment so that you do not use "off the shelf" code and you have to understand and write your own.

Grumpy_Mike:
It also looks like you have mounted the bottom two matrices up side down. While you could compensate for that in software it makes the font definitions very difficult to do.

Quite so, but it appears many assemblies (16 by 16) offered for sale are arranged in exactly that fashion as I noted before.

You can use the same font definitions - the software needs to compensate.

CrossRoads:
Might want to try the parola library as well
https://parola.codeplex.com/

I was going to suggest exactly that - if only I could recall what and where it was. :grinning:

you have to understand and write your own

i am not good in programming, bu when i searched i fond this code wish commanded via "IR remote", I don't like to use this "IR remote" and I don't know how to change it and make it working Without "IR remote"

the code is at the link below -----> https://docs.google.com/file/d/0BzIpQjwhROrVNDlOSzVkMzhpenM/edit

hi MARCO!

thank you for the sketch and the PAROLA libraries. if i decided to build a 80*16 do matrix using your sketch. It necessary any change in the parola code. if yes what is this change?

Can you help me?

I am assuming that you want to create letters 16 LEDs high scrolling across the display.

The majority of changes will need to be in the MD_MAX72XX library, and the extent of the changes is not trivial. If you are not experienced I would not recommend this.

  1. Above all else you will need to be clear how the hardware will be configured as you will need to take this into account in the way that the data is sent to the MAX7219 chips.
  2. The font definition will need to change in order to map to 16 pixels high instead of 8. All associated code will need to change for the new font and hardware configuration.
  3. All definitions on the display buffers that use uint8_t will need to change to uint16_t. All code processing buffers (shifts, transformations, SPI comms, buffer management) will need to be inspected and adapted.
  4. Testing, testing, testing ...

There should be few, if any, changes needed for the MD_Parola library as these are hardware independent, using the MD_MAX72xx library to take care of those details.

hi marco!
that's way i ask you, i am not an excellent experienced, i have the font map to 16 pixels, but i don't know how change the program to command 4 matrix at the same time. have you an example of the parola libraries the command 16*16 matrix. Please give me a hand.

No example is available unless someone else can provide it.

Are you trying to do 16x16 or 16x80 (earlier post)?

I agree with all the others - your hardware is non-standard and this is a school assignment - does that mean that you should be doing this yourself?

Are you trying to do 16x16 or 16x80 (earlier post)?

i want to build a 1680 but to simplify i write 1616 it was the same code to command 1616 dot matrix than 1680 expect changing the MaxInUse or no?

does that mean that you should be doing this yourself?

for this I confess I'm doing it for school and i will represent it next month. Please help me this is the truth.