Controlling an ST7789 Display With a Raspberry Pi Pico

Raspberry Pi Pico on breadboard drives LCD showing Hello message surrounded by colourful wires LEDs creating playful beginner electronics scene

The ST7789 is a popular LCD display controller that works especially well when paired with a Raspberry Pi Pico. When people talk about using an ST7789 with a Pico, they are usually describing a setup where the Pico sends simple instructions to the ST7789 chip, which then takes care of driving the LCD screen. This makes it possible for a small, low-cost microcontroller like the Pico to control a bright, full-colour display without needing complex hardware.

An ST7789 with a Pico typically communicates using a serial interface called SPI. SPI uses only a handful of wires, which keeps projects neat and beginner-friendly. The Pico sends data one bit at a time at high speed, and the ST7789 interprets this data as either commands or pixel colour information. This approach is ideal for learning how displays work because you can see immediate visual results from your code.

When using an ST7789 with a Pico, your program sends commands to set things like screen orientation, drawing areas, or colour mode. After that, pixel data is streamed to the display to draw text, shapes, or images. The ST7789 stores this data internally and refreshes the LCD automatically, so the image stays on screen even when your code moves on to other tasks.

Overall, using an ST7789 with a Pico is a great entry point into controlling LCD displays with a serial interface. The Pico provides the brains, the ST7789 handles the display complexity, and together they let beginners create colourful, interactive projects with relatively little code or wiring.

Parts List

Wire up the circuit

In order to run the project firstly connect the display, using the ST7789, as shown in the diagram below. The circuit diagram below is shown for clarity and the actual connection on the breadboard follow.

The circuit looks as shown below on the set up that was used to create this tutorial.

Running the Code

In order to get started you will need to follow this tutorial, which will ensure that your environment and Pico are configured correctly.

You will need to create 2 files on the Raspberry Pico to help control the LCD display. Download the file here and save it as lcd_api.py, then download the file here and save it as vga1_8x8.py.

Writing to the screen

When writing text to an ST7789 screen, the Raspberry Pi Pico sends instructions and image data over the SPI connection. It tells the display where on the screen to draw, then sends colour information for each pixel. The display stores this data in its internal memory and uses it to turn individual pixels on and off, making shapes and text appear on the screen.

The font file provides a simple map of how each character should look using small grids of pixels. When you ask the screen to display text, the software looks up each letter in the font file (vga1_8x8) and draws its pixels in the chosen colour at the correct position. This allows clear, readable text to be shown without needing to manually draw every pixel yourself.

Now create a file called main.py on the Raspberry Pico with the following content.

Next, click the run button and the display should show “Hello from Tinkimo!” as shown below.

Drawing to the screen

When drawing to an ST7789 screen, the Raspberry Pi Pico sends instructions over the SPI connection that describe what should be drawn and where. These instructions define areas of the display, such as lines, rectangles, or circles, and prepare the screen to receive pixel data. The Pico then sends colour values that fill in those shapes pixel by pixel.

The drawing functions in the display library (st7789py ) handle the maths needed to work out which pixels belong to a shape. Instead of you setting each pixel by hand, the library calculates their positions and sends the correct colour data to the screen. This makes it easy to create graphics, icons, and simple user interfaces using just a few lines of code.

You can try drawing to the screen by changing the code to that shown below.

When you run the example you should see the following on the screen.

Here is a simple table explaining the purpose of the main drawing functions.

FunctionPurpose
fillFills the entire screen with a single colour. Commonly used to clear the display before drawing new content.
fill_rectDraws a solid rectangle at a chosen position with a specified width, height, and colour. Useful for panels, buttons, or blocks of colour.
hlineDraws a horizontal line starting at a position and extending a set length across the screen. Often used for separators or underlines.
vlineDraws a vertical line starting at a position and extending a set length down the screen. Useful for dividers or simple graph axes.
textDraws readable characters on the screen using a font file, placing text at a specified position in a chosen colour. Useful for labels and messages.

If you’d like, I can also add a short example showing how these commands can be combined to build a simple on-screen interface.

Screen Coordinate System

The screen is treated like a grid of pixels with its origin at the top left corner. This position is called 0,0. The x value increases as you move to the right, and the y value increases as you move down the screen. Every drawing command uses this same coordinate system.

Functions like fill and fill_rect colour large areas by setting many pixels at once. Line commands such as hline and vline colour pixels in straight paths across or down the screen. Circle and fill_circle calculate which pixels fall on or inside a circular shape and colour only those. The text function works in a similar way, but instead of shapes, it draws groups of pixels that form letters based on the font file.

Once you understand that everything is just colouring pixels at specific x and y positions, all drawing operations become much easier to visualise and combine into simple user interfaces or graphics.

