Picaxe control of Adafruit 8x8 LED matrix with i2c backpack

stevesmythe

Senior Member
I couldn't find any Picaxe Basic code examples for controlling this display, but this thread described how to control a 4-digit, 7-segment display that uses the same backpack.

8x8 matrix LED.jpg

Building on the information in that thread, I have produced the following code that demonstrates how to turn on/off, dim or flash the display and control which pixels are lit up. By giving it its own thread, people searching on the Internet for information on how to control this module (as opposed to the 7-seg version) will find it more easily.

1. After initialising, the starting address ($00) is sent, then (in brackets in the example below), the string of data containing the value for each of the 8 columns, where the "value" is the row value in binary, MSB first. However, the row value is a 16 bit value and only the first 8 bits are physically connected. So, every other byte is ignored. I have put $AA into each of these in the example below, just so they are not confused with anything else.
2. For some reason, the physical row 0 (at the top if you look at the display with the Adafruit logo at the bottom) is wired as the MSB so all the other rows are shifted down.

Code:
#picaxe 08m2    ' Define PICAXE 08M2
#no_data        ' Ignore EEPROM data - loads program faster

Initialise:                ' Initialise pins and set up variables
LET dirsC = %00000110        ' Make pins C.1 & C.2 outputs; rest as inputs
LET pinsC = %00000000         ' Turn off all outputs on port C
Hi2cSETUP  i2cmaster,%11100000, i2cfast, i2cbyte
PAUSE 1 ; wait 1 ms for the display chip to initialise
Hi2cOUT ($21) ; start clock/oscillator
' $00 turns off the whole row

Main:
Hi2cOUT ($80) ; clear the display


' turn on all LEDS in each column (%11111111=$FF)
' x = don't care (not connected) but I have used $AA
'    start !  col0 x  , col1 x  , col2 x  , col3 x  , col4 x , col5 x  'col6 x  , col 7 x
Hi2cOUT $00, ($FF, $AA, $FF, $AA, $FF, $AA, $FF, $AA, $FF,$AA, $FF, $AA, $FF,$AA, $FF, $AA)
Hi2cOUT ($81) ; turn on the display
pause 1000

' now draw a smiley face
'  xxxx 
' x    x
'x x  x x
'x      x
'x x  x x
'x  xx  x
' x    x
'  xxxx



'    columns
'7 6 5 4 3 2 1 0
'0 0 1 1 1 1 0 0 row0
'0 1 0 0 0 0 1 0 row1
'1 0 1 0 0 1 0 1 row2
'1 0 0 0 0 0 0 1 row3
'1 0 1 0 0 1 0 1 row4
'1 0 0 1 1 0 0 1 row5
'0 1 0 0 0 0 1 0 row6
'0 0 1 1 1 1 0 0 row7

'Adafruit logo at bottom

'MOVE TOP ROW (ROW0) TO bottom (MSB) AND SHIFT EVERYTHING ELSE DOWN=>BIT0->BIT7, BIT7->BIT6, BIT6->BIT5

' becomes....

'    columns
'7 6 5 4 3 2 1 0
'0 1 0 0 0 0 1 0 row0
'1 0 1 0 0 1 0 1 row1
'1 0 0 0 0 0 0 1 row2
'1 0 1 0 0 1 0 1 row3
'1 0 0 1 1 0 0 1 row4
'0 1 0 0 0 0 1 0 row5
'0 0 1 1 1 1 0 0 row6
'0 0 1 1 1 1 0 0 row7

'Adafruit logo at bottom

'for example, after shifting row 0, column 0 becomes %00011110 or $1E
'    start !  col0 x  , col1 x  , col2 x  , col3 x  , col4 x , col5 x  'col6 x  , col 7 x
Hi2cOUT $00, ($1E, $AA,$21, $AA, $CA, $AA, $D0, $AA, $D0,$AA, $CA, $AA, $21,$AA, $1E, $AA)
Hi2cOUT ($81) ; turn on the display
pause 1000

