Two color screens on an Arduino Uno
An ST7735 and an ST7789 on one Uno: the same command set, different glass. The ST7789 has no chip select, so it has pins of its own. The whole build, an Arduino Uno and 2 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.
Teaching? Assign it to your class in one click.
Advanced About 25 minutes to build and run. Runs in your browser. Free, and no account needed.
The parts retail for about $42. On Mokxi they're free.
Step by step, with the wiring and the common mistakes: Arduino ST7735: 1.8 Inch Color TFT Wiring and Code
What you'll learn
- Driving two displays from one board
- Hardware SPI versus software SPI on any pins
- Why a display with no chip select needs its own pins
- Same command set, different panel details
- Drawing only what moves to stay fast
- Difficulty: Advanced
- Time: About 25 minutes
- Board: Arduino Uno R3
- Parts: 4
How it works
Two different color screens share one Uno. The ST7735 uses hardware SPI pins 13 and 11, with chip select on 10, A0 on 9 and reset on 8. The ST7789 has no chip select, so it gets its own pins: data on A0, clock on A1, DC on 7 and reset on 6.
At startup each screen is cleared and given a title. Then the loop moves a colored block one step along each screen every 100 ms, changing its color as it goes, for 16 steps before starting over. Both screens get the same color each step.
Parts list
4 parts, plus the jumper wires. They retail for about $42; on Mokxi they're free.
- 1 × Arduino Uno R3In Starter Kit, Claw Machine Kit, Vending Machine Kit.
- 1 × Full-size breadboard
- 1 × TFT display, 1.8 inch ST7735
- 1 × IPS display, ST7789
Wiring table
Every connection, pin by pin, read from the circuit itself. Each row joins the pin on the left to the pin on the right, by a jumper wire or a breadboard strip.
| Part and pin | Connects to |
|---|---|
| TFT display, 1.8 inch ST7735 pin SCK | Arduino Uno R3 pin 13 |
| TFT display, 1.8 inch ST7735 pin SDA | Arduino Uno R3 pin 11 |
| TFT display, 1.8 inch ST7735 pin CS | Arduino Uno R3 pin 10 |
| TFT display, 1.8 inch ST7735 pin A0 | Arduino Uno R3 pin 9 |
| TFT display, 1.8 inch ST7735 pin RESET | Arduino Uno R3 pin 8 |
| IPS display, ST7789 pin DC | Arduino Uno R3 pin 7 |
| IPS display, ST7789 pin RES | Arduino Uno R3 pin 6 |
| TFT display, 1.8 inch ST7735 pin VCC | Arduino Uno R3 pin 5V |
| TFT display, 1.8 inch ST7735 pin LED | Arduino Uno R3 pin 5V |
| IPS display, ST7789 pin VCC | Arduino Uno R3 pin 5V |
| IPS display, ST7789 pin BLK | Arduino Uno R3 pin 5V |
| TFT display, 1.8 inch ST7735 pin GND | Arduino Uno R3 pin GND |
| IPS display, ST7789 pin GND | Arduino Uno R3 pin GND |
| IPS display, ST7789 pin SDA | Arduino Uno R3 pin A0 |
| IPS display, ST7789 pin SCL | Arduino Uno R3 pin A1 |
The code
The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.
// Two color screens: a 1.8 inch ST7735 and a 1.3 inch ST7789.
//
// ST7735 SCK -> 13 SDA -> 11 CS -> 10 A0 -> 9 RESET -> 8 LED -> 5 V
// ST7789 SCL -> A1 SDA -> A0 DC -> 7 RES -> 6 BLK -> 5 V CS unwired
//
// Both chips speak the same command set as the ILI9341: a column window, a row
// window, then pixels, with DC saying which bytes are commands. What differs
// is the glass. The ST7789's memory is 240x320 and this panel shows 240x240 of
// it, so rotations that count rows from the bottom start at row 80; and its
// IPS glass shows colors inverted until INVON, which init() sends.
//
// The ST7789 is wired the way the 1.3 inch board comes: no chip select, so it
// listens to every clock on its pins. That is why it has pins of its own here
// (the five-argument constructor is software SPI on any pins). On the ST7735's
// bus it would take that panel's bytes as its own.
//
// Every pixel goes out bit by bit, so an Uno draws a small square quickly and
// a whole screen slowly: draw what moves.
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <Adafruit_ST7789.h>
Adafruit_ST7735 small(10, 9, 8);
Adafruit_ST7789 square(-1, 7, A0, A1, 6); // no CS; DC, SDA, SCL, RES
void setup() {
small.initR(INITR_BLACKTAB);
small.fillScreen(ST77XX_BLACK);
small.setTextColor(ST77XX_GREEN);
small.setCursor(4, 4);
small.print("ST7735 128X160");
square.init(240, 240, SPI_MODE3);
square.setRotation(2);
square.fillRect(0, 0, 240, 40, ST77XX_BLUE);
square.setTextColor(ST77XX_WHITE);
square.setTextSize(2);
square.setCursor(8, 12);
square.print("ST7789 IPS");
}
void loop() {
// A block that walks around each screen, in a color that changes as it goes.
static uint8_t step = 0;
uint16_t color = Adafruit_ST7789::color565((uint8_t)(step * 16), 255 - step * 16, 128);
small.fillRect((int16_t)(8 + (step % 8) * 14), 40, 12, 12, color);
square.fillRect((int16_t)(10 + (step % 8) * 28), 120, 24, 24, color);
step = (uint8_t)((step + 1) % 16);
delay(100);
}
Code walkthrough
The key functions of the sketch, and what each one does.
setup sketch.ino
Starts the ST7735 with initR(INITR_BLACKTAB), fills it black and prints green text. Then it starts the ST7789 as a 240 by 240 panel, sets rotation 2, draws a blue bar across the top and prints white text in it. Each screen is drawn once here.
void setup() {
small.initR(INITR_BLACKTAB);
small.fillScreen(ST77XX_BLACK);
small.setTextColor(ST77XX_GREEN);
small.setCursor(4, 4);
small.print("ST7735 128X160");
square.init(240, 240, SPI_MODE3);
square.setRotation(2);
square.fillRect(0, 0, 240, 40, ST77XX_BLUE);
square.setTextColor(ST77XX_WHITE);
square.setTextSize(2);
square.setCursor(8, 12);
square.print("ST7789 IPS");
}loop sketch.ino
Keeps a counter called step that counts 0 to 15. It builds a color from the step, then draws a small square on the small screen and a larger one on the square screen, each moved along by step % 8. Drawing a small block instead of the whole screen keeps this quick on an Uno. A 100 ms delay sets the pace.
void loop() {
// A block that walks around each screen, in a color that changes as it goes.
static uint8_t step = 0;
uint16_t color = Adafruit_ST7789::color565((uint8_t)(step * 16), 255 - step * 16, 128);
small.fillRect((int16_t)(8 + (step % 8) * 14), 40, 12, 12, color);
square.fillRect((int16_t)(10 + (step % 8) * 28), 120, 24, 24, color);
step = (uint8_t)((step + 1) % 16);
delay(100);
}Troubleshooting
The usual mistakes with this circuit, and the fix for each.
- The ST7789 stays blank or shows garbage. This project
It has its own pins here: SDA on A0, SCL on A1, DC on 7, RES on 6. Do not put it on the ST7735's pins 13 and 11, since with no chip select it would read that screen's bytes. - A screen is dark even though the code runs. This project
Check the backlight pins: the ST7735's LED pin and the ST7789's BLK pin both go to 5 V. - The screen is blank or white. TFT display
Check all the SPI wires: SCK, MOSI, CS, DC and RST, plus power and the backlight pin. Many modules need the LED pin tied to 3.3 V, with a resistor on some. Use the right library init. - Colors are wrong, or the picture is shifted with a noisy edge. TFT display
Pick the tab color your library asks for, such as INITR_BLACKTAB or GREENTAB, until the picture is clean. Swap red and blue if the colors are reversed. Rotation changes the offset. - Colors are inverted, looking like a negative. IPS display
Send the INVON command (0x21) in the driver init. Most libraries handle this with the right display setup. Pick the correct size for your panel: 240x240, 240x320 or 135x240. - The screen stays blank or is shifted. IPS display
It is a 3.3 V part. Wire SPI properly: SCK, MOSI, DC, RST and CS if present, and power the backlight. Some panels have offsets, so set the correct column and row offsets in the library. - Upload fails or nothing runs after wiring pins 0 and 1 to a module. Arduino Uno R3
Pins 0 and 1 are the USB serial port. Move the module to other pins, or unplug it while uploading. Also check the right board is selected. - Pins misbehave or the board resets when you power motors or servos from it. Arduino Uno R3
Each I/O pin gives about 20 mA, 40 mA max. Power motors and servos from their own supply and join its ground to the Uno's GND.
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.