f-log

just another web log

10 Nov 2013:
Right now we can get serious with the Pi Matrix.

So we know how to show any pattern in any single row or column. The way to show a image/frame is to show each row of the pattern one at a time over and over again. This produces an after image affect that means your eyes do not see the time when the LED are off.

If you watch the video at the end of the post you can see the square in the middle, which is the following code.
#!/usr/bin/python
# square.py
# Light square on the Pi Matrix demonstrating simple multiplexing
import smbus     #Python access to I2C bus
import time     #For timing delays

addr = 0x20     #I2C bus address of the 23017
dirA = 0x00     #PortA I/O direction register
dirB = 0x01     #PortB I/O direction register
portA = 0x12     #PortA data register
portB = 0x13     #PortB data register

print "Pi Matrix - Square demo"
bus = smbus.SMBus(1)    #Use '1' for newer Pi's and 0 for revision 1 Pi's
bus.write_byte_data(addr, dirA, 0x00)    #all zeros = all outputs on PortA
bus.write_byte_data(addr, dirB, 0x00)     #all zeros = all outputs on PortB

for i in range(0,500) :
    bus.write_byte_data(addr, portA, 0x00)    
    bus.write_byte_data(addr, portB, ~0b00100000)
    bus.write_byte_data(addr, portA, 0b00111100)    
    time.sleep(0.001)
    bus.write_byte_data(addr, portA, 0x00)    
    bus.write_byte_data(addr, portB, ~0b00010000)
    bus.write_byte_data(addr, portA, 0b00100100)    
    time.sleep(0.001)
    bus.write_byte_data(addr, portA, 0x00)    
    bus.write_byte_data(addr, portB, ~0b00001000)
    bus.write_byte_data(addr, portA, 0b00100100)    
    time.sleep(0.001)
    bus.write_byte_data(addr, portA, 0x00)    
    bus.write_byte_data(addr, portB, ~0b00000100)
    bus.write_byte_data(addr, portA, 0b00111100)    
    time.sleep(0.001)

print "Clearing display"
bus.write_byte_data(addr, portA, 0x00)


You should make note of a couple of things. Firstly, there are four blocks of code in the loop each starting by setting the column(Anodes) to low/off and a sleep instruction set to just 1x1000/second. That means each row clears the old column data and that after setting the new column pattern(more on that in a moment) the code pauses. If we did not clear the column data before changing row there would be an additional after image affect and that is what I saw here before I added the clear. The top of the square would be draw correctly but then for a brief moment the same four LEDs were on on the second row before the sides of the square for that row were set on their own, creating pink LEDs in between the red ones. The delay stops the LEDs flashing on and then immediately off again. When missing the LEDs in the image look dull.
The actual drawing is a manual bit-bash to set the row(the ~ is bit-wise NOT, which inverts the bit pattern) and then to set the column pattern of the row.
00100000 00111100
00010000 00100100
00001000 00100100
00000100 00111100

Hard coded values are not very useful so lets move on.

#!/usr/bin/python
# singleframe.py
# Single frame on the Pi Matrix demonstrating simple multiplexing
import smbus     #Python access to I2C bus
import time     #For timing delays

addr = 0x20     #I2C bus address of the 23017
dirA = 0x00     #PortA I/O direction register
dirB = 0x01     #PortB I/O direction register
portA = 0x12     #PortA data register
portB = 0x13     #PortB data register

print "Pi Matrix - Single frame demo"
bus = smbus.SMBus(1)    #Use '1' for newer Pi's and 0 for revision 1 Pi's
bus.write_byte_data(addr, dirA, 0x00)    #all zeros = all outputs on PortA
bus.write_byte_data(addr, dirB, 0x00)     #all zeros = all outputs on PortB

def drawRow(row,display):
    bus.write_byte_data(addr, portA, 0x00) # clear the column data    
    bus.write_byte_data(addr, portB, ~row) # set the row
    bus.write_byte_data(addr, portA, display) # set column data    
    time.sleep(0.001)

def drawFrame(data):
    for b in range(0,7+1) :
        drawRow(0x01<<b,data[b])

for i in range(0,500) :
    drawFrame([
0b10000000,
0b01000000,
0b00100000,
0b00010000,
0b00001000,
0b00000100,
0b00000010,
0b00000001])

