Go Down

Topic: MAX7219 with Arduino (Read 3353 times) previous topic - next topic

imzack

Im having trouble trying to figure out how to set up the MAX7219 chip, in the startup routine....  I see there is supposed to be an ledcontrol.h file that is supposed to help.  My arduino compliler says there is no such library though....


Any suggestions on how i can get this thing programed and through the start up section?


Thanks!

Zack

CrossRoads

Here's what I did. I don't use libraries a lot, preferring to read the data sheet & understand what's going on. Doesn't make for the greatest code sometimes, and there's plenty of room for improvement.

You'll have to do some variable declarations too.
Code: [Select]

// addresses for the MAX7221, and the values/ranges to write in

#define DECODE_MODE 0x09 // write data 0xFF, Code B Decode for all digits
#define INTENSITY_ADDRESS 0x0A // 0x07 to start, half intensity. valid from 0x00 (min) to 0x0F (max)
#define SCANLIMIT_ADDRESS 0x0B // 0xFF, all 8 digits on
#define SHUTDOWN_ADDRESS 0x0C  // 0x01, normal operation (0x01 = shutdown) - powers up in shutdown mode

#define DISPLAYTEST_ADDRESS 0x0F // 0x01 = all lights on full, 0x00 = normal ops
#define leftscore_tens_address 0x01 // digit 0, leftscore_tens+left_yellow, fill right hand byte with data to display
// data = 0-9, A='-', B='E', C='H', D='L', E='P', F=blank
#define leftscore_ones_address 0x02 // digit 1, leftscore_ones+right_yellow
#define rightscore_tens_address 0x03 // digit 2, rightscore_tens+right_red
#define rightscore_ones_address 0x04 // digit 3, rightscore_ones+right_yellow
#define minutes_tens_address 0x05 // digit 4, minutes_tens+colon
#define minutes_ones_address 0x06 // digit 5, minutes_ones+left_priority
#define seconds_tens_address 0x07 // digit 6, seconds_tens+right_priority
#define seconds_ones_address 0x08 // digit 7, seconds_ones+swap