Hi2cOUT ($E0) 'dim the display (range $E0 to $EF)
pause 1000
Hi2cOUT ($EF) ' full brightness again
pause 1000
Hi2cOUT ($83) 'blink the display ($83=2Hz blink, $85=1Hz, $87=0.5Hz)
pause 3000
Hi2cOUT ($80) ; turn off the display
pause 1000
goto main
 
Last edited:

techElder

Well-known member
Last edited:

stevesmythe

Senior Member
I found the 8x8 matrix tricky until I worked out what was going on. I think they must have designed the backpack for 7-seg plus decimal point then, when porting to 8x8 matrix found that row0 was connected to the backpack on the same line that the decimal point from the 7-seg was connected to. Not very intuitive!
 

uniformswift

New Member
Hi guys, thanks heaps for posting that code! This had me scratching my head for a while until I found this link. I got it working with an 08m2, but tried to write a similar program for a 14m2 and a 20m2, but to no avail. For some reason I couldn't get it to even start. I'm sorry if this is a stupid question as I'm fairly new to all this, but how would I go about making this work for 14m2 and/or 20m2 chips and what would I have to change?
Cheers,
Eli.
 

hippy

Technical Support
Staff member
I got it working with an 08m2, but tried to write a similar program for a 14m2 and a 20m2, but to no avail. For some reason I couldn't get it to even start. I'm sorry if this is a stupid question as I'm fairly new to all this, but how would I go about making this work for 14m2 and/or 20m2 chips and what would I have to change?
I2C code for an 08M2 should work on any M2 or X2 chip without change. As long as the correct pins are used for the SDA and SCL connections it should just work.

The only thing I note which is 08M2 specific in the code here are the two "Let dirsC=" and "Let pinsC=" commands at the top. You could try commenting those out but I would not have expected them to cause things not to work.

The other thing to try is replacing the I2CFAST in the HI2CSETUP command with I2CSLOW.

If it is your own developed code you are using it may be worth posting that in case there is something which requires change to make it work on other than the 08M2.
 

OLDmarty

Senior Member
For the newbies that didn't realise, the very first line of the code above should be #picaxe 08m2.....the "#" is missing ;-)
 

system11

Member
As I had a large number (81) characters to get hex strings for, I quickly made this perl script, if you have comments in your code like the below you can just paste them at the script instead of typing them in manually and doing all the row manipulation and binary conversion by hand. Supports X/1 and ./0 for input, I found X and . to be more readable when designing the characters, comment quote is stripped if found at the start of the line.

Code:
'........
'........
'XX.XX.XX
'X..X..X.
'XX.XX.X.
'X...X.X.
'XX.XX.XX
'........
Script output:

Code:
Enter character as 8 lines of X and . or 1 and 0:
'........
'........
'XX.XX.XX
'X..X..X.
'XX.XX.X.
'X...X.X.
'XX.XX.XX
'........
$22,$3e,$0,$3a,$2e,$0,$2a,$3e
You could easily modify it to pad the output with $aa or whatever beyween the bytes that matter in the I2C command, it doesn't at the moment because I needed to store all these in the scratchpad and it was too wasteful. Script below:

Code:
#!/usr/bin/perl -w
# turn 8x8 graphic inputs into hex value strings for use in i2c code
# note rows are shifted up a 'bit' hence foreach loop order
# columns are 7 .) 0 instead of 0 -< 7 as a user would input them
#
my @cline;

while(1) {
  print "Enter character as 8 lines of X and . or 1 and 0:\n";

  # because rows all need moving up, lazy way of re-ordering them via input
  foreach (7,0,1,2,3,4,5,6) {
    my $line = <STDIN>;
    chomp($line);
    $cline[$_] = lc($line);
    $cline[$_] =~ s/x/1/g;
    $cline[$_] =~ s/\./0/g;
    # strip leading ' if pasted from pic comment
    $cline[$_] =~ s/\'//;
  }

  # this is very ugly
  my $c=",";
  foreach (7,6,5,4,3,2,1,0) {
    my $hexcol = "";
    for(my $row = 7; $row >= 0; $row--) {
      $hexcol .= substr($cline[$row],$_,1);
    }
    if($_ == 0) { $c=""; }
    printf("\$%x$c", oct("0b$hexcol"));
  }
  print"\n\n";
}
 
Last edited:
Top