print "Clearing display"
bus.write_byte_data(addr, portA, 0x00)

Here the "def NAME" are functions and code calls 'drawFrame' with my array that then in turn calls 'drawRow' for each line in the array. This is repeated 500 hundred times, which seems to show the diagonal line image for about five seconds.

Never has a diagonal line been more interesting or more boring, so on with the show.

#!/usr/bin/python
# animation.py
# Multiple frame animation on the Pi Matrix demonstrating simple multiplexing
import smbus     #Python access to I2C bus
import time     #For timing delays

addr = 0x20     #I2C bus address of the 23017
dirA = 0x00     #PortA I/O direction register
dirB = 0x01     #PortB I/O direction register
portA = 0x12     #PortA data register
portB = 0x13     #PortB data register

print "Pi Matrix - Multiple frame demo"
bus = smbus.SMBus(1)    #Use '1' for newer Pi's and 0 for revision 1 Pi's
bus.write_byte_data(addr, dirA, 0x00)    #all zeros = all outputs on PortA
bus.write_byte_data(addr, dirB, 0x00)     #all zeros = all outputs on PortB

def drawRow(row,display):
    bus.write_byte_data(addr, portA, 0x00) # clear the column data    
    bus.write_byte_data(addr, portB, ~row) # set the row
    bus.write_byte_data(addr, portA, display) # set column data    
    time.sleep(0.001)

def drawImage(data):
    for b in range(0,7+1) :
        drawRow(0x01<<b,data[b])

def drawFrame(frameData,refreshes):
    for i in range(0,refreshes) :
        drawImage(frameData)

def displayAnimation(frames,frameRefreshes):
    for i in range(0, len(frames)) :
        if (i<len(frameRefreshes)) :
            fallBackRefresh=frameRefreshes[i]
        drawFrame(frames[i], fallBackRefresh)

displayAnimation([
[
0b00000000,
0b00000000,
0b00000000,
0b00000001,
0b00000001,
0b00000001,
0b00000001,
0b00000001]
,[
0b00000000,
0b00000000,
0b00000001,
0b00000010,
0b00000010,
0b00000010,
0b00000010,
0b00000010]
,[
0b00000000,
0b00000001,
0b00000010,
0b00000101,
0b00000101,
0b00000100,
0b00000100,
0b00000101]
,[
0b00000000,
0b00000011,
0b00000100,
0b00001110,
0b00001110,
0b00001000,
0b00001000,
0b00001101]
,[
0b00000000,
0b00000111,
0b00001000,
0b00010110,
0b00010110,
0b00010000,
0b00010000,
0b00010101]
,[
0b00000000,
0b00001111,
0b00010000,
0b00111011,
0b00111011,
0b00100000,
0b00100000,
0b00110101]
,[
0b00000000,
0b00011110,
0b00100001,
0b01011011,
0b01011011,
0b01000000,
0b01000000,
0b01010101]
,[
0b00000000,
0b00111100,
0b01000011,
0b11101101,
0b11101101,
0b10000001,
0b10000001,
0b11010101]
,[
0b00000000,
0b00111100,
0b01000011,
0b10110111,
0b10110111,
0b10000001,
0b10000001,
0b10101011]
,[
0b00000000,
0b00111100,
0b01000011,
0b11101101,
0b11101101,
0b10000001,
0b10000001,
0b11010101]
,[
0b00000000,
0b00111100,
0b01000011,
0b10110111,
0b10110111,
0b10000001,
0b10000001,
0b10101011]
,[
0b00000000,
0b00111100,
0b01000011,
0b11101101,
0b11101101,
0b10000001,
0b10000001,
0b11010101]
,[
0b00000000,
0b00111100,
0b01000011,
0b10110111,
0b10110111,
0b10000001,
0b10000001,
0b10101011]
]
,[20])

print "Clearing display"
bus.write_byte_data(addr, portA, 0x00)

Here 'drawRow' is exactly the same but 'drawFrame' has been renamed 'drawImage' and 'drawFrame' is now the control for how many times the image is shown per frame. 'displayAnimation' is the main controlling loop, picking each frame and checking if it has a refresh rate and if not using the previous one.

Instead of entering the refresh value once for each frame I could just enter 20 once in the second array and all the frames picked it up, but if I ever need different frames to be different lengths all I have to do is add the individual frame refreshes.