void setup() // stuff that runs once before looping forever
{
 // start up SPI to talk to the MAX7221
 SPI.begin(); // nothing in () because we are the master
 pinMode(SS, OUTPUT);  // Slave Select for SPI  <--- Need this here before any SPI writes

 //  MAX7221: write shutdown register  
 digitalWrite(SS,LOW);  // take the SS pin low to select the chip:
 SPI.transfer(SHUTDOWN_ADDRESS);  // select the Address,
 SPI.transfer(0x00);      // select the data, 0x00 = Outputs turned off
 digitalWrite(SS,HIGH);   // take the SS pin high to de-select the chip:
 // Serial.println("shutdown register, dislays off");

 // put known values into MAX7221 so doesn't have weird display when actually turned on
 // 0x0F = blank digit
 digitalWrite(SS,LOW);  // take the SS pin low to select the chip:
 SPI.transfer(leftscore_tens_address);  // select the Address,   <<< these are the addresses of the 8 data registers
 SPI.transfer(0x0F);      // select the data
 digitalWrite(SS,HIGH);   // take the SS pin high to de-select the chip

 digitalWrite(SS,LOW);  // take the SS pin low to select the chip:
 SPI.transfer(leftscore_ones_address);  // select the Address,
 SPI.transfer(0x0F);      // select the data
 digitalWrite(SS,HIGH);   // take the SS pin high to de-select the chip

 digitalWrite(SS,LOW);  // take the SS pin low to select the chip:
 SPI.transfer(rightscore_tens_address);  // select the Address,
 SPI.transfer(0x0F);      // select the data
 digitalWrite(SS,HIGH);   // take the SS pin high to de-select the chip  

 digitalWrite(SS,LOW);  // take the SS pin low to select the chip:
 SPI.transfer(rightscore_ones_address);  // select the Address,
 SPI.transfer(0x0F);      // select the data
 digitalWrite(SS,HIGH);   // take the SS pin high to de-select the chip

 digitalWrite(SS,LOW);  // take the SS pin low to select the chip:
 SPI.transfer(minutes_tens_address);  // select the Address,
 SPI.transfer(0x0F);      // select the data
 digitalWrite(SS,HIGH);   // take the SS pin high to de-select the chip

 digitalWrite(SS,LOW);  // take the SS pin low to select the chip:
 SPI.transfer(minutes_ones_address);  // select the Address,
 SPI.transfer(0x0F);      // select the data
 digitalWrite(SS,HIGH);   // take the SS pin high to de-select the chip

 digitalWrite(SS,LOW);  // take the SS pin low to select the chip:
 SPI.transfer(seconds_tens_address);  // select the Address,
 SPI.transfer(0x0F);      // select the data
 digitalWrite(SS,HIGH);   // take the SS pin high to de-select the chip  

 digitalWrite(SS,LOW);  // take the SS pin low to select the chip:
 SPI.transfer(seconds_ones_address);  // select the Address,
 SPI.transfer(0x0F);      // select the data
 digitalWrite(SS,HIGH);   // take the SS pin high to de-select the chip

 //  MAX7221:
 //  write intensity register
 digitalWrite(SS,LOW);  // take the SS pin low to select the chip:
 SPI.transfer(INTENSITY_ADDRESS);  // select the Address,
 SPI.transfer(intensity);      // select the data
 digitalWrite(SS,HIGH);   // take the SS pin high to de-select the chip:
 //Serial.println("intensity register ");

 // write scanlimit register
 digitalWrite(SS,LOW);  // take the SS pin low to select the chip:
 SPI.transfer(SCANLIMIT_ADDRESS);  // select the Address,
 SPI.transfer(0xFF);      // select the data - FF = all 8 digits
 digitalWrite(SS,HIGH);   // take the SS pin high to de-select the chip:
 //Serial.println("scanlimit register ");

 // write decode register
 digitalWrite(SS,LOW);  // take the SS pin low to select the chip:
 SPI.transfer(DECODE_MODE);  // select the Address,
 SPI.transfer(0xFF);      // select the data - FF = all 8 digits
 digitalWrite(SS,HIGH);   // take the SS pin high to de-select the chip:
 //Serial.println("decode register ");

 //display test
 digitalWrite(SS,LOW);  // take the SS pin low to select the chip:
 SPI.transfer(DISPLAYTEST_ADDRESS);  // select the Address,
 SPI.transfer(0x01);      // select the data
 digitalWrite(SS,HIGH);   // take the SS pin high to de-select the chip:
 //Serial.println("digit display test on ");
 delay (100);

 digitalWrite(SS,LOW);  // take the SS pin low to select the chip:
 SPI.transfer(DISPLAYTEST_ADDRESS);  // select the Address,
 SPI.transfer(0x00);      // select the data
 digitalWrite(SS,HIGH);   // take the SS pin high to de-select the chip:
 //Serial.println("digit display test off ");
 delay (100);

 // write shutdown register for normal display operations
 digitalWrite(SS,LOW);  // take the SS pin low to select the chip:
 SPI.transfer(SHUTDOWN_ADDRESS);  // select the Address,
 SPI.transfer(0x01);      // select the data, 0x01 = Normal Ops
 digitalWrite(SS,HIGH);   // take the SS pin high to de-select the chip:
 //Serial.println("shutdown register, displays on ");

}
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

imzack

Thank you so much! you even have comments!

Ill go through it here in a bit, ill see if i can get this thing working!


I appreciate it!

Zack

imzack

btw, what is SPI.transfer?  i havent seen this yet, im still kinda new to all of this.

imzack

I also see a pin called SS, what pin is this?   example "digitalWrite(SS, HIGH);

xaxxx