Displaying Images On The Screen

The Raspberry Pi Pico has only a small amount of built-in flash storage and working memory compared to a full computer. Large images can quickly use up this space if they are loaded all at once, leading to errors or crashes. By breaking an image into smaller chunks, the Pico only needs to load and draw a small piece at a time, keeping memory use low. This makes the code more reliable and allows images to be displayed smoothly even on very limited hardware.

In this example, we take the Tinkimo logo, which is a 240 by 240 pixel image, and split it into smaller 64 by 64 pixel chunks. Loading the full image at once would use a large amount of the Pico’s limited memory, which will cause problems. By breaking the image into smaller pieces, the Pico only loads one chunk at a time, draws it to the screen, then moves on to the next. This approach keeps memory usage low and makes it possible to display larger images reliably on very constrained hardware.

The code (tile_image.py) to perform the conversion can be found here in the Tinkimo Git repository. Download the script together with the Tinkimo logo and place them in the same directory.

The script requires that the Python pillow module is install on your machine. You can do this using the following command.

Next, the code can be run to create a directory of tiles that can be used to construct the image using the following.

In the directory you will now see a tiles folder, containing the image in smaller pieces that the Pico can handle without memory issues.

To upload the tiles select View->Files from the top menu which will then allow you to copy from your local machine to the Pico. Copy the entire “tiles” directory to the root folder on the Pico.

Next, create a main.py to run on the Pico as follows.

When the image is displayed you will see the tiles appear as it is being written to the display. The ordering of the tiles being displayed has been randomised to make it more interesting when it appears!

The blit_buffer function is used to copy a block of raw pixel data directly onto the screen. Instead of drawing shapes or text one pixel at a time, it takes a prepared buffer of colour values and places it at a specific position on the display. This makes it ideal for showing images, icons, or tiles that have already been converted into the screen’s native colour format.

When blit_buffer is called, the Pico sends the contents of the buffer to the display over SPI in one continuous stream. Along with the buffer, it tells the screen the width, height, and position where the data should appear. The display then writes those colour values straight into its internal memory, updating all of the pixels in that area in one operation.

Because blit_buffer works with raw pixel data, it is both fast and memory efficient. The Pico only needs enough memory to hold the small buffer being drawn, not the entire screen. This is why it works well with techniques like image tiling, where small chunks of an image are loaded and drawn one at a time to build up a larger picture.

Main Topic

The Raspberry Pi Pico

Raspberry Pi Pico on a breadboard with sensors and jumper wires arranged neatly on a desk, ready for an electronics project.

Raspberry Pi Pico is an affordable, efficient microcontroller offering flexible GPIO, strong performance, and versatile hardware features for beginner electronics projects.

Other Tutorials in this Topic

Cartoon Raspberry Pi Pico on a breadboard with glowing LED and wires beside a computer screen showing the Thonny picozero plugin installation.

Getting Started With The Raspberry Pico

Getting started guide showing how to set up a Raspberry Pi Pico on a breadboard and install…

A cheerful orange octopus adjusts wires on a breadboard with a Raspberry Pi Pico, potentiometer, and glowing LED beneath the text Basic Input / Output On the Pico.

Basic Input and Output With The Raspberry Pi…

The article explains how a Raspberry Pi Pico uses a potentiometer to control LED brightness, demonstrating basic…

A cheerful cartoon duck turns a control dial beside a spinning motor while an oscilloscope displays a squarewave showing PWM motor control.

Pico Motor Control Using the L9110 Control Board

A tutorial showing how to control a motor using PWM modulation to varying the speed of a…

Cartoon computer and Raspberry Pi Pico shout echo into a glowing cave with bold title Using Bluetooth On The Raspberry Pico.

Using Bluetooth on the Raspberry Pico

The article explains how to use Bluetooth Low Energy on the Raspberry Pi Pico, set up BLE…

Small educational robot uses ultrasonic sensor to navigate obstacles like cones and boxes while moving through a bright indoor course

Getting Started with an Ultrasonic Sensor Module on…

Beginner guide explaining how an ultrasonic sensor module works with Raspberry Pi Pico to measure distance using…

Cartoon robot spins happily while IMU detects z-axis rotation with arrows screens and motion lines in colorful laboratory scene background

Using the MPU6050 Gyro With Raspberry Pi Pico

The article explains how the MPU6050 IMU measures motion and rotation and communicates with microcontrollers using the…

Cartoon LCD on breadboard shows Hello from Tinkimo heart while silly banana sparks and googly eyed hammer watch Pico project

Using an LCD with the Pico

Beginner friendly guide explains using an LCD with the Raspberry Pi Pico for wiring, control signals, and…