This is the video I uploaded to YouTube containing the row/column demos followed by the square, single frame and animation demos.

10 Nov 2013:
Pi Matrix failure story time
Story time.

So, I had the Pi Matrix working and stepping through rows and columns but for some reason I was convinced that I had the Matrix connected upside down. Seemed quite logical if the Matrix was connected upside down the anodes and cathodes would be the wrong way around.

Without turning off the Pi I disconnected the LED matrix reoriented it and reconnected. The first signs of panic were now setting in. During the removal process, even though the LEDs were set to all be off some flashed and the same when I reconnected.

Never mind its all low voltage, isn't it?

Running the tutorial that should have turned on all the LEDs only showed four.
Raspberry Pi with PI Matrix board attached with the LED matrix attached upside down causing only four LEDs to light

Uh oh!

Then I ran the had the Pi Matrix working and stepping through row and column Python scripts and sometimes nothing would light and other times weird patterns showed for each row/column.

Step 1: Shutdown the Pi disconnect the Pi Matrix and connect my friend the Berryclip. The Berryclip worked perfectly so I had not completely fried the Pi. It did not test all the GPIO pins but it was as reassuring as I could get.

Step 2: Shutdown and remove the Berryclip and reconnect the Pi Matrix this time with the LED matrix the correct way around. I made sure to mark the LED matrix with a sharpie so I would know which away around was correct.

Step 3: Power up the Pi and run the tutorial, the test commands and the row/column demos. Oh dear! Same dodgy patterns!
At this point it is worth pointing out I had made a mistake. The mark was on the wrong corner so I was RECONNECTING the matrix the wrong way up. But of course I had not noticed which lead to...

Step 4: Replace the chip on the Pi Matrix. It had been noted that damaging the Pi Matrix was not an expensive mistake as the chip was less than £1 to replace. So duly went googling and found the MCP23017-E/SP for 99p but trying to get cheap shipping was fun... what with minimum purchase volumes and min order values, in the end ebay was the only place that would sell me one for 99p. £2.58 total. Wait for delivery, replace chip and ... same result (remember I was not aware the matrix was upside down). Which lead to...

Step 5: Replace the LED matrix. Still cheap but not quite as cheap as the chip I order what the image showed to be exactly what I wanted. £3.30. wait for delivery and... Find it is a 3rd of the size so the pins would not line up, that will teach me to read the sizes and descriptions more closely.

Step 6: I wondered what was broken/burned out on the Pi Matrix. So I noted the patterns that were shown, shutdown and reoriented the LED matrix once again. Notebook in hand I waited to record more messed up LED patterns.

Oh, now it all works <slap target="head" />

Now we can move on to something more exciting.
10 Nov 2013:
Pi Matrix row and columns step demos
Previously we setup the Pi Matrix and used command line tools to operate it, now we can use Python to control the output.

The Matrix works by setting a bit pattern for which columns to light and second one for which rows. This means it is very easy to have a single row or column lit.

In this column step demo set all the cathodes on portB low/ground and then set portA to the bit patterns.
00000001
00000010
00000100
00001000
00010000
00100000
01000000
10000000
one after another via bit shifting. Video at the end of this post.
                                                    

#!/usr/bin/python
#
# columnstep.py
#
# Lights each column in turn on the Pi Matrix

import smbus     #Python access to I2C bus
import time     #For timing delays

# Definitions for the MCP23017 chip
addr = 0x20     #I2C bus address of the 23017
dirA = 0x00     #PortA I/O direction register
dirB = 0x01     #PortB I/O direction register
portA = 0x12     #PortA data register
portB = 0x13     #PortB data register

# Program start
print "Pi Matrix - Column step demo"
bus = smbus.SMBus(1)    #Use '1' for newer Pi's and 0 for revision 1 Pi's
bus.write_byte_data(addr, dirA, 0x00)    #all zeros = all outputs on PortA
bus.write_byte_data(addr, dirB, 0x00)     #all zeros = all outputs on PortB
bus.write_byte_data(addr, portB, 0x00)     #set row outputs low

for i in range(0,7+1) :
bus.write_byte_data(addr, portA, 0x01<<i) #set column outputs low = LEDs off
time.sleep(0.25)                 #keep LEDs off for 0.5 secs

