Pages: [1] 2   Go Down
Author Topic: how to controll brightness of LEDs with max 7219  (Read 3574 times)
0 Members and 1 Guest are viewing this topic.
Cologne, DE
Offline Offline
Newbie
*
Karma: 0
Posts: 32
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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();
}
Logged

Forum Administrator
Cambridge, MA
Offline Offline
Faraday Member
*****
Karma: 12
Posts: 3538
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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):

Code:
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):

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.
Logged

Cologne, DE
Offline Offline
Newbie
*
Karma: 0
Posts: 32
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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 % smiley-cool);
  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);
  }
}

...
Logged

Forum Administrator
Cambridge, MA
Offline Offline
Faraday Member
*****
Karma: 12
Posts: 3538
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Two things.

One, in this code:

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:

Code:
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).
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Cologne, DE
Offline Offline
Newbie
*
Karma: 0
Posts: 32
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Forum Administrator
Offline Offline
Newbie
*****
Karma: 3
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bene

Welcome back. how was thailand (lucky b...benedikt smiley ) (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 smiley


massimo
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 41
I love YaBB 1G - SP1!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 6
I Love YaBB 2!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Cologne, DE
Offline Offline
Newbie
*
Karma: 0
Posts: 32
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:


Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 6
I Love YaBB 2!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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...

 :'(

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...
Logged

Cologne, DE
Offline Offline
Newbie
*
Karma: 0
Posts: 32
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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
« Last Edit: March 31, 2006, 09:15:25 am by fux » Logged

Cologne, DE
Offline Offline
Newbie
*
Karma: 0
Posts: 32
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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  smiley

cheers,

fux
« Last Edit: March 31, 2006, 09:11:44 am by fux » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 6
I Love YaBB 2!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Logged

Cologne, DE
Offline Offline
Newbie
*
Karma: 0
Posts: 32
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

http://interface.fh-potsdam.de/

someone told me, that they also work with arduino.

servus,

fux
Logged

Pages: [1] 2   Go Up
Jump to: