Learn EV3 Python‎ > ‎

LCD Screen

Working with the LCD screen is rather complicated and in any case the EV3's screen is small and hard to see (no backlight) so I would suggest that working with the screen should be a low priority for you as you learn EV3 Python.

The EV3 has a 178 x 128 pixels monochrome (black and white) LCD. The coordinates of the top-left pixel are (0, 0) and the coordinates of the bottom-right pixel are (177, 127).

To interact with the LCD you will mainly be using a powerful graphics library called Pillow which is part of standard Python rather than something unique to EV3 Python. Note that Pillow evolved out of the Python Image Library (PIL). There is some documentation on the EV3 Python bindings page but you will find much more detailed documentation in the official Pillow documentation HERE, especially the documentation on the ImageDraw module. The ImageDraw module provides the following methods:
  • arc(xy, start, end, fill=None)
  • bitmap(xy, bitmap, fill=None)
  • chord(xy, start, end, fill=None, outline=None)
  • ellipse(xy, fill=None, outline=None)
  • line(xy, fill=None, width=0)
  • pieslice(xy, start, end, fill=None, outline=None)
  • point(xy, fill=None)
  • polygon(xy, fill=None, outline=None)
  • rectangle(xy, fill=None, outline=None)
  • text(xy, text, fill=None, font=None, anchor=None, spacing=0, align="left")
  • multiline_text(xy, text, fill=None, font=None, anchor=None, spacing=0, align="left")
  • textsize(text, font=None, spacing=0)
  • multiline_textsize(text, font=None, spacing=0)
You may find this tutorial to be a good place to start.  Multiline_text does not seem to be available currently in EV3 Python and there may be others that are not available.

Warning: EV3 Python scripts using the LCD screen can easily be run successfully from within the Brickman interface or using VS Code with the EV3 extension but if you want to run such scripts from within an SSH session (PuTTY or MobaXTerm, for example), you should follow the instructions at the bottom of this page. 

Smiley / Grumpy
This script draws two circles for eyes then an arc (in this case half an ellipse) which alternates between opening upwards (a smile) and opening downwards (grumpy). Warning: Do NOT run this script from within Brickman because it runs forever and therefore you need to stop it with a long press on the Back button but this does NOT properly stop the program, presumably due to some kind of bug in Brickman. You CAN successfully run this program from SSH, stopping it with Ctrl-C, but don't forget to read the note at the end of this page.

#!/usr/bin/env python3
from time import sleep
from ev3dev.ev3 import *

lcd = Screen()

smile = True

while True:
    lcd.clear()

    # lcd.draw returns a PIL.ImageDraw handle
    lcd.draw.ellipse(( 20, 20,  60, 60))
    lcd.draw.ellipse((118, 20, 158, 60))

    if smile:
        lcd.draw.arc((20, 80, 158, 100), 0, 180)
    else:
        lcd.draw.arc((20, 80, 158, 100), 180, 360)

    smile = not smile  # toggle between True and False

    # Update lcd display
    lcd.update() # Applies pending changes to the screen.
    # Nothing will be drawn on the lcd screen
    # until this function is called.

    sleep(1)

Note that the screen.draw.ellipse() command has parameters that are the top-left corner and bottom-right corner of a bounding box (an imaginary box that would contain the ellipse). The  screen.draw.arc() command needs the same pair of coordinates and also needs a starting angle and an ending angle, both in degrees. Angles are measured from 3 o’clock, increasing clockwise.

Display text with the print() function

The print() function is simpler to use than the draw.text() function since it just works - it does not require you to create a Screen object and it does not require you to update the screen in order to see the text. You do not need to import the ev3dev.ev3 module in order to use print(). It automatically wraps text at the right edge of the screen and automatically scrolls the text up as necessary. You can change the font as in the following example. When you set a font that setting will be remembered until you turn off the brick so if you do not set the font like this then the script will use whatever font was used last time it was set.

The script below shows how to set the desired font. You can get a list of available fonts by running  ls /usr/share/consolefonts in the SSH terminal. Note that the fonts used by the print() function and the procedure for specifying one, are different from the fonts used by the draw.text() function and the procedure for specifying one. The script below also shows how you can stop the print() function from starting a new line after printing. 

#!/usr/bin/env python3
# from ev3dev.ev3 import *   # NOT NEEDED
from time import sleep
import os
os.system('setfont Lat15-TerminusBold14')
# os.system('setfont Lat15-TerminusBold32x16')  # Try this larger font
# A full list of fonts can be found with `ls /usr/share/consolefonts`

