- To control an LED matrix connected to an SPI MAX7219 chip, create the following matrixControl.py script:
#!/usr/bin/python3 # matrixControl.py import wiringpi import time MAX7219_NOOP = 0x00 DIG0=0x01; DIG1=0x02; DIG2=0x03; DIG3=0x04 DIG4=0x05; DIG5=0x06; DIG6=0x07; DIG7=0x08 MAX7219_DIGIT=[DIG0,DIG1,DIG2,DIG3,DIG4,DIG5,DIG6,DIG7] MAX7219_DECODEMODE = 0x09 MAX7219_INTENSITY = 0x0A MAX7219_SCANLIMIT = 0x0B MAX7219_SHUTDOWN = 0x0C MAX7219_DISPLAYTEST = 0x0F SPI_CS=1 SPI_SPEED=100000 class matrix(): def __init__(self,DEBUG=False): self.DEBUG=DEBUG wiringpi.wiringPiSPISetup(SPI_CS,SPI_SPEED) self.sendCmd(MAX7219_SCANLIMIT, 8) # enable outputs self.sendCmd(MAX7219_DECODEMODE, 0) # no digit decode self.sendCmd(MAX7219_DISPLAYTEST, 0) # display test off self.clear() self.brightness(7) # brightness 0-15 self.sendCmd(MAX7219_SHUTDOWN, 1) # start display def sendCmd(self, register, data): buffer=(register<<8)+data buffer=buffer.to_bytes(2, byteorder='big') if self.DEBUG:print("Send byte: 0x%04x"% int.from_bytes(buffer,'big')) wiringpi.wiringPiSPIDataRW(SPI_CS,buffer) if self.DEBUG:print("Response: 0x%04x"% int.from_bytes(buffer,'big')) return buffer def clear(self): if self.DEBUG:print("Clear") for row in MAX7219_DIGIT: self.sendCmd(row + 1, 0) def brightness(self,intensity): self.sendCmd(MAX7219_INTENSITY, intensity % 16) def letterK(matrix): print("K") K=(0x0066763e1e366646).to_bytes(8, byteorder='big') for idx,value in enumerate(K): matrix.sendCmd(idx+1,value) def main(): myMatrix=matrix(DEBUG=True) letterK(myMatrix) while(1): time.sleep(5) myMatrix.clear()
time.sleep(5) letterK(myMatrix) if __name__ == '__main__': main() #End
Running the script (python3 matrixControl.py) displays the letter K.
- We can use a GUI to control the output of the LED matrix using matrixMenu.py:
#!/usr/bin/python3 #matrixMenu.py import tkinter as TK import time import matrixControl as MC #Enable/Disable DEBUG DEBUG = True #Set display sizes BUTTON_SIZE = 10 NUM_BUTTON = 8 NUM_LIGHTS=NUM_BUTTON*NUM_BUTTON MAX_VALUE=0xFFFFFFFFFFFFFFFF MARGIN = 2 WINDOW_H = MARGIN+((BUTTON_SIZE+MARGIN)*NUM_BUTTON) WINDOW_W = WINDOW_H TEXT_WIDTH=int(2+((NUM_BUTTON*NUM_BUTTON)/4)) LIGHTOFFON=["red4","red"] OFF = 0; ON = 1 colBg = "black" def isBitSet(value,bit): return (value>>bit & 1) def setBit(value,bit,state=1): mask=1<<bit if state==1: value|=mask else: value&=~mask return value def toggleBit(value,bit): state=isBitSet(value,bit) value=setBit(value,bit,not state) return value class matrixGUI(TK.Frame): def __init__(self,parent,matrix): self.parent = parent self.matrix=matrix #Light Status self.lightStatus=0 #Add a canvas area ready for drawing on self.canvas = TK.Canvas(parent, width=WINDOW_W, height=WINDOW_H, background=colBg) self.canvas.pack() #Add some "lights" to the canvas self.light = [] for iy in range(NUM_BUTTON): for ix in range(NUM_BUTTON): x = MARGIN+MARGIN+((MARGIN+BUTTON_SIZE)*ix) y = MARGIN+MARGIN+((MARGIN+BUTTON_SIZE)*iy) self.light.append(self.canvas.create_rectangle(x,y, x+BUTTON_SIZE,y+BUTTON_SIZE, fill=LIGHTOFFON[OFF])) #Add other items self.codeText=TK.StringVar() self.codeText.trace("w", self.changedCode) self.generateCode() code=TK.Entry(parent,textvariable=self.codeText, justify=TK.CENTER,width=TEXT_WIDTH) code.pack() #Bind to canvas not tk (only respond to lights) self.canvas.bind('<Button-1>', self.mouseClick) def mouseClick(self,event): itemsClicked=self.canvas.find_overlapping(event.x, event.y,event.x+1,event.y+1) for item in itemsClicked: self.toggleLight(item) def setLight(self,num): state=isBitSet(self.lightStatus,num) self.canvas.itemconfig(self.light[num], fill=LIGHTOFFON[state]) def toggleLight(self,num): if num != 0: self.lightStatus=toggleBit(self.lightStatus,num-1) self.setLight(num-1) self.generateCode() def generateCode(self): self.codeText.set("0x%016x"%self.lightStatus) def changedCode(self,*args): updated=False try: codeValue=int(self.codeText.get(),16) if(codeValue>MAX_VALUE): codeValue=codeValue>>4 self.updateLight(codeValue) updated=True except: self.generateCode() updated=False return updated def updateLight(self,lightsetting): self.lightStatus=lightsetting for num in range(NUM_LIGHTS): self.setLight(num) self.generateCode() self.updateHardware() def updateHardware(self): sendBytes=self.lightStatus.to_bytes(NUM_BUTTON, byteorder='big') print(sendBytes) for idx,row in enumerate(MC.MAX7219_DIGIT): response = self.matrix.sendCmd(row,sendBytes[idx]) print(response) def main(): global root root=TK.Tk() root.title("Matrix GUI") myMatrixHW=MC.matrix(DEBUG) myMatrixGUI=matrixGUI(root,myMatrixHW) TK.mainloop() if __name__ == '__main__': main() #End
- The Matrix GUI allows us to switch each of the LEDs on/off by clicking on each of the squares (or by directly entering the hexadecimal value) to create the required pattern:
Using the Matrix GUI to control the 8 x 8 LED matrix