Using a Max7219 8×8 LED Matrix with an ATTINY85, like Trinket or DigiSpark

While waiting for part two of the handheld construction article, I thought I’d give you a little distraction about interfacing an ATTINY85 to an 8×8 LED Matrix using the Max7219 chip.

ATTINY85LEDMatrix1Been working on getting either a DigiSpark or Trinket to work with one of my 8×8 LED matrix displays. Connection is simple, but the maxmatrix library doesn’t seem to like the ATTINY85 processor. So, I went looking for something that did or, at least, getting enough knowledge to bit bang my way to displaying SOMETHING on the little display. Well, I found some code to do this, but it is not very pretty and doesn’t do enough. However, it does give a good demo of how to make these arrays do something and, even better, work with the confines of the ATTINY85 processor.
The code shows how turn on and off pixels (a specific LED in the matrix, to be more precise) and send a ‘bitmap’ to the display.
Cool stuff. Could be another game or, perhaps, a temperature display, mood indicator, etc.

You can grab the code I used (middle of the page) here…http://www.avrfreaks.net/…/max7219-8×8-dot-matrix-led-drive…

FYI-To connect it:
PB0 -> DIN
PB1 -> CS
PB2 -> CLK
+5 -> VCC
GND -> GND

Pretty easy. ATTINY85LEDMatrix21

The code I found puts a smiley face, inverts the screen, frowny face, etc. up on the display. I took out the inversion as it takes too much time.  This code, which is unattributed as the poster on the AVR forum did not credit the code, is a good start, but needs work.  I thought about modifying it to handle ASCII text, but that will be a ways off yet. I have several things to finish up before then. 

I’d love to see what you can do with this, so drop us a note in the comments or send me an email and I’d be happy to write it up and post it here.

Code:

/*
  One MAX7219 connected to an 8x8 LED matrix.
 */

#include <avr/io.h>
#include <util/delay.h>

#define CLK_HIGH()  PORTB |= (1<<PB2)
#define CLK_LOW()   PORTB &= ~(1<<PB2)
#define CS_HIGH()   PORTB |= (1<<PB1)
#define CS_LOW()    PORTB &= ~(1<<PB1)
#define DATA_HIGH() PORTB |= (1<<PB0)
#define DATA_LOW()  PORTB &= ~(1<<PB0)
#define INIT_PORT() DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2)

uint8_t smile[8] = {
        0b00000000,
        0b01100110,
        0b01100110,
        0b00011000,
        0b00011000,
        0b10000001,
        0b01000010,
        0b00111100};

uint8_t sad[8] = {
        0b00000000,
        0b01100110,
        0b01100110,
        0b00011000,
        0b00011000,
        0b00000000,
        0b00111100,
        0b01000010,
};


void spi_send(uint8_t data)
{
    uint8_t i;

    for (i = 0; i < 8; i++, data <<= 1)
    {
  CLK_LOW();
  if (data & 0x80)
      DATA_HIGH();
  else
      DATA_LOW();
  CLK_HIGH();
    }
    
}

void max7219_writec(uint8_t high_byte, uint8_t low_byte)
{
    CS_LOW();
    spi_send(high_byte);
    spi_send(low_byte);
    CS_HIGH();
}

void max7219_clear(void)
{
    uint8_t i;
    for (i = 0; i < 8; i++)
    {
  max7219_writec(i+1, 0);
    }
}

void max7219_init(void)
{
    INIT_PORT();
    // Decode mode: none
    max7219_writec(0x09, 0);
    // Intensity: 3 (0-15)
    max7219_writec(0x0A, 1);
    // Scan limit: All "digits" (rows) on
    max7219_writec(0x0B, 7);
    // Shutdown register: Display on
    max7219_writec(0x0C, 1);
    // Display test: off
    max7219_writec(0x0F, 0);
    max7219_clear();
}


uint8_t display[8];

void update_display(void)
{
    uint8_t i;

    for (i = 0; i < 8; i++)
    {
  max7219_writec(i+1, display[i]);
    }
}

void image(uint8_t im[8])
{
    uint8_t i;

    for (i = 0; i < 8; i++)
  display[i] = im[i];
}

void set_pixel(uint8_t r, uint8_t c, uint8_t value)
{
    switch (value)
    {
    case 0: // Clear bit
  display[r] &= (uint8_t) ~(0x80 >> c);
  break;
    case 1: // Set bit
  display[r] |= (0x80 >> c);
  break;
    default: // XOR bit
  display[r] ^= (0x80 >> c);
  break;
    }
}


int main(void)
{
    uint8_t i;
    
    max7219_init();
    
    while(1)
    {
  image(sad);
  update_display();
  _delay_ms(500);
  image(smile);
  update_display();
  _delay_ms(500);

  // Invert display
//  for (i = 0 ; i < 8*8; i++)
//  {
//      set_pixel(i / 8, i % 8, 2);
//      update_display();
//      _delay_ms(10);
//  }
  _delay_ms(500);
    }
}

 

 

Advertisements