print('EV3 Python rules!')
print()  # print a blank line

print('EV3', 'Python rules!')  # comma means continue on same line

# By default, the invisible parameter 'end' is the new line character
print('EV3')    # A new line will be started after this
print('Python rules!')

# Here the 'end' parameter is replaced
# with an empty string so no new line is begun
print('EV3', end='')
print('Python rules!')

# Here the 'end' parameter is replaced
# with a space character so no new line is begun
print('EV3', end=' ')
print('Python rules!')

sleep(15)  # display the text long enough for it to be seen

Display text with the draw.text() function
Displaying text with the draw.text() function is more difficult but gives you more control, as you can specify where the text is to be placed and whether the text should be black or white.

This script will display 'Hello, World' as small white text in a black rectangle with 'THIS TEXT IS BLACK' displayed in black in the lower half of the screen. The coordinates in the parameter of the text() function refer to the top left corner of the text.

#!/usr/bin/env python3
from ev3dev.ev3 import *
from time import sleep

lcd = Screen()
lcd.draw.rectangle((0,0,177,40), fill='black')
lcd.draw.text((48,13),'Hello, world.', fill='white')
lcd.draw.text((36,80),'THIS TEXT IS BLACK')
lcd.update()
sleep(6)

Center Text Horizontally
The textsize() function is not used to set the size of text, it is used to get the size (length and height) of a text string in pixels. For example, it might return the tuple (111, 15). The first element of the tuple (element zero) can be used to center text horizontally as shown below. To center text vertically just subtract half the text height from 64. The center of the screen can be assumed to be at (89, 64). This script also prints the value of the textsize tuple.

#!/usr/bin/env python3
# aligns text to the centre horiztally. 
from ev3dev.ev3 import *
from time import sleep

lcd = Screen()

mystring = 'EV3 Python rules!'

lcd.clear()
size = lcd.draw.textsize(mystring) # returns a tuple
lcd.draw.text((20, 20), 'textsize = '+str(size))
# screen height = 128 pixels, so vertical center is
# at 64 pixels, so place text (height 11 pixels) at
# 5 pixels above the center, at 59
lcd.draw.text((89-size[0]/2, 59), mystring)
lcd.update()
sleep(10)

Wrap text
The print() function wraps text automatically but the draw.text() function does not. The following script wraps the text onto a new line after every 30 characters. This isn't proper 'word wrap' since it does not try to detect the spaces between words.

#!/usr/bin/env python3
# wraps text to a new line after every 30 characters
from ev3dev.ev3 import *
from time import sleep

lcd = Screen()

mystring = 'This is a very long string! '*7
newstring=''
for i in range(len(mystring)):
    # len(mystring) gives the number of characters
    newstring = newstring+mystring[i]
    if i%30 == 29:  # modulo, or remainder after division
        newstring = newstring+'\n'
        # \n is the new line character

lcd.clear()
lcd.draw.text((0,0), newstring)
lcd.update()
sleep(10)

Use larger fonts
The draw.text() command used above without any 'font' argument draws very small text. Specifying a 'font' argument allows you to choose from a wide range of fonts and sizes that you can visualise HEREThe capital letters in the names of the fonts have the following meanings: B= Bold, I=Italic, O=Oblique (similar to italic), S=?, R=? As an example I will use the luBS24 font which is therefore bold, size 24. As usual, before using SSH to run this script or any other script that draws on the LCD screen you should follow the instructions at the bottom of this page. Note that the line 'from PIL import...' is not really needed since the draw.text() function is imported with ev3dev.ev3.

#!/usr/bin/env python3
from ev3dev.ev3 import *
from time import sleep
import ev3dev.fonts as fonts
from PIL import Image, ImageDraw, ImageFont  # this line is optional

lcd = Screen()
lcd.draw.text((10,10), 'Hello World!', font=fonts.load('luBS24'))
lcd.update()
sleep(8)

Install fonts to use even bigger text
To use fonts and font sizes other than the ones included by default in version 0.8.0 and beyond you can install additional fonts. Denis D, a top contributor to the ev3dev project, suggested this procedure to install and use additional fonts:
  1. Install the MS core fonts package:
    sudo apt-get install ttf-mscorefonts-installer
  2. Run this to see what fonts have been installed:
    ls /usr/share/fonts/truetype/msttcorefonts/
Here's a sample script using one of the newly available fonts, a TrueType (scalable) font called Arial in size 75 (a.k.a. huge):

