genuinequality

Download free music MP3s on genuine quality, the world’s largest online music catalogue, powered by your scrobbles. Free listening, videos, photos, The world’s largest online music catalogue, powered by your scrobbles. Free listening, videos, photos, stats, charts, biographies and concerts. stats, charts, biographies and concerts.

Sunday, July 20, 2025

Arduino with Multiple Displays – Part 2

As I mentioned in my last post on Arduino with Multiple Displays I'm going to look at other microcontrollers too. This post takes a wander through my Waveshare Zero and similar format boards that each support one of the RP2040, ESP32-C3 or ESP32-S…
Read on blog or Reader
Site logo image Simple DIY Electronic Music Projects Read on blog or Reader

Arduino with Multiple Displays – Part 2

By Kevin on July 20, 2025

As I mentioned in my last post on Arduino with Multiple Displays I'm going to look at other microcontrollers too. This post takes a wander through my Waveshare Zero and similar format boards that each support one of the RP2040, ESP32-C3 or ESP32-S3.

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
  • 2x 0.96" ST7735 60x180 SPI TFT displays.
  • Breadboard and jumper wires.

Once again I'm using displays that look like this - note the order of the pins.

The Circuit

All circuits are a variation on the above, requiring the following ideal connections:

Display Function RP2040 ESP32-C3 ESP32-S3
BLK Backlight control
(not required)
N/C N/C N/C
CS Chip select
One per display.
5 or any SPI0 CS 10 10
DC Data/Command 8 8 8
RES Reset 14 9 9
SDA Data (MOSI) 3 or any SPI0 MOSI 6 or 7 11
SCL Clock (SCLK) 2 or any SPI0 SCLK 4 or 6 12
VCC Power 3V3 3V3 3V3
GND Ground GND GND GND

For the explanations of the pin choices, and what it means for the code, see the following sections.

ESP32-S3 Zero

In the Arduino IDE, using board ESP32-> Waveshare ESP32-S3-Zero.

There are several SPI buses on the ESP32-S3, but they have fixed uses as follows (see the ESP32-S3 Technical Reference Manual Chapter 30 "SPI Controller"):

  • SPI 0: Reserved for internal use.
  • SPI 1: Reserved for internal use.
  • SPI 2: General purpose use - often called FSPI in the documentation.
  • SPI 3: General purpose use - often called SPI or SPI3.

Sometimes the two SPI buses are called VSPI and HSPI but I think that is really terminology from the original ESP32 rather than the ESP32-S3.

The ESP32 Arduino core for the Waveshare ESP32-S3 Zero variant defines the following:

// Mapping based on the ESP32S3 data sheet - alternate for SPI2
static const uint8_t SS = 34; // FSPICS0
static const uint8_t MOSI = 35; // FSPID
static const uint8_t MISO = 37; // FSPIQ
static const uint8_t SCK = 36; // FSPICLK

By default the Adafruit libraries will use the boards default SPI interface, as defined in the variants.h file - i.e. the above.