MAX7219 Dot Matrix LED Display: Assembling and usage

I have to admit something: I have a major fetish.

XANDER - WIN_20140226_131628 (2)No, get your mind out of the gutter. This fetish is for displays. Any kind of display. LCD, LED, Plasma even CRT. I love them all. If it lights up, I like it. So, while perusing eBay for some parts and Arduino shields, I came across these nifty little 8×8 LED arrays.  They were complete with a driver board. You can get them assembled or in little kits. And, the best part? They are very cheap.  $13US for a package of five kits. (See here) (Please note: the listing may not be here for long, but you can find lots of similar listing for the same or less.)

Since I like to put things together, I got the kits. They arrived about a week and a half later. Only problem was that there was zero documentation.  Fortunately, the boards are nicely done and silkscreened with parts.  So, after building all five, I have a pretty good strategy for putting them together.  I wish to share that with you , so…read on!XANDER - WIN_20140226_131933 (2)

Your kit should include:

  1. 1 PC Board
  2. 1 10Kohm, 1/4 watt resistor (BROWN, BLACK, BLACK, RED)
  3. 1 10uF capacitor
  4. 1 .1 uF capacitor
  5. 1 MAX7219 IC
  6. 1 20 pin IC Socket
  7. 2 8 pin female headers
  8. 2 5 pin, 90 degree headers
  9. 1 8×8 LED array

Assembly is easy.  Start with the parts that will be hidden by the array: the two capacitors and the resistor.

The 10uF capacitor, which looks like a cylinder, is polarized and can only be inserted one way. Look at it and you will see a thick, white arrow with a minus sign. Holding the board so the silkscreened writing is facing you, and you can read the writing, carefully bend the legs of the capacitor at about 90 degrees, with the minus sign facing you. Insert it into the board. Refer to the photo below for correct placement. XANDER - WIN_20140226_131056 Bend its legs slight so it does not fall out.

Next, insert the 0.1uF capacitor. It does not matter which way it goes. Bend the legs slightly to hold it in place.

Insert the resistor into the 10K resistor holes. Bend the legs slightly to hold it in place.

Turn the board over and solder each of the legs into place. Trim the excess once you have soldered the parts.

Insert the 20 pin socket. You may want to place a piece of tape over the socket to keep it from falling out when you turn the board over to solder it into place.  Solder the socket, making sure it is flat and level against the board.

Once the socket is soldered into place, insert the MAX chip.  You may need to bend one or both sides so it fits. You can do so by placing the chip on its side, on a flat surface and gently apply pressure while slightly bending the chip down. It won’t take much.

Next, solder the two five pin headers into the board. Make sure you solder the shorter ends into the board. One header goes into each side of the board into the holes marked VCC,GND,DIN, CS and CLK.XANDER - WIN_20140226_131346

Now, take the LED array and turn over so the pins are sticking up. Insert one of the 8 pin female headers onto each set of pins. Doing this before soldering the headers onto the board makes it easier than soldering and then inserting the array.  XANDER - WIN_20140226_131417 (2)

Next, insert the array with the board, making sure the NOTCHED side is toward the bottom of the board, see the picture for proper orientation.

Congratulations, you have assembled your display!

Next, we need to test it.

Go here and read up on the array and how it works. You can download sample code and the library to use in your own code.

I am using this library, available on Google’s code repository.

Download the MaxMatrix library from the Google site and import it into your Arduino Libraries via the Arduino’s Import Library function. Then, load up the example code and upload to your UNO or other compatible device.  When it runs, you should see the message scrolling by, letter by letter.

If you have more than one, you can chain up to four together (using MaxMatrix) and see the message more clearly.

I have four of them chained together and connected to Arduino Mini Pro, which is like a UNO, only really small.

When chaining them together, remember that the one that is connected to the Arduino is where the message STARTS. So, arrange them in order from the last connected to the first. When the message scrolls, it should appear normally, scrolling from right to left.

scrollerI have gone a bit further and used one of my PC’s to send data to the 4 8×8 array’s. Currently, I am just sending the date and time, but I have plans to feed it news and weather information as well. Possibly using wireless. For now, I am just using the USB interface. I wrote the PC code using Visual Studio 2005 and the serial port control.  See below for my sample code.

There are a ton of uses for these nifty and cheap devices. From a scrolling marquee to crude handheld gaming. 

Have fun!

SAMPLE VB.NET CODE:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim thetime As String
        thetime = ”  ” + Format(Now) + ”   “
        If SerialPort1.IsOpen Then
            SerialPort1.Write(thetime)
        Else
            SerialPort1.Open()
            SerialPort1.Write(thetime)
        End If
        Timer1.Interval = 10000
        Timer1.Start() 

End Sub

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Dim thetime As String
        thetime = ”  ” + Format(Now) + ”   “
        If SerialPort1.IsOpen Then
            SerialPort1.Write(thetime)
        Else
            SerialPort1.Open()
            SerialPort1.Write(thetime)
            SerialPort1.Write(“~”)
        End If
End Sub