how to controll brightness of LEDs with max 7219

hello,

I want to use the max 7219 LED driver to controll the brightness of 64 LEDs individually. The hardware part is already done and I used the code example I found in the sketchbook "max7219_v1" to work with. My idea is to declare an array of 64 bytes. each byte stands for the brightness of an LED. In the future I want to controll these values with Processing over the serial port. At the moment I have 8 possible values for the brightness (0..7). there is a function called "brightnessController" which turns an LED "on" or "off", depending on its value in the array "brightnessArray". The programm itself seems to work, but I have performance problems! The on/off frequency of each LED is to slow, although there is no delay function in my programm. Any ideas to solve this problem or has someone already done a programm, that controlls the brightness of 64 LEDs individually?

Cheers,

Andreas

here is the sketch:

////////////////////////
byte brightnessArray[64];
byte maxArray[8];
////////////////////////

// define wiring pins
byte pin_max7219_clock = 7;
byte pin_max7219_load = 2;
byte pin_max7219_dataIn = 4;

// specify wiring pin i/o directions
void setPinModes()
{
pinMode(pin_max7219_dataIn, OUTPUT);
pinMode(pin_max7219_clock, OUTPUT);
pinMode(pin_max7219_load, OUTPUT);
}

// 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;

// function to control max7219 data line
void max7219_setData(boolean value)
{
digitalWrite(pin_max7219_dataIn, value);
}

// function to control max7219 clock line
void max7219_setClock(boolean value)
{
digitalWrite(pin_max7219_clock, value);
}

// function to control max7219 load line
void max7219_setLoad(boolean value)
{
digitalWrite(pin_max7219_load, value);
}

// function that puts a byte of data to the max7219
void max7219_putByte(byte data)
{
byte i = 8;
byte mask;
while(i > 0) {
mask = 0x01 << (i - 1); // get bitmask
max7219_setClock(LOW); // tick
if (data & mask){ // choose bit
max7219_setData(HIGH); // send 1
}
else{
max7219_setData(LOW); // send 0
}
max7219_setClock(HIGH); // tock
--i; // move to lesser bit
}
}
// function that puts a byte of data into a max7219 register
void max7219_put(byte reg, byte data)
{
max7219_setLoad(HIGH); // begin
max7219_putByte(reg); // specify register
max7219_putByte(data); // put data
max7219_setLoad(LOW); // latch in data
max7219_setLoad(HIGH); // end
}

// function that sets brightness of the max7219
void max7219_setIntensity(byte intensity)
{
// range: 0x00 to 0x0f
max7219_put(max7219_reg_intensity, intensity & 0x0f);
}
////////////////////////////////////////////
// function that sets the same value for all registers of the max7219

void max7219_all(byte value)
{
max7219_put(0x01, value);
max7219_put(0x02, value);
max7219_put(0x03, value);
max7219_put(0x04, value);
max7219_put(0x05, value);
max7219_put(0x06, value);
max7219_put(0x07, value);
max7219_put(0x08, value);
}

//////////////////////////////////////////////////////////////

// function that initializes the max7219 to use a matrix of leds
void max7219_init()
{
max7219_put(max7219_reg_scanLimit, 0x07); // use all 8 columns
max7219_put(max7219_reg_decodeMode, 0x00); // using an led matrix (not digits)
max7219_put(max7219_reg_shutdown, 0x01); // not in shutdown mode
max7219_put(max7219_reg_displayTest, 0x00); // no display test
max7219_all(0x00); // empty registers
max7219_setIntensity(0x0f); // set initial brightness to dim
}

///////////////////////////////////////////
// brightness controller //////////////////
///////////////////////////////////////////

