Would you like to drive a 8×8 LED matrix with a Raspberry Pi and Lazarus? But you do not know how? Then find a solution proposed in this article.
In Lazarus, there are not as many libraries available as in Python for the Raspberry Pi. Therefore Python is rightly the first choice for projects with the Pi. In special cases, however, a solution with Lazarus is better!
I think that’s always when there should be additionally a visualization on a screen. I want to show you in this article exactly this variant.
A prerequisite for the use of Lazarus that the corresponding component is also supported on a library. Otherwise, you have to be an expert to code them yourself.
Such a library is the TMS LCL HW Pack for Raspberry Pi TMS software. With it, a number of different displays from Adafruit can be easily controlled:
- 4 digit 7 segment display
- Adafruit monochrome 128 × 32 OLED graphic display
- Adafruit barometrix pressure / temperature sensor
- Adafruit 8 × 8 LED matrix I2C
I want to use the 8 × 8 LED matrix. The only condition is that the matrix is connected via the I2C bus.
Install TMS Library
Before you start, the package for Lazarus must be downloaded and installed.
You can find the webpage with further information about the included components at:
The download of Lazarus Packages can be found on github:
Download the zip file and unzip all the files in your lib folder (or another folder of your choice).
In the Lazarus menu, select PACKAGE and PACKAGE FILE (* .lpk). Then select your folder from the LPK file.
Click on the button USE and then INSTALL . So the package is goint to be installed and Lazarus recompiled. On the Raspberry Pi this takes a little longer than on a PC. But the speed is still okay.
After restarting Lazarus the new components are available immediately.
Connect the matrix to your Raspberry
The connection of the matrix is done quickly through the I2C.
- VCC >> 3V3 (Pin 1)
- GND >> GND (Pin 6)
- SDA >> SDA (Pin 3, GPIO2)
- SDL SDL >> (Pin 5, GPIO3)
If everything is working correctly, you can use the command i2cdetect for a check. Open a terminal window and enter the command. The result is the address of the 8×8 matrix.
Coding in Lazarus
The address of the I2C bus with i2cdetect is displayed in hexadecimal. But in Lazarus we need a decimal number.
If you convert the value by yourstelf, it can be entered in the Object Inspector.
But it is easier to use the Freepascal function HEX2DEC directly in the source code. The display is prepared with a few commands.
m8x8.I2CAddress:=HEX2DEC('$70'); m8x8.Open; m8x8.Rotation: = MR90; m8x8.DisplayOn; m8x8.Clear;
Sample app: mini animation
To show you how to code this in Lazarus, we create a sample app. It should allow us to design a small animation and run it. Plus usw a few functions for moving and inverting the 8×8 matrix.
LEDs on / off
The component of TMS provides a few functions for turning on and off LEDs.
The two main procedures are DrawPixel (x, y) to turn on and ClearPixel (x, y) to turn off of LEDs. With these two functions we will also work in the sample app.
But there is more, this I would like to briefly introduce:
- procedure DrawChar (x, y: byte; c: char);
Draws a letter or number to the specified position.
- procedure DrawArrow (x, y: byte; ADirection: TArrowDirection);
Draws an arrow at the specified position. Possible values for ADirection are AUP , Adown , aLeft and aright .
- procedure DrawVertLine (x, y1, y2: integer);
Draws a vertical line.
- procedure DrawHorzLine (x1, x2, y: integer);
Draws a horizontal line.
As already mentioned, the strength of Lazarus is visualization. Therefore, the 8×8 matrix is to be displayed in the window on the screen.
As appropriate component I choose a TShape object. For an easy use, we create a two-dimensional array:
Led: array [0..7,0..7] of TShape;
In the create procedure of the main form the shapes are all generated and set correctly. Then they are all inserted in a panel (Panel1) .
for x:=0 to 7 do
for y:=0 to 7 do
with Led[x,y] do
In the property Tag the x and y coordinate is stored. We use that value to recalculate the coordinates of x and y when some clicks on a LED on the screen.
This is done in the procedure LedOnClick.
TMainForm.LedOnClick procedure (Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var w, x1, y1: integer; begin w:=TShape (Sender).Tag; x1:=w div 10; y1:=w-x1*10; Label1.Caption:='X'+IntToStr(x1)+'Y:'+IntToStr(y1); SetPixel(x1,y1,not GetPixel(x1,y1)); m8x8.Display; end;
Pixel on and off
If you want to control not only the real LED matrix but also a visual one on the screen, you can do it with a common function.
Instead of the existing variants DrawPixel and ClearPixel I introduce two new elements in the sample app.
The function GetPixel(x,y) , which returns as a result the status (LED on or off) as a boolean value.
function TMainForm.GetPixel(x, y: integer): boolean; begin result:=false; if x>7 then exit; if x<0 then exit; if y>7 then exit; if y<0 then exit; if TShape(Led[x,y]).Brush.Color=clRed then result:=true else result:=false; end;
And the procedure SetPixel (x, y, status) , which sets the status of the LED as a boolean value.
procedure TMainForm.SetPixel(x, y: integer; LedOn: boolean); begin if x>7 then exit; if x<0 then exit; if y>7 then exit; if y<0 then exit; if LedOn=true then begin TShape(Led[x,y]).Brush.Color:=clRed; m8x8.DrawPixel(x,y); end else begin TShape(Led[x,y]).Brush.Color:=clWhite; m8x8.ClearPixel(x,y); end; end;
Manipulate LEDs or pixels
With this function and procedure, it is now very easy to perform simple manipulations in the real and visual matrix.
The matrix can be passed through with two loops.
E.g. to clear the matrix.
for x:=0 to 7 do for y:=0 to 7 do SetPixel(x,y,false); 8x8.Display;
It is important to know that the real matrix is only updated after you use the command Display. So this must be the command at the end of each manipulation.
Just as easy is it to invert the matrix.
Another manipulation could be to move the LED image to the left.
for x:=0 to 6 do for y:=0 to 7 do SetPixel(x,y,GetPixel(x+1,y)); for y:=0 to 7 do SetPixel(7,y,false); m8x8.Display;
For the other three directions, have a look in the source code of the sample app.
Now gets animated!
Animate means to us in this case that we previously have to save a matrix image. For this we transform the states of the LEDs (ON = 1 and OFF = 0) in a 64-character string and store it in a TListBox component.
The implementation of the code works just over two loops. Is a LED on, is added a 1 to a string s. If the LED is off, the string s is expanded with a 0. Finished!
if GetPixel(x,y)=true then s:=s+'1' else s:=s+'0';
To display the matrix picture again, a reverse procedure is missing. The 64-character string is again broken down piece by piece in an x and y coordinate, and turned on the LED:
procedure TMainForm.StrToMatrix8x8(value : string); var x, y: integer; begin for x:=0 to 7 do for y:=0 to 7 do if copy(value,x*8+y+ 1,1)='1' then SetPixel(x,y,true) else SetPixel(x,y,false); m8x8.Display; end;
The actual animation takes place via a timer component. At each timer event a global variable is incremented and the next “image” from the listbox with procedure StrToMatrix8x8 is displayed.
That was it! In the sample app a few more functions are implemented: to change the order of images and to open and save the animation.
Have fun trying!
Source code of the sample app mini animation
use tar xfvz en.tar.gz
Website of TMS software: https://www.tmssoftware.com/site/tmslclhwpack.asp
TMS package on github: https://github.com/tmssoftware/TMS-LCL-HW-Pack-for-Raspberry-Pi