When it comes to assigning SPI devices to GPIO there are a few considerations (see the "ESP32-S3 Technical Reference Manual, Chapter 6 "IO MUX and GPIO Matrix"):

  • In general, any GPIO can be mapped onto any SPI function. However...
  • Some GPIO have special "strapping" functions so are best avoided.
  • Some GPIOs have a default SPI function that bypasses the GPIO MUX routing, so allows for better performance (see section 6.6 "Direct Input and Output via IO MUX").

From my reading of the reference manual I believe the following are default "non-MUX" SPI connections:

In the previous table, where SPI3 is mentioned, then the entry for "Direct IO via IO MUX" is set to "no", so I'm guessing that isn't available.

But now we can see why the Arduino core is using GPIO 34-37, but we can also see that GPIO 10-13 would be an alternative (fast) option too.

The problem is that not all of GPIO 34-37 are broken out on a Waveshare ESP32-S3 Zero, so I need to use the alternative pinouts. Aside: this makes no sense to me that these are the defaults in the Waveshare ESP32-S3 Zero's "variant.h" file, but anyway...

To use a different SPI interface requires using a constructor that passes in an initialised SPI instance. There is an example in the ESP32 core for setting up multiple SPI buses here: https://github.com/espressif/arduino-esp32/blob/master/libraries/SPI/examples/SPI_Multiple_Buses/SPI_Multiple_Buses.ino

This leads to the pins as defined in the previous table, and the code below to setup one of the displays.

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <SPI.h>

#define SPI_SS 10
#define SPI_MOSI 11
#define SPI_SCLK 12
#define SPI_MISO 13
SPIClass MySPI(FSPI);

#define TFT_CS SPI_SS
#define TFT_RST 9
#define TFT_DC 8
Adafruit_ST7735 tft = Adafruit_ST7735(&MySPI, TFT_CS, TFT_DC, TFT_RST);

void setup() {
MySPI.begin(SPI_SCLK, SPI_MISO, SPI_MOSI, SPI_SS);
pinMode(SPI_SS, OUTPUT);
tft.initR(INITR_MINI160x80_PLUGIN);
}

ESP32-C3 Zero

In the Arduino IDE, using board ESP32-> ESP32C3 Dev Module.

Again there are several SPI buses on the ESP32-C3, with the same fixed uses as follows (see the ESP32-C3 Technical Reference Manual Chapter 30 "SPI Controller"):

  • SPI 0: Reserved for internal use.
  • SPI 1: Reserved for internal use.
  • SPI 2: General purpose use - sometimes called GP-SPI in the documentation.

The ESP32-C3 also has a very similar SPI arrangement to the ESP32-S3, in that whilst any pin can be configured for SPI usage, there are certain hard-wired optional arrangements that bypass the GPIO routing matrix.

The faster (direct to IO MUX) pins are as follows (more here):

  • CS0 - 10
  • SCLK - 6
  • MISO - 2
  • MOSI - 7

Curiously, the general ESP32-C3 Arduino variant defines them as follows:

static const uint8_t SS = 7;
static const uint8_t MOSI = 6;
static const uint8_t MISO = 5;
static const uint8_t SCK = 4;

From the Technical Reference manual, we can see that the default Arduino definitions above, do not support the non-routed, direct-to-IO MUX pin mappings, which from the table below do indeed map onto GPIO 2, 6, 7, 10.

In terms of using a Waveshare ESP32-C3 Zero, both combinations would be supported on the broken out GPIO, so from a software point of view, the Adafruit libraries could be used "as is" with the default mapping, or with a custom SPI definition (as shown above) with the more bespoke, but faster, mapping.

RP2040 Zero

This is using the (unofficial) RP2040 core from here: https://github.com/earlephilhower/arduino-pico, where this is an entry: RP2040 -> Waveshare RP2040 Zero.

The RP2040 has two SPI peripherals and the SPI functions are mapped onto specific sets of GPIO pins. This gives a range of flexibility, but not arbitrary flexibility. The board definition file for the Waveshare RP2040 Zero provides this as a default:

// SPI
#define PIN_SPI0_MISO (4u)
#define PIN_SPI0_MOSI (3u)
#define PIN_SPI0_SCK (2u)
#define PIN_SPI0_SS (5u)

#define PIN_SPI1_MISO (12u)
#define PIN_SPI1_MOSI (15u)
#define PIN_SPI1_SCK (14u)
#define PIN_SPI1_SS (13u)

Note that the SPI1 pins for the Waveshare RP2040 Zero are not all on the standard header connections, some are on the additional pin headers across the bottom.

Using a bespoke configuration is possible using a series of calls to set the SPI pins as shown below.

  SPI.setRX(SPI_MISO);
SPI.setCS(SPI_SS);
SPI.setSCK(SPI_SCLK);
SPI.setTX(SPI_MOSI);
SPI.begin(true);

To use pins for SPI1, replace SPI above with SPI1. As long as this happens prior to the call to the Adafruit libraries, everything works fine.

A Common Option

It would be nice to find a set of physical pin connections that I know would always work regardless of the board in use: RP2040, ESP32-S3 or ESP32-C3.

With careful noting of the RP2040 limitations, I think that is largely possible with the following. Even though the GPIO numbers are different, the physical pins are common on all three boards.

Display Function WS Pin RP2040 ESP32-C3 ESP32-S3
BLK Backlight control
(not required)
N/C N/C N/C
CS1 Chip select
Display 1
H2 P6 GP5 GP9 GP10
DC Data/Command H2 P5 GP4 GP10 GP11
RES Reset H2 P9 GP8 GP6 GP7
SDA Data (MOSI) H2 P8 GP7 GP7 GP8
SCL Clock (SCLK) H2 P7 GP6 GP8 GP9
VCC Power H1 P3 3V3 3V3 3V3
GND Ground H1 P2 GND GND GND
CS2 CS Display 2 H1 P9 GP14 GP5 GP6
CS3 CS Display 3 H1 P8 GP15 GP4 GP5
CS4 CS Display 4 H1 P7 GP26 GP3 GP4

A couple of notes:

  • I've avoided pins 1-4 on header 2, as the ESP32-C3 can't use them for SPI and they support either the UART or USB.
  • I've had to include a MISO (SPI RX) pin in each configuration too, so I've just picked something that can be ignored. For RP2040 that has to be one of GP0, GP4 or GP16 however, which could clash with either the UART, the above configuration for DC pin, or the onboard WS2812 LED, but there isn't much that can be done.
  • I've allowed three consecutive pins on the first header for optional additional CS pins for displays 2 to 4.

Here is the full set of configurable code for the above:

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <SPI.h>

//#define WS_RP2040_ZERO
//#define WS_ESP32C3_ZERO
#define WS_ESP32S3_ZERO

#ifdef WS_RP2040_ZERO
#define SPI_SS 5
#define SPI_MOSI 7
#define SPI_SCLK 6
#define SPI_MISO 4 // Not used
#define SPI_BUS SPI
#define TFT_CS1 SPI_SS
#define TFT_CS2 14
#define TFT_CS3 15
#define TFT_CS4 26
#define TFT_RST 8
#define TFT_DC 4
Posted by BigPalaceNews at 10:23 AM
Email ThisBlogThis!Share to XShare to FacebookShare to Pinterest

No comments:

Post a Comment

Newer Post Older Post Home
Subscribe to: Post Comments (Atom)

Search This Blog

About Me

BigPalaceNews
View my complete profile

Blog Archive

  • June (50)
  • May (82)
  • April (84)
  • March (87)
  • February (90)
  • January (74)
  • December (72)
  • November (95)
  • October (105)
  • September (112)
  • August (116)
  • July (96)
  • June (100)
  • May (105)
  • April (95)
  • March (131)
  • February (111)
  • January (104)
  • December (98)
  • November (87)
  • October (126)
  • September (104)
  • August (97)
  • July (112)
  • June (113)
  • May (132)
  • April (162)
  • March (150)
  • February (342)
  • January (232)
  • December (260)
  • November (149)
  • October (179)
  • September (371)
  • August (379)
  • July (360)
  • June (385)
  • May (391)
  • April (395)
  • March (419)
  • February (356)
  • January (437)
  • December (438)
  • November (400)
  • October (472)
  • September (460)
  • August (461)
  • July (469)
  • June (451)
  • May (464)
  • April (506)
  • March (483)
  • February (420)
  • January (258)
  • December (197)
  • November (145)
  • October (117)
  • September (150)
  • August (132)
  • July (133)
  • June (117)
  • May (190)
  • January (48)
Powered by Blogger.