The approach of CrossRoads is very good and I myself like to read the datasheet and understand the protocol, but sometimes I'm interested more in programing fast and clean. This is the main reason I recently started working with arduino. If you don't have the ledcontrol library you should download it an compile an empty sketch with it. Here, I've looked it up for you and you'll find some examples in there as well:
http://arduino.cc/playground/Main/LedControl#Source

Techone

Here my method. I use shiftOut(); to send the data into the MAX7219.

And I recomend you download the datasheet here : http://www.datasheetcatalog.org/datasheet/maxim/MAX7219-MAX7221.pdf and read it multiple times to make sure you understand. Don't forget about R set. It limit the current going into a segment. I set my circuit about 56 K to 68 K.  I want to limit the segments current between 5 mA to 15 mA to be safe. If you want a bigger currents, well use a transistor to control the segments.

Here my test code. My code is simply this : Display 1,2,3,4,5,6,7,8 for a second and display 8,7,6,5,4,3,2,1. I use Mode 3. For a multiples leds paterns, use No Mode. To further understand this... read the datasheet. The MAX7219 init is in the setup. I don't use SPI. I use shiftOut(). I have the flexibility of choosing the output pins.  And beside, I have 70 chips at my place. I better learn to use it.  I do have a code for a multiples leds. I use No Mode. The other test code simply count 0 to 255 in binary. Use Leds arrays has leds.

If you want to design program for the MAX7219, think in HEX and in BINARY. Use Arrays a lots. And a lots of for() loops.

Mode 3 test code.

Code: [Select]

const byte datapin = 12;
const byte latchpin = 11;
const byte clockpin = 10;

void setup()
{
pinMode(datapin, OUTPUT);
pinMode(latchpin, OUTPUT);
pinMode(clockpin, OUTPUT);
// set : Normal Mode
digitalWrite(latchpin, LOW);
shiftOut(datapin, clockpin, MSBFIRST, 0x0C );
shiftOut(datapin, clockpin, MSBFIRST, 0x01 );
digitalWrite(latchpin, HIGH);
delay(5);
// set : Normal Operation
digitalWrite(latchpin, LOW);
shiftOut(datapin, clockpin, MSBFIRST, 0x0F );
shiftOut(datapin, clockpin, MSBFIRST, 0x00 );
digitalWrite(latchpin, HIGH);
delay(5);
// set : Intensity
digitalWrite(latchpin, LOW);
shiftOut(datapin, clockpin, MSBFIRST, 0x0A );
shiftOut(datapin, clockpin, MSBFIRST, 0x0B );
digitalWrite(latchpin, HIGH);
delay(5);
// set : Numbers of digits
digitalWrite(latchpin, LOW);
shiftOut(datapin, clockpin, MSBFIRST, 0x0B );
shiftOut(datapin, clockpin, MSBFIRST, 0x07 );
digitalWrite(latchpin, HIGH);
delay(5);
// set : Decode Mode Register
digitalWrite(latchpin, LOW);
shiftOut(datapin, clockpin, MSBFIRST, 0x09 );
shiftOut(datapin, clockpin, MSBFIRST, 0xFF );
digitalWrite(latchpin, HIGH);
}