void initBrightnessArray(){
int i;
for(i=0; i<64; i++){
// just to test brightness controller (brightness gradient from first LED row to last)
brightnessArray = i/8;

  • }*
    }
    void brightnessController(){
  • byte index;*
  • byte bitpos;*
  • int i;*
  • int j;*
  • int k;*
  • // set all to zero*
  • for(i=0; i<8; i++){*
    _ maxArray = 0;_
    * }*
    * // 8 brightness values*
    * for(i=0; i<8; i++){*
    * // 64 LEDs*
    * for(j=0; j<64; j++){*
    * //*
    * if (brightnessArray[j] <= i){*
    * index = j/8;*
    * bitpos = j%8;*
    * maxArray[index] = maxArray[index] | 1<<bitpos;*
    * }*
    * }*
    * // output to max7219*
    * for(k=0; k<8; k++){*
    * max7219_put(0x0+(k+1), maxArray[k]);
    _
    }_
    _
    // delay (although when there is no delay the programm seems to be too slow!?)_
    _
    delayMicroseconds(1);_
    _
    }_
    _
    }_
    _
    //////////////////////////////////////////_
    _
    // program initialization routine*_
    void setup()
    {
    * beginSerial(57600);*
    * setPinModes();*
    * max7219_init();
    _
    initBrightnessArray();_
    _
    }_
    _
    // program loop*_
    void loop()
    {
    * // brightness*
    * brightnessController();*
    }

Hmm... if the brightness of the individuals LEDs won't be changing too fast, you might try flipping your data structures around. Instead of storing a brightness for each LED, try storing the bytes that you'll be writing to the registers of the MAX7219 for each time slice. That is, create a 64-byte array registers such that registers[timeslice * 8 + register] gives you the byte to write to the corresponding register during the appropriate timeslice. Thus, you could update the display with a very simple and efficient loop (warning, untested code ahead):

for (index = 0; index < 64; )
  for (register = 0; register < 8; register++, index++)
    max7219_put(register + 1, registers[index]);

To change the brightness of an LED, you would do something like this (more untested code):

void setBrightness(int led, int brightness)
{
  int timeslice;
  int bitmask = (1 << (led % 8));
  int register = led / 8;

  for (timeslice = 0; timeslice < brightness; timeslice++)
    registers[timeslice * 8 + register] |= bitmask;
  for (timeslice = brightness; timeslice < 8; timeslice++)
    registers[timeslice * 8 + register] &= ~bitmask;
}

Let us know if you have any luck; this would be a great example for the tutorial section.

Thanks for your advice! I tried to implement your code, but now all the LEDs just start blinking all together at the same time in an interval of about 500 ms. My main problem is, that I am a newbie in programming microcontrollers. Till now I just have experience in programming visual interfaces and I have to get more in depth with the "Byte" thing I think. So maybe the actual code has still some mistakes. Maybe you have an idea what is wrong?

best,
Andreas

here is the code (just the new functions):

I call the function "initBrightness" once in "void setup()" and "brigthnessController" in the "void loop()" section. the array registers[] is declared globally as "byte registers[64];" at the beginning of the code

...

void setBrightness(int led, int brightness){
int timeslice;
int bitmask = (1 << (led % 8));
int tempRegister = led/8;
for (timeslice = 0; timeslice < brightness; timeslice++){
registers[timeslice * 8 + tempRegister] |= bitmask;
for (timeslice = brightness; timeslice < 8; timeslice++){
registers[timeslice * 8 + tempRegister] &= ~bitmask;
}
}
}
void brightnessController(){
int index;
for (index = 0; index < 64; index++){
int tempRegister;
for (tempRegister = 0; tempRegister < 8; tempRegister++){
max7219_put(tempRegister + 1, registers[index]);
}
}
}
void initBrightness(){
int i;
for(i=1; i<=64; i++){
// 16 different brightness values
setBrightness(i, i/4);
}
}

...

Two things.

One, in this code:

for (index = 0; index < 64; )
  for (register = 0; register < 8; register++, index++)
    max7219_put(register + 1, registers[index]);

the index++ needs to be in the inner loop. I know it looks weird, but the index needs to change with the register. This is equivalent to:

for (timeslice = 0; timeslice < 8; timeslice++)
  for (register = 0; register < 8; register++)
    max7219_put(register + 1, registers[timeslice * 8 + register]);

except that you don't need the multiplication in the inner loop (though it probably wouldn't slow things down much).