#!/usr/bin/env python3
from ev3dev.ev3 import *
from PIL import Image, ImageDraw, ImageFont  
from time import sleep

lcd = Screen()

f = ImageFont.truetype('/usr/share/fonts/truetype/msttcorefonts/Arial.ttf', 75)
lcd.draw.text((3,0), 'Hello', font=f)
lcd.draw.text((2,55), 'world', font=f)
lcd.update()

sleep(7)  # if run from Brickman, need time to see displayed image

Here is the result: 

Display an image file
I thank Denis D, a top contributor to the ev3dev project, for helping me with this code.

Before you can display an image file, you have to have an image file to display! Most of the popular image formats should work (jpg, bmp, gif, png etc). I suggest you start by doing what I did: copy all the standard Lego EV3 BMP image files that are included with the free Lego EV3 software into a directory called 'pics' within your 'robot' directory. You can see the BMP files listed on this page and at the bottom of that page is a link to a zip file (328KB) containing the 107 monochrome BMP files, each one perfectly dimensioned to fit the EV3 screen (178*128 pixels). If you prefer, you can find the files on your PC in a location like this: C:\Program Files (x86)\LEGO Software\LEGO MINDSTORMS EV3 Home Edition\Resources\BrickResources\Retail\Images\files. The 'Program Files (x86)' folder may also be called simply 'Program Files'. If you are getting the files from your PC I suggest you copy all the BMP files (not the RGF files) into a single folder.

Decompress the zip file then create a directory inside your robot directory, name it 'pics' and upload the decompressed BMP files to the pics directory. This is very easy to do if you are using MobaXTerm as I recommend. Once you've done all of that you should be ready to run the following script, replacing 'Bomb.bmp' with the name of the image file of your choice.

#!/usr/bin/env python3
from ev3dev.ev3 import *
from time import sleep
from PIL import Image

lcd = Screen()

logo = Image.open('pics/Bomb.bmp')
lcd.image.paste(logo, (0,0))
lcd.update()
sleep(5) # when running from Brickman, need time to admire image

Here is the result:

The script runs easily from Brickman (don't forget to make your program file executable). If you want to run your script via SSH then be sure to read the paragraph at the bottom of this page.

Note that the line from PIL import Image is not really needed since the Image module is imported already by from ev3dev.ev3 import *. However, it is still a good idea to include from PIL import Image because it makes it more obvious that the Image module is being used.

How to capture a screenshot of the EV3 screen

If you are using VS Code with the EV3 extension then taking a screenshot is as easy as right-clicking the green 'connected' button in the EV3 Device Browser and choosing 'Take Screenshot'. Don't forget to save the image, and be sure to choose a convenient location for that saved image.

How to run from the terminal a script that writes to the EV3's LCD display
This is for people who are not using the VS Code with the EV3 extension. If you run code that addresses the screen from an SSH session without following these instructions then you may experience two problems:
  • the Brickman display may reappear before your script stops running, even after a second or less
  • or you might have the opposite problem: when the script stops it may take a minute or two before the the screen reverts back to the Brickman interface
David L, a top contributor to the ev3dev project, gave me the following advice:

Easy way, recommended unless you are a perfectionist. Disadvantage: you will then see a little blinking cursor at the bottom of a small 'dead square' somewhere on the screen (you can see the cursor in the 'Hello World' image higher up this page). :
  1. Run sudo chvt 6. This just switches the display to show you an empty terminal instead of Brickman, so that Brickman doesn't mess with you. You will need to enter the password for robot, which is 'maker'.
  2. Run your program. You should see it show up on the EV3 display, as you'd expect. You can stop the script running with Ctrl+C if necessary. You can work from this terminal like normal, run your program multiple times, etc.
  3. Run sudo chvt 1 to get Brickman back
Perfectionist's wayDisadvantage: More steps and you will be using a copy of the EV3's tiny display.
  1. Run sudo chvt 6. This just switches the display to show you an empty terminal instead of Brickman, so that Brickman doesn't mess with you. You will need to enter the password for robot, which is 'maker'.
  2. Run sudo conspy. This will make your SSH session show the same terminal that is on the EV3's display. Log in to the prompt it shows you with login = robot and password = maker.
  3. Run your program. You should see it show up on the EV3 display, as you'd expect. You can stop the script running with Ctrl+C if necessary. You can work from this terminal like normal, run your program multiple times, etc.
  4. Press the ESC key on the PC 3 times to exit the display terminal
  5. Run sudo chvt 1 to get Brickman back
Subpages (1): BMP image collection
Comments