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 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. If you run code that addresses the screen from the SSH session without following the instructions at the bottom of this page then you may experience two problems:
  • the Brickman display may reappear at any time, momentarily or permanently
  • when the script stops it may take a minute or two before the the screen reverts back to the Brickman interface

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
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)

The textsize() function is not used to set the size of text, it is used to determine the size of a text string in pixels. Here is the same script including a line that prints the size of the second text string:
#!/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')
my_string='THIS TEXT IS BLACK'
print(lcd.draw.textsize(my_string))
lcd.draw.text((36,80),my_string)
lcd.update()
sleep(6)

Use larger fonts
The draw.text() command used above without any 'font' argument draws very small text. Beginning with EV3 Python v0.8.0 you can use larger fonts. Version 0.8.0 was released in October 2016 - always be sure to use the latest version. 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, S=Sans Serif, R=?, O=? As an example I will use the luBS14 font which is therefore bold, sans serif and size 14. 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.

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

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

Install fonts to use 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
The simplest way to do a screen capture is to run this at the command line:
fbgrab "screenshot.png"
This will save a black and white png image called 'screenshot.png' in the current folder.  If you are using MobaXTerm you can then click the 'Download selected files' button to download the file to the location of your choice on the PC. 

WasabiFan, a top contributor to the ev3dev project, sent me this more advanced script below for taking a screenshot of the EV3 screen. The script creates an image file 'screenshot.png' in the directory from which the script is run. The image is (optionally) scaled to double its original size and given a pale green background that resembles the real background of the EV3 LCD screen. This script was used to create the 'Hello World' screenshot that you saw higher up this page. You will want to run this script from SSH and not from Brickman so see the paragraph at the bottom of this page. 

#!/usr/bin/env python3

# Import system utilities
import sys
from subprocess import call
# Import imaging library to resize and recolor the screenshot
from PIL import Image

# Choose the name for the screenshot to save.
# It defaults to "screenshot.png",
# but you can supply a custom name as a command-line argument.
out_name = sys.argv[1] if len(sys.argv) > 1 else "screenshot.png"

# Call the fbgrab utility to have it save a screenshot
call(["fbgrab", out_name]);

# Load the screenshot that fbgrab saved so that we can modify it
image = Image.open(out_name)
# Convert the black-and-white screenshot (where
# each pixel is just "black" or "white")
# to an image with red, green and blue channels.
# This lets us make it more colorful later.
image = image.convert("RGB")
# Resize the image to be twice the dimensions,
# making sure to preserve crisp edges
image = image.resize(tuple(i * 2 for i in image.size), Image.NEAREST)

# Get access to the underlying pixel data so that we can modify it
pixel_data = image.load()

# Loop through each pixel
for y in range(image.size[1]):
    for x in range(image.size[0]):
        # If the pixel is white, make it #adb578 (the color we
        # use as an approximation of the LCD screen) instead
        if pixel_data[x, y] == (255, 255, 255):
            pixel_data[x, y] = (173, 181, 120)

# Save the image again
image.save(out_name);

The actual screenshot is made by the fbgrab method in bold. The yellow-highlighted line scales the image to double its original size - you can comment out that line if you prefer the original size (178x128 pixels). The green-highlighted block changes each white pixel into a pale green pixel.

How to run a script that writes to the display via SSH
David L, a top contributor to the ev3dev project, gave me this advice about running an application that writes to the display via SSH.

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