Second, your brightnesses only go between 0 and 7, but you're setting them at up to 15 (63/4). That means that half your LEDs will be at maximum brightness (always on).

hello fux,

can you please post the finished script?
i'm very also very interested into controlling leds with arduino via a led driver ... but i think i'm going to buy rather the MAX7313 (16 channels + PWM)

thanks
bene

hello,

As soon as my code will work I will post it here. Today I talked to a c coder at work and he had the same idea than mellis. Maybe I will be sucessful till next week, but at the moment there is to much other work to do for me. The MAX7313 sounds very interessting. I will have a look on it.

Thanks,

fux

Bene

Welcome back. how was thailand (lucky b...benedikt :slight_smile: ) (btw i've sent you an sms)

remeber that the max7313 is very different from the 7219. the 7219 can only dim a whole block of leds at the time while the 7313 can dim each LED individually. In order for the 7219 to dim each led individually it's going to be tricky (especially for large displays)

so mr benefit your code will be much simpler, if you come to milan i'll write the code for you :slight_smile:

massimo

i wasnt aware that the 7219 could dim individual leds at all. thats interesting! but then my display incorporates 12 of the chips so thats going to be a nightmare... think i'll just stick with what i (vaguely) understand for the time being. ;D

HOW ABOUT THE HARDWARE PART? could you post a picture or sketch or something? my imagination end here.

here are some pics of the LED board. you have to wire a 8x8 matrix and connect it to the max 7219 described in its datasheet.

Cheers,
fux

front view:

back view:

hm. unfortunately I don't get it done. There is no explanation in the documentation of 7219, either.

could anybody post schematics of how to connect the LEDs with eachother and the IC?

the 7219 sketch delivered with the arduino software is (from my point of view) quite useless, too, because there is not the slightest information of WHAT should it do and HOW could it be done...

:cry:

i am familiar with arrays, objects, receive and store data etc. and am programming for years now, but i'm a complete newbie to ICs and stuff...

hello goldbauch,

i am really sorry. at the moment i have too much work to do at my job. maybe i can post a description next week. but maybe there is someone else out there who could help you.

best,

fux

hello goldbauch,

are you from germany ("goldbauch" sonds like this). i live in cologne. i did the hardware stuff with some guy in my school, who is really familiar with electronical stuff. i am also a newbie in these things. so it would be much easier to meet each other so i can show how i get it done. next week i am in bremen for two days. otherwise as i posted it before i will try to draw a schematics till the end of the next week.

maybe here is a fallback solution for you:

http://www.active-robots.com/products/phidgets/phidgets-led-systems.shtml

but it is quite expensive (with shipping about 120 euros). there comes also a C library with the board and maybe it is possible to controll it with an arduino board.

but for me it is much more fun to build a LED board on your own :slight_smile:

cheers,

fux

hey. yes. german. austrian. austrian but living in berlin. servus.

don't stress yourself, at the moment it's a time problem for me, too. i will experiment a bit and have a look whether I can solve it on my own. if I have a more detailed question than "can't get it to work - hm?" I will let you know and hope you or your pal can help me out. so, thanks for your offer.

i am austrian too.

with some luck i move to berlin in autumn. very nice city!!!
maybe you can contact some guys from the FH potsdam:

someone told me, that they also work with arduino.

servus,

fux

austrian from WHERE?

the fh guys at least use the same conrad electronics mounting boards. =)

move here! now. =)

from lustenau, vorarlberg.

now studying at the KHM (Kunsthochschule für Medien). but at the moment i have to work too much for my job and too less time for my studies. if you know Malte from the FH Potsdam salute him from me. he worked for three month in our office. just see his project "just-on-time-cube", he sent to the "digital sparks awards 2006". pretty nice work!

cheers,
fux

xiberger müssen nach xberg (kreuzberg) ziehen. =)

ich bin tiroler.

holldrio. bis bald.

hab da vor zwei jahren schon mal für drei monate direkt am kottbuser tor gewohnt. mal schaun, vielleicht wirds wieder kreuzberg :slight_smile: