Pages: [1] 2   Go Down
Author Topic: MAX7219 with Arduino  (Read 3017 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 549
Posts: 27425
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
// 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 ");

}
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

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

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
Logged

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

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

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

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

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

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
 
Logged

Toronto, Canada
Offline Offline
Edison Member
*
Karma: 2
Posts: 1234
"Keep it R.E.I.L. - "Research, Experiment, Investigate and Learn"
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 549
Posts: 27425
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

0
Offline Offline
Edison Member
*
Karma: 8
Posts: 1251
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Logged


Global Moderator
Melbourne, Australia
Online Online
Brattain Member
*****
Karma: 511
Posts: 19333
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

http://www.gammon.com.au/spi
Logged

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

Please post technical questions on the forum - not to me by personal message. Thanks a lot.

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

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

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

 
Code:
#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)
« Last Edit: April 20, 2012, 05:04:19 am by Nick Gammon » Logged

0
Offline Offline
Edison Member
*
Karma: 8
Posts: 1251
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Did you add the LedControl library to your library directory?
Logged


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

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

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

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
Logged

Pages: [1] 2   Go Up
Jump to: