Whilst messing around a little more with my Arduino with Multiple Displays – Part 2, I’ve optimised the code a little and found out a bit more about these displays!
In this part, I’m actually using a PCB that can hold four displays, powered by a Waveshare Zero device. More on that here: Waveshare Zero Multi Display PCB Design.

Warning! I strongly recommend using old or second hand equipment for your experiments. I am not responsible for any damage to expensive instruments!
These are the key Arduino tutorials for the main concepts used in this project:
- Arduino with Multiple Displays
- https://emalliab.wordpress.com/2025/07/19/small-microcontroller-displays/
If you are new to microcontrollers, see the Getting Started pages.
Parts list
- A Waveshare Zero format board or similar
- 4x 0.96″ ST7735 60×180 SPI TFT displays.
- Built Waveshare Zero Multi Display PCB
- Breadboard and jumper wires.
Recall that I’m using displays that look like this – note the order of the pins.

Although even with displays that look exactly the same, it appears there can be differences in how they are used software wise. More on that later.
The Circuit

For two displays, I can reuse the circuit from Arduino with Multiple Displays – Part 2. For more displays, it is possible to cascade more displays using jumper wires, but I’ve used my PCB.

The pins to be used for various Waveshare Zero boards is covered in part 2.
The Code
Whilst using these displays, I found that the colours can be inverted in some of them compared to others. Typically, I’ve found that I might have to use either of the following two options to drive them correctly:
tft.initR(INITR_MINI160x80);
tft.initR(INITR_MINI160x80_PLUGIN);
These represent different Adafruit displays as before, but they generally work for me.
However there is another thing to watch out for. These displays are 16-bit colour displays, which means each colour value is a 16-bit word with red, green and blue elements represented by 5, 6 and 5 bits. This means two of the colours have a resolution of 0 to 31, and one has 0 to 63.
But the ordering seems different for different displays. The default Adafruit library appears to assume RGB ordering, but my displays seem to be BGR. This means that if I use the provided short-cuts for colours, the red and blue elements are swapped.
Consequently, I defined my own colours along with a macro to allow me to provide RGB values and turn it into the device-specific 16-bit value as required.
In the following, I define the bit-shift number for each of red, green and blue and the use that in a macro “ST_COL” shifting the value to the correct place in the 5-6-5 format. Red and blue are the 5-bit colours and green is the 6-bit colour, so in each case I take the most significant bits which means each colour can still be defined in terms of 0..255 RGB values.
// Format is 16-bit 5-6-5 B-G-R
// Allow 0..255 in component values, by only taking
// most significant bits (5 or 6) from each value.
// bbbbbggggggrrrrr
#define ST_COL(r,g,b) (((r&0xF8)>>3)|((g&0xFC)<<3)|((b&0xF8)<<8))
#define ST_BLACK ST_COL(0,0,0)
#define ST_GREY ST_COL(64,64,64)
#define ST_WHITE ST_COL(255,255,255)
#define ST_BLUE ST_COL(0,0,255)
#define ST_GREEN ST_COL(0,255,0)
#define ST_RED ST_COL(255,0,0)
#define ST_YELLOW ST_COL(255,255,0)
#define ST_MAGENTA ST_COL(255,0,255)
#define ST_CYAN ST_COL(0,255,255)
I’m also building up to seeing if I can drive more than four displays, so I’ve also changed the code to allow me to iterate across a number of displays.
#define NUM_TFTS 4
int tftTypes[NUM_TFTS] = {
INITR_MINI160x80, INITR_MINI160x80,
INITR_MINI160x80, INITR_MINI160x80,
};
int tftCS[NUM_TFTS] = {SPI_SS, 6, 5, 4};
#define TFT_RST 7
#define TFT_DC 11
Adafruit_ST7735 *tft[NUM_TFTS];
void setup() {
int rstPin = TFT_RST;0
for (int i=0; i<NUM_TFTS; i++) {
tft[i] = new Adafruit_ST7735(&MySPI, tftCS[i], TFT_DC, rstPin);
rstPin = -1;
tft[i]->initR(tftTypes[i]);
tft[i]->setRotation(3);
tft[i]->fillScreen(ST_BLACK);
}
}
void loop() {
for (int i=0; i<NUM_TFTS; i++) {
unsigned long time = millis();
tft[i]->fillRect(10, 20, tft[i]->width(), 20, ST_BLACK);
tft[i]->setTextColor(ST_GREEN);
tft[i]->setCursor(10, 20);
tft[i]->print(i);
tft[i]->print(":");
tft[i]->print(time, DEC);
}
}
Each instance of the display code is now created dynamically and stored in an array which can then be iterated over when it comes to putting things on each display.
Notice how the reset pin definition is set to -1 after the first initialisation. This ensures that subsequent instantiations won’t reset displays that have already been set up.
The final code actually allows up to eight displays to be included by setting NUM_TFTS at the top to two or four.
The GPIO usage being assumed is described here: Waveshare Zero Multi Display PCB Build Guide.
Closing Thoughts
Approaching the code in this way allows me to experiment more easily with more than four displays.
If my PCB works as I’m hoping I should be able to cascade them to get eight displays – assuming the Waveshare Zero is up to driving eight of course.
Kevin