bus.write_byte_data(addr, portA, 0x00) #set column outputs low = LEDs off


Now instead of setting the cathodes low/ground we set the anodes all high and walk through the inverse bit patterns setting each column on in turn.
11111110
11111101
11111011
11110111
11101111
11011111
10111111
01111111

#!/usr/bin/python
#
# rowstep.py
#
# Lights each row in turn on the Pi Matrix

import smbus     #Python access to I2C bus
import time     #For timing delays

# Definitions for the MCP23017 chip
addr = 0x20     #I2C bus address of the 23017
dirA = 0x00     #PortA I/O direction register
dirB = 0x01     #PortB I/O direction register
portA = 0x12     #PortA data register
portB = 0x13     #PortB data register

# Program start
print "Pi Matrix - Row step demo"
bus = smbus.SMBus(1)    #Use '1' for newer Pi's and 0 for revision 1 Pi's
bus.write_byte_data(addr, dirA, 0x00)    #all zeros = all outputs on PortA
bus.write_byte_data(addr, dirB, 0x00)     #all zeros = all outputs on PortB
bus.write_byte_data(addr, portA, 0xFF)     #set column outputs high

for i in range(0,7+1) :
bus.write_byte_data(addr, portB, ~(0x01<<i)) #set column outputs low = LEDs off
time.sleep(0.25)                 #keep LEDs off for 0.5 secs

bus.write_byte_data(addr, portA, 0x00)


This video shows the two programs above and then some of the more complex ones I will describe in later posts.


Next up, a story.. are we sitting comfortably?
10 Nov 2013:
Pi Matrix powered up
Pi Matrix is the next Raspberry Pi soldering project. It is made up of a 8x8 Red LED matrix a controller chip, many resistors and the various header pins an connectors.

A daunting task made easy by the fact that each trace on the board has a elliptical solder point that made each of my joints look very professional, not to much solder and not too little. Secondly, almost half the header pins supplied do not have to be connected for the board to work. They are supplied to as break-out pins for a extension projects, which is a very good idea.

raspberry pi with PI Matrix board attached and the LED matrix upside to the right

After soldering the unit up and connecting the LED matrix I connected it up to the PI and started following the Mag Pi issue 13 Introduction to the Pi Matrix .

There are a number of setup requirements to enable the I2C support in the Pi.

edit /etc/modprobe.d/raspi-blacklist.conf
and comment out the blacklist command for the i2c-bcm2708 module.
#blacklist i2c-bcm2708
So it was black listed and not loaded, now its not black listed it can be loaded.

then edit /etc/modules and add the module
i2c-dev

install the python and I2C support
sudo apt-get update
sudo apt-get install python-smbus
sudo apt-get install i2c-tools


finally add the "pi" user to the "i2c" group
sudo adduser pi i2c

and reboot.

Now using the "i2cset" command initialise the data ports (these commands are set for the newer Raspberry Pis)
i2cset -y 1 0x20 0x00 0x00
i2cset -y 1 0x20 0x01 0x00


and test the matrix by setting all the cathodes to 0 (low/ground) and all the anodes high.
i2cset -y 1 0x20 0x13 0x00
ic2set -y 1 0x20 0x12 0xFF

-bash: ic2set: command not found
oops they printed a typo
i2cset -y 1 0x20 0x12 0xFF
which should turn all 64 LEDs on, but if you only got four turn everything off, turn the LED matrix around and reattach it.
i2cset -y 1 0x20 0x12 0x00
to turn all the LEDs off again.
This photo shows the PiMatrix incorrectly attached with the ports set to have all LEDs ON, but instead shows four lit.
Raspberry Pi with PI Matrix board attached with the LED matrix attached upside down causing only four LEDs to light

Next time we can get some python controlling the Pi Matrix.
loading results, please wait loading animateloading animateloading animate
[More tags]
rss feed

email

root

flog archives


Disclaimer:
This page is by me for me, if you are not me then please be aware of the following
I am not responsible for anything that works or does not work including files and pages made available at www.jumpstation.co.uk I am also not responsible for any information(or what you or others do with it) available at www.jumpstation.co.uk
In fact I'm not responsible for anything ever, so there!

[Pay4Foss banner long]