void loop()
{
byte j;

for (int i=1;i<9;i++)
{
   digitalWrite(latchpin, LOW);
   shiftOut(datapin, clockpin, MSBFIRST, i );
   shiftOut(datapin, clockpin, MSBFIRST, i );
   digitalWrite(latchpin, HIGH);
   delay(5);
}
delay(2000);
j = 8;
for (int i=1;i<9;i++)
{
   digitalWrite(latchpin, LOW);
   shiftOut(datapin, clockpin, MSBFIRST, i );
   shiftOut(datapin, clockpin, MSBFIRST, j );
   digitalWrite(latchpin, HIGH);
   delay(5);
   j--;
}
delay(2000);



Here the No Mode test code.

Code: [Select]

const byte datapin = 12;
const byte latchpin = 11;
const byte clockpin = 10;

byte display_number[8] = {0,0,0,0,0,0,0,0};

void setup()
{
pinMode(datapin, OUTPUT);
pinMode(latchpin, OUTPUT);
pinMode(clockpin, OUTPUT);
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
// set : Normal Mode
digitalWrite(latchpin, LOW);
shiftOut(datapin, clockpin, MSBFIRST, 0x0C );
shiftOut(datapin, clockpin, MSBFIRST, 0x01 );
digitalWrite(latchpin, HIGH);
delay(5);
// set : Normal Operation
digitalWrite(latchpin, LOW);
shiftOut(datapin, clockpin, MSBFIRST, 0x0F );
shiftOut(datapin, clockpin, MSBFIRST, 0x00 );
digitalWrite(latchpin, HIGH);
delay(5);
// set : Intensity
digitalWrite(latchpin, LOW);
shiftOut(datapin, clockpin, MSBFIRST, 0x0A );
shiftOut(datapin, clockpin, MSBFIRST, 0x0B );
digitalWrite(latchpin, HIGH);
delay(5);
// set : Numbers of digits
digitalWrite(latchpin, LOW);
shiftOut(datapin, clockpin, MSBFIRST, 0x0B );
shiftOut(datapin, clockpin, MSBFIRST, 0x07 );
digitalWrite(latchpin, HIGH);
delay(5);
// set : Decode Mode Register
digitalWrite(latchpin, LOW);
shiftOut(datapin, clockpin, MSBFIRST, 0x09 );
shiftOut(datapin, clockpin, MSBFIRST, 0x00 );
digitalWrite(latchpin, HIGH);
delay(5);
// set display to zero
display_the_max();
}

void loop()
{
for (int j=0;j<8;j++)
{
   for (int i=0;i<256;i++)
   {
     display_number[j]=lowByte(i);
     display_the_max();
     delay(25);
   } 
   display_number[j]=0;
   display_the_max();
   digitalWrite(13, HIGH);
   delay(5000);
   digitalWrite(13, LOW);
}
digitalWrite(13, HIGH);
delay(2000);
digitalWrite(13, LOW);
}

void display_the_max()
{
for (int k=0; k<8;k++)
{
    digitalWrite(latchpin, LOW);
    shiftOut(datapin, clockpin, MSBFIRST, (k+1));
    shiftOut(datapin, clockpin, MSBFIRST, display_number[k]);
    digitalWrite(latchpin, HIGH);
    delay(5);
}   



CrossRoads

SS is slave select. To control the 7219 via its SPI interface, you take slave select low, use the internal hardware to send the data out real quick (write 2 bytes, vs all the software needed for the shiftout() command), and then take slave select high to let the 7219 know you're done talking to it.

The ATmega has built in hardware for the Serial Peripheral Interface - your code writes a byte to a register, the hardware uses buit in shift registers to crank the data out.  Versus the software method which does something like this:

set the output pin to match bit 0 of the byte being sent (if using LSBFIRST, and pin7 if using MSBFIRST)
set the clock pin high
set the clock pin low
set the output pin to match bit 1 of the byte being sent (or bit 6, see above)
set the clock pin high
set the clock pin low
(and repeat 6 more times)
so a lot more steps involved.

ledcontrol.h does all the same stuff, it just hides that it is doing it in a "library", and also uses the software shift method as it lets you define the pins to be used. SPI uses pins 13-12-11, and you can define something besides pin 10 if you want as the SS pin.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

xl97

Does the 7219 support SPI? I thought only the 7221 version did? (I could be wrong though?)

I too found the ledControl library a nice and easy lib to use.. especially for beginners.. but if it does support SPI.. its a good thing to learn about.


Nick Gammon


btw, what is SPI.transfer?  i havent seen this yet, im still kinda new to all of this.


http://www.gammon.com.au/spi
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

imzack

Techone, MSBfirst, is that a variable that arduino knows?  or is that something else?

Also still having trouble with getting the LedControl.h library, it says it's not there.  I tried to update it, says its 1.0, im on ubuntu btw.

"
Alarm_Clock.cpp:31:88: error: LedControl.h: No such file or directory
Alarm_Clock:44: error: 'LedControl' does not name a type
Alarm_Clock.cpp: In function 'void setup()':
Alarm_Clock:146: error: 'lc' was not declared in this scope
Alarm_Clock.cpp: In function 'void loop()':
Alarm_Clock:247: error: 'lc' was not declared in this scope
Alarm_Clock:255: error: 'lc' was not declared in this scope
Alarm_Clock:263: error: 'lc' was not declared in this scope
Alarm_Clock:271: error: 'lc' was not declared in this scope
"

imzack

#11
Apr 20, 2012, 05:41 am Last Edit: Apr 20, 2012, 12:04 pm by Nick Gammon Reason: 1
Code: [Select]

#include <LiquidCrystal.h>  //Used for the LCD Module   HAVE TO GO TO SKETCH-> Import Library...
#include "LedControl.h"  // This library helps with using the 7-segment driver(MAX72XX)

/*
pin 12 is DataIn
pin 11 is CLK
pin 10 is LOAD (Latch)

*/
const int Data = 12;        // Data line into the chip
const int CLK =  11;       //CLOCK Signal for the chip
const int LOAD = 10;       //The pin to control the latch or load value on chip
const int driver_num = 1;  //number of MAX72XX's we are linked or using in total


LedControl lc=LedControl(Data,CLK,LOAD,driver_num);  //this line assigns the pins to what we have labeled in the comment block above (is it lc or lcl in this line?)  
                                                   //The last number states how many devices aka how many MAX72XX's  Note: the lc is just a variable that is created






       int countOnes = 0;  // will keep track of seconds

       int countTwos = 0;  // will keep track of tens of seconds

       int countThrees = 0;  // will keep track of minutes

       int countFours = 0;  // will keep track of tens of minutes

       int countFives = 0;  // will keep track of hours

       int countSix = 0;  // will keep track of tens of hours

       int amPM = 0;      // low for AM, High for pm



//INTERRUPT SERVICE ROUTINE FOR TIMER 1

   ISR(TIMER1_OVF_vect) {

             TCNT1 = 0xC180;      //this resets the timer to this preloaded value after every overflow

             milliseconds = milliseconds + 1;    //increments this 1 each time an overflow occurs

                         }




void setup() {                   //Code to be run 1 time goes here


//*******************************************TIMER INITIALIZATION CODE************************************************************
TIMSK1 = 0x01;
TCCR1A = 0x00;
TCNT1 = 0xC180;        //Reload value of 49,536, so we can get a 1millisecond clock...
TCCR1B = 0x01;        //No prescaler  (page 137 Atmel Datasheet)
//***********************************************************************************************************************************


//wakes up the MAX72XX from power-saving mode
lc.shutdown(0,false);


//set a medium brightness for the display
lc.setIntensity(0,8);  //this sets intesity for digits 0 to 3


//clear display
lc.clearDisplay(0);



// initialize the digital pin as an output.
// Pin 13 has an LED connected on most Arduino boards:


}




This is my header files that i include btw and the setup that im doing....  direct copy and paste...

Moderator edit: [code] ... [/code] tags added. (Nick Gammon)


imzack

No, i was under the assumption that the newest version had it included...  let me see about doing that, im in ubuntu and still trying to get used to this aswell.

imzack

Ok, i went to the site on the arduino section on the LEDControl section, downloaded the zip, extracted it, then put it in the library folder.

I now ran my code, and with everything wired up the only segments thus far that are lit up is the decimal point, ill see whats wrong with my code now, but im happy to see progress!

Thanks,

Zack

Go Up