Built-in project · Arduino Uno R3

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

The circuit runs here once the page has loaded.

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.

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 pinConnects to
TFT display, 1.8 inch ST7735 pin SCKArduino Uno R3 pin 13
TFT display, 1.8 inch ST7735 pin SDAArduino Uno R3 pin 11
TFT display, 1.8 inch ST7735 pin CSArduino Uno R3 pin 10
TFT display, 1.8 inch ST7735 pin A0Arduino Uno R3 pin 9
TFT display, 1.8 inch ST7735 pin RESETArduino Uno R3 pin 8
IPS display, ST7789 pin DCArduino Uno R3 pin 7
IPS display, ST7789 pin RESArduino Uno R3 pin 6
TFT display, 1.8 inch ST7735 pin VCCArduino Uno R3 pin 5V
TFT display, 1.8 inch ST7735 pin LEDArduino Uno R3 pin 5V
IPS display, ST7789 pin VCCArduino Uno R3 pin 5V
IPS display, ST7789 pin BLKArduino Uno R3 pin 5V
TFT display, 1.8 inch ST7735 pin GNDArduino Uno R3 pin GND
IPS display, ST7789 pin GNDArduino Uno R3 pin GND
IPS display, ST7789 pin SDAArduino Uno R3 pin A0
IPS display, ST7789 pin SCLArduino 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.

sketch.ino · Arduino Uno R3
// 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.