13 Nov 2013

Led matrix graphical user interface on the RaspberryPi

Yesterday, I plugged into my Raspberry Pi a little i2c LED Matrix. I wrote Python class to interact with it but I tought it would be really interesting to toggle the matrix's LED with a graphical user interface on the Pi itself. This is exactly what I done and you can take a look at the result in the following Youtube video:



To connections between the matrix and the Pi are really simple, you just need to connect 4 signals directly together : GND, 3V3, DATA and CLK. There is no need for pull-up resistor on the i2c clock and data lines, I presume the Pi already have them. The display is designed for 5V but it works really well at 3.3V.

For using i2c on the Raspberry Pi, you need to make some little configurations and install the Python libraries. These steps are outlined on this Instructable tutorial.

You will also need the PyQt4 package, install it with:
sudo apt-get install python-qt4

The final Python script is listed below. The LedMatrix class is the i2c communication part of my program and MatrixWidget is the graphical user interface. The Qt windows part does essentially two things, it reacts to mouse press and draw an array of ellipse (the virtual LEDs).

If you have any questions with the code, just ask in the comments and I will be glad to help. Happy coding!

#!/usr/bin/env python
import sys
from smbus import SMBus
from PyQt4 import QtGui, QtCore

class LedMatrix():
    ADDRESS = 0x70
    OSCILLATOR_ON = 0x21
    BLINK_CMD = 0x80
    DISPLAY_ON = 0x01
    BLINK_2HZ = 0x01
    BLINK_1HZ = 0x02
    BLINK_HALFHZ = 0x03
    BRIGHTNESS_CMD = 0xE0
    POS_X = (128, 1, 2, 4, 8, 16, 32, 64)
    POSn_X = (127, 254, 253, 251, 247, 239, 223, 191)
    POS_Y = (7, 0, 1, 2, 3, 4, 5, 6)

    def __init__(self, blink=0, brightness=15):
        self.bus = SMBus(1) #device on i2c channel 1
        self.bus.write_byte(self.ADDRESS, self.OSCILLATOR_ON)
        self.bus.write_byte(self.ADDRESS, self.BLINK_CMD|self.DISPLAY_ON|(blink<<1))
        self.bus.write_byte(self.ADDRESS, self.BRIGHTNESS_CMD|brightness)
        self.clearBuffer()

    def setBrightness(self, brightness):
        self.bus.write_byte(self.ADDRESS, self.BRIGHTNESS_CMD|brightness)
        
    def setBlinkRate(self, blink):      
        self.bus.write_byte(self.ADDRESS, self.BLINK_CMD|self.DISPLAY_ON|(blink<<1))
    
    def setPixel(self, x, y, state):
        if state:
            self.buffer[self.POS_Y[y]]|=self.POS_X[x]
        else:
            self.buffer[self.POS_Y[y]]&=self.POSn_X[x]

    def clearBuffer(self):
        self.buffer = [0]*8
    
    def writeBuffer(self):
        data = []
        for row in self.buffer:
            data.append(0)
            data.append(row)
        self.bus.write_block_data(self.ADDRESS, 0x00, data)

class MatrixWidget(QtGui.QWidget):
    def __init__(self):
        super(MatrixWidget, self).__init__()     
        self.w=20
        self.setGeometry(300, 300, self.w*10, self.w*10)
        self.setWindowTitle('Led Matrix')
        self.clearPixelBuffer()
        self.setFixedSize(self.width(),self.height())
        self.leds = LedMatrix()
        self.show()

    def clearPixelBuffer(self):
        self.buffer = [[0 for _ in range(8)] for _ in range(8)]

    def mousePressEvent(self, QMouseEvent):
        x = QMouseEvent.pos().x()
        y = QMouseEvent.pos().y()
        x = x/self.w-1
        y = y/self.w-1
        if x==-1 or y==-1 or x==8 or y==8:
            self.clearPixelBuffer()
            self.update()
            self.leds.clearBuffer()
            self.leds.writeBuffer()
            return
        pixel = self.buffer[x][y]
        if pixel:
            self.leds.setPixel(x, y, False)
            self.buffer[x][y]=0
        else:
            self.leds.setPixel(x, y, True)
            self.buffer[x][y]=1        
        self.update()
        self.leds.writeBuffer()
    
    def paintEvent(self, e):
        qp = QtGui.QPainter()
        qp.begin(self)
        self.refresh(qp, e)
        qp.end()
    
    def drawLed(self, qp, x, y):
        state = self.buffer[x][y]
        if state:
            col = QtGui.QColor("#FFF71C") #bright yellow
        else:
            col = QtGui.QColor("#373511") #dark yellow
        qp.setPen(col)
        qp.setBrush(col)
        qp.drawEllipse(self.w+self.w*x,self.w+self.w*y,self.w-3,self.w-3)
           
    def refresh(self, qp, event):
        qp.setBrush(QtCore.Qt.black)
        qp.drawRect(event.rect())
        for y in range(8):
            for x in range(8):
                self.drawLed(qp, x, y)

if __name__=="__main__":
    app = QtGui.QApplication(sys.argv)
    ex = MatrixWidget()
    sys.exit(app.exec_())

3 Nov 2013

I'm back for the winter

Hi everyone, I suppose some of you noticed that I have been silent for a couple months now. I have been pretty this summer with work and sport. At the beginning of October, I also moved into my new house so I had to move my workbench and all my electronic stuff. That was a lot of work!

Even if I have not posted any blog post, I have been working on a side project with a friend from Spain, Arrizen. The project is about domotics and you can learn more about it on our project website : Koollaborate.

Here is an excerpt from the website describing the project :

This project is about creating a home network of autonomous little sensor/actuator node called ‘Motes’. The Mote is a generic pluggable module comprising a brain (┬ÁController) and a communication module. The Motes are slaves to a central controller. Motes with different ┬ÁC will be designed; they will share code librairies and projects should compile and work on the different architectures.

The goal of this project is to provide a cheap module for home automation that you can program to your will and make it communicate information. It will help someone focus on the project he wants to do and not designing controllers board over and over.


Domotics is a subject that interests me a lot because it involves electricity, electronics, programming, human machine interface, communication protocols, internet, servers...

For an house to be intelligent, it needs to be able communicate information to you, even if you are not home. In the next article, I will show you how to use the Python programming language to send emails and text messages on your cellphone.