#WaveshareZero

diyelectromusicdiyelectromusic
2025-08-14

Messing around driving up to eight small SPI displays from a Waveshare Zero format board.

It works. But it is getting a little warm :) Figuring out why is on the todo list!

diyelectromusic.com/2025/08/14

Photo of two custom PCBs joined in the centre.  Each PCB has four small colour TFT displays arranged vertically in a line, one above the other.  The overall effect is a 2x4 grid of small rectangular displays.  Each display has some small magenta text on it.
2025-08-14

Waveshare Zero Multiple SPI Displays

makertube.net/w/jwddZfiSGyRKKh

Simple DIY Electronic Music Projectsdiyelectromusic.com@diyelectromusic.com
2025-08-14

Waveshare Zero Multi Display PCB – Expander Board

Here are the additional build notes to use my Waveshare Zero Multi Display PCB in “expander” mode to support up to eight displays.

https://makertube.net/w/jwddZfiSGyRKKhAuU4Rhas

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

If you are new to electronics and microcontrollers, see the Getting Started pages.

Bill of Materials

  • Waveshare Zero Multi Display PCB (GitHub link here: Waveshare Zero Multi Display PCB Build Guide)
  • 4x SPI 0.96″ 80×160 (RGB) IPS TFT displays
  • Capactitors: 2x 100nF ceramic
  • Optional: 4x 8-way pin header sockets – strongly recommended. PH5.0 “short” headers are best.
  • 1x 10-way right angle pin headers
  • 1x 10-way right angle pin header socket

Build Steps

It largely doesn’t matter what order things are soldered on. I did them in the following order

  • Right angle pin header.
  • 8-way PH 5.0 pin header sockets for the displays
  • 2 ceramic capacitors

The expander board photos are shown below.

Note that when adding the right-angle pin headers to the main board, as described in Waveshare Zero Multi Display PCB Build Guide, they will need to be soldered flush to the PCB and not left separated by the plaster spacers.

To do this, I pushed the spacers to the edge of the bent pin headers and then pushed the whole thing through the PCB prior to soldering. Once soldered, the plastic spacers can be removed and the pins clipped, but in the photo below the spacer has been left.

Testing

The updated sketch described in Arduino with Multiple Displays – Part 3 can be used to test the expander board with eight displays in total.

A Note About Power…

When running 8 displays, I can feel my Waveshare board getting quite hot…

The displays are all powered from the 3V3 line. The Waveshare schematic shows that the 3V3 line comes from a ME6217C33M5G which is powered from the VBUS/5V line as shown below. Recall that the VBUS/5V line comes ether from the USB socket or an external connection to the VCC pin.

That regulator can supply up to 800mA according to the datasheet.

In terms of current usage of a ST7735 display, the datasheet states the following:

I have to say, I’m not really sure what that is telling me. Is that up to 0.7mA per line displayed? What if all lines are on – are these displays scanned or “all on”? There are potentially 80 lines on a display…

Ah, this post: https://wiki.dfrobot.com/0.96_Inch_160_80_Color_SPI_TFT_Display_SKU_DFR0847 suggests that the display only consumes 15mA full screen.

Powering eight displays and a Waveshare Zero ESP32-S3 via the USB connection through one of those current measuring USB pass-through devices, seems to show a continuous current consumption of 200mA.

Removing four of the displays, that appears to drop down to 110mA, so I think in my case it is a little more than 15mA – perhaps nearer 20mA per display.

I can’t quite work out if it is the regulator or the ESP32-S3 itself getting hot. My sophisticated sensor (finger) hasn’t the resolution to work it out. But it is definitely not as hot powering four displays as eight.

I am now wondering if I should have included an independent regulator on the board to generate a 3V3 supply rather than use the one onboard the Waveshare Zero.

Closing Thoughts

I really ought to think about some of these design issues up front. One day 🙂

In general terms this seems to work really well. I’d like to know a little more about what is getting hot, as, as far as I can see, “on paper” the components ought to be able to cope.

I have an application in mind for all these displays. There is a small clue in the filenames of the PCB, but it remains to be seen if I get right to the end of the idea or not.

For now, these are quite neat ways to drive several small, full colour displays.

Kevin

#ESP32s3 #midi #pcb #st7735 #WaveshareZero

Simple DIY Electronic Music Projectsdiyelectromusic.com@diyelectromusic.com
2025-08-14

Arduino with Multiple Displays – Part 3

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:

If you are new to microcontrollers, see the Getting Started pages.

Parts list

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.

Find it on GitHub here.

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

#arduinoUno #define #esp32c3 #ESP32s3 #rp2040 #st7735 #tftDisplay #WaveshareZero

Simple DIY Electronic Music Projectsdiyelectromusic.com@diyelectromusic.com
2025-08-14

Waveshare Zero Multi Display PCB Build Guide

Here are the build notes for my Waveshare Zero Multi Display PCB.

Also see the Waveshare Zero Multi Display PCB – Expander Board.

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

If you are new to electronics and microcontrollers, see the Getting Started pages.

Bill of Materials

  • Waveshare Zero Multi Display PCB (GitHub link below)
  • Waveshare Zero format board – e.g. ESP32S3 or RP2040
  • 1x H11L1 optoisolator
  • 1x 1N4148 or 1N914 signal diode
  • 4x SPI 0.96″ 80×160 (RGB) IPS TFT displays
  • Resistors: 1×10Ω; 1x 33Ω; 1x 220Ω; 1x 470Ω
  • Capactitors: 3x 100nF ceramic; 1x 100uF electrolytic
  • 2x 3.5mm stereo TRS sockets (see photos and PCB for footprint)
  • 1x 2.1mm barrel jack socket (see photos and PCB for footprint)
  • 2x 9-way pin header sockets
  • Optional: 4x 8-way pin header sockets – strongly recommended. PH5.0 “short” headers are best.
  • Optional: 1x 6-way DIP socket – recommended
  • Pin headers/jumpers
  • Optional: 1x DPDT slider switch with 2.54mm pin footprint
  • Optional: 1x SPDT slider switch with 2.54mm pin footprint

Build Steps

Taking a typical “low to high” soldering approach, this is the suggested order of assembly:

  • Diode then resistors.
  • DIP socket (if used) and TRS sockets.
  • Disc capacitors.
  • Slider switches (if used).
  • 9-way pin header sockets for Waveshare Zero.
  • Electrolytic capacitor.
  • Barrel jack sockets.
  • On rear: 8-way pin header sockets (if used) or displays.

Note: all the components apart from the displays (and their sockets if used) are on one side and the displays are on the other. The silkscreen reflects the side of the components.

Here are some build photos.

If slider switches are used for MIDI, then as shown above they can be added a this stage too. If pin headers and jumpers are used, then it might be worth waiting until the other header sockets are added. If the ability to disable MIDI isn’t required, then wire jumpers can be soldered on instead to make a permanent connection.

There are a few options around power:

  • Use a barrel jack or pin jumper headers. These are both 5V only however as there is no power regulation in this version (it is an option in the schematic, but not the actual PCB).
  • An optional on/off switch can be used as long as it has 2.54mm pitch pin connections.
  • Note: the solder bridge jumper can be ignored. It is not relevant on a PCB with no regulator.

It is strongly recommended that 8-way pin header sockets are used for the displays too. I used PH5.0 height headers, which are shorter than the usual ones.

If the displays are to be soldered directly, then it is strongly recommended that they are tested in isolation first, as there are a number of different types and in my experience cheap ones might not always work on arrival.

The orientation of the Waveshare Zero and displays is shown below.

It is possible to use M2 spacers to support the displays. For my PH5.0 sized headers, I found that a 6mm spacer, 6mm screw and two nuts gave me the right height to level out each display when plugged in.

Testing

Even before the build is started, it is worth testing the displays to be used. When I first assembled and tested my first board, I had the following:

One of the displays was inverted compared to the others, and one had arrived with the screen cracked. At this point I was pleased I’d chosen to use pin header sockets for the displays…

Once built I recommend performing the general tests described here: PCBs.

The using the sample applications mentioned below it should be possible to test the following in turn:

  • MIDI IN and OUT.
  • Four display.

PCB Errata

There are the following issues with this PCB:

  •  None at present.

Enhancements:

  • I avoided added holes to mount the displays at the time, but now I’m thinking adding the holes on the non-pin header side of the displays would have been really useful.
  • Having now seen the completed PCBs, I could probably have left space for a regulator, especially one of those DC-DC converter regulator replacements that doesn’t require a heatsink.
  • I should consider adding a 3V3 regulator too rather than driving all the displays through the Waveshare Zero’s onboard 3V3 regulator.

Find it on GitHub here.

Sample Applications

The GPIO layout for the PCB with various Waveshare Zero boards is given below.

FunctionWSZ PinRP2040ESP32-C3ESP32-S3VCCPowerH1 P33V33V33V3GNDGroundH1 P2GNDGNDGNDRXMIDI INH2 P2GP1 (U0/RX)GP20 (U0/RX)GP44 (U0/RX)TXMIDI OUTH2 P1GP0 (U0/TX)GP21 (U0/TX)GP43 (U0/TX)DCData/CommandH2 P5GP4GP10GP11RESResetH2 P9GP8GP6GP7SDAData (MOSI)H2 P8GP7GP7GP8SCLClock (SCLK)H2 P7GP6GP8GP9CS1CS Display 1H2 P6GP5GP9GP10CS2CS Display 2H1 P9GP14GP5GP6CS3CS Display 3H1 P8GP15GP4GP5CS4CS Display 4H1 P7GP26GP3GP4CS5CS Ext Display 5H1 P6GP27GP2GP3CS6CS Ext Display 6H1 P5GP28GP1GP2CS7CS Ext Display 7H1 P4GP29GP0GP1CS8CS Ext Display 8H2 P4GP3GP18GP12

The application described here can be used to test the displays: Arduino with Multiple Displays – Part 2.

A more complete application for up to four (expandable to eight) displays can be found here: Arduino with Multiple Displays – Part 3.

Using a Waveshare Zero ESP32-S3, the following will test the MIDI IN and OUT:

#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

void setup() {
MIDI.begin(MIDI_CHANNEL_OMNI);
pinMode (LED_BUILTIN, OUTPUT);
}

void loop() {
if (MIDI.read()) {
midi::MidiType type = MIDI.getType();

if (MIDI.isChannelMessage(type)) {
midi::Channel ch = MIDI.getChannel();
midi::DataByte d1 = MIDI.getData1();
midi::DataByte d2 = MIDI.getData2();
switch(type) {
case midi::NoteOff:
digitalWrite (LED_BUILTIN, LOW);
break;

case midi::NoteOn:
digitalWrite (LED_BUILTIN, HIGH);
break;

default:
break;
}
}
}
}

Closing Thoughts

This seems to work pretty well. I’ve not really put it through its paces yet, but driving the displays is working and so is MIDI.

I have a specific application in mind, but first I need to see if it is possible to link these boards together to get more displays running. That is explored here Waveshare Zero Multi Display PCB – Expander Board.

Kevin

#include #midi #pcb #st7735 #WaveshareZero

Simple DIY Electronic Music Projectsdiyelectromusic.com@diyelectromusic.com
2025-08-14

Waveshare Zero Multi Display PCB Design

Following on from my Arduino with Multiple Displays – Part 2, using a Waveshare Zero type module, I wanted to try even more displays in parallel. I don’t know what the performance implications will be, or even if it is possible, but I do know I don’t really want to be using jumper wires to try it out. This PCB will hopefully allow me to hook up at least four displays to a Waveshare Zero format board.

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

If you are new to electronics and microcontrollers, see the Getting Started pages.

The Circuit

This is following pretty much directly on from Arduino with Multiple Displays – Part 2. One thing I wanted however was the possibility of connecting two panels together with a single microcontroller, so I’ve passed all control signals onto pin headers with the option for four more displays on a second PCB.

All displays share SCL, SDA, RES and DC. It is only the CSn pins that have to be independent, so I need to support up to 8 CSn lines. I’ve chosen the GPIO pins I have for the widest compatibility between the RP2040, ESP32-C3 and ESP32-S3.

CS8 on an ESP32-C3 might cause issues as it might clash with one of the USB signals, I’ll have to see. Worst case is that an ESP32-C3 can only support up to 7 displays. That is assuming the software performance is good enough for more than four in the first place of course.

I’ve included a MIDI IN/OUT circuit and 5V power regulator circuit as an option, but really I’m expecting it to be powered from the Waveshare Zero USB port.

PCB Design

The displays are arranged on one side of the PCB and the Waveshare Zero and other components are on the underside.

I’ve opted not to include the regulator power circuitry in the final PCB, but I have included the barrel jack and jumpers to allow a +5V (only) supply as an option. To save changing the schematic, I replaced the regulator bypass jumper with a (closed) solder bridge.

I had to use a custom footprint for the displays, but it is loosely based on an Adafruit display component. I have two versions – one with mounting holes and one without. Even through the mounting holes are present in the “user drawings” layer, they are not actual holes on the PCB.

I’ve duplicated a number of the silkscreen labels on both sides of the board for easy reference.

Closing Thoughts

Four displays fit really neatly into a 100x50mm footprint making these boards pretty cheap to get manufactured.

Kevin

#midi #pcb #st7735 #WaveshareZero

diyelectromusicdiyelectromusic
2025-07-20

More multi-SPI display messing around. This time using Waveshare Zero format boards, finding a common way to drive them from a RP2040, ESP32S3 or ESP32C3.

I hadn't realised SPI on the ESP32S3 was so complex!

(or that finding some common physical pins across the range required so much software messing about too).

diyelectromusic.com/2025/07/20

Photo of a Waveshare ESP32S3 Zero independently driving two small SPI displays all plugged into two mini solderless breadboards and connected via jumper wires.
Simple DIY Electronic Music Projectsdiyelectromusic.com@diyelectromusic.com
2025-07-20

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-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:

If you are new to microcontrollers, see the Getting Started pages.

Parts list

  • A Waveshare Zero format board or similar
  • 2x 0.96″ ST7735 60×180 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:

DisplayFunctionRP2040ESP32-C3ESP32-S3BLKBacklight control
(not required)N/CN/CN/CCSChip select
One per display.5 or any SPI0 CS1010DCData/Command888RESReset1499SDAData (MOSI)3 or any SPI0 MOSI6 or 711SCLClock (SCLK)2 or any SPI0 SCLK4 or 612VCCPower3V33V33V3GNDGroundGNDGNDGND

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.

DisplayFunctionWS PinRP2040ESP32-C3ESP32-S3BLKBacklight control
(not required)N/CN/CN/CCS1Chip select
Display 1H2 P6GP5GP9GP10DCData/CommandH2 P5GP4GP10GP11RESResetH2 P9GP8GP6GP7SDAData (MOSI)H2 P8GP7GP7GP8SCLClock (SCLK)H2 P7GP6GP8GP9VCCPowerH1 P33V33V33V3GNDGroundH1 P2GNDGNDGNDCS2CS Display 2H1 P9GP14GP5GP6CS3CS Display 3H1 P8GP15GP4GP5CS4CS Display 4H1 P7GP26GP3GP4

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
#endif

#ifdef WS_ESP32C3_ZERO
#define SPI_SS 9
#define SPI_MOSI 7
#define SPI_SCLK 8
#define SPI_MISO 0 // Not used
SPIClass MySPI(FSPI);
#define TFT_CS1 SPI_SS
#define TFT_CS2 5
#define TFT_CS3 4
#define TFT_CS4 3
#define TFT_RST 6
#define TFT_DC 10
#endif

#ifdef WS_ESP32S3_ZERO
#define SPI_SS 10
#define SPI_MOSI 8
#define SPI_SCLK 9
#define SPI_MISO 1 // Not used
SPIClass MySPI(FSPI);
#define TFT_CS1 SPI_SS
#define TFT_CS2 6
#define TFT_CS3 5
#define TFT_CS4 4
#define TFT_RST 7
#define TFT_DC 11
#endif

#ifdef WS_RP2040_ZERO
Adafruit_ST7735 tft1 = Adafruit_ST7735(TFT_CS1, TFT_DC, TFT_RST);
Adafruit_ST7735 tft2 = Adafruit_ST7735(TFT_CS2, TFT_DC, -1);
#else
Adafruit_ST7735 tft1 = Adafruit_ST7735(&MySPI, TFT_CS1, TFT_DC, TFT_RST);
Adafruit_ST7735 tft2 = Adafruit_ST7735(&MySPI, TFT_CS2, TFT_DC, -1);
#endif

void setup() {
#ifdef WS_RP2040_ZERO
SPI_BUS.setRX(SPI_MISO);
SPI_BUS.setCS(SPI_SS);
SPI_BUS.setSCK(SPI_SCLK);
SPI_BUS.setTX(SPI_MOSI);
SPI_BUS.begin(true);
#else
MySPI.begin(SPI_SCLK, SPI_MISO, SPI_MOSI, SPI_SS);
pinMode(SPI_SS, OUTPUT);
#endif

tft1.initR(INITR_MINI160x80_PLUGIN);
tft2.initR(INITR_MINI160x80_PLUGIN);
tft1.setRotation(3);
tft1.fillScreen(ST77XX_BLACK);
tft2.setRotation(3);
tft2.fillScreen(ST77XX_BLACK);
}

void loop() {
unsigned long time = millis();
tft1.fillRect(10, 20, tft1.width(), 20, ST77XX_BLACK);
tft1.setTextColor(ST77XX_GREEN);
tft1.setCursor(10, 20);
tft1.print(time, DEC);
delay(100);

time = millis();
tft2.fillRect(10, 20, tft2.width(), 20, ST77XX_BLACK);
tft2.setTextColor(ST77XX_MAGENTA);
tft2.setCursor(10, 20);
tft2.print(time, DEC);
delay(400);
}

Closing Thoughts

It is a little annoying that these great boards don’t share a re-usable, common pinout in terms of naming and positions, but I guess that isn’t the main focus for these systems.

Still, it seems that a common hardware pinout can be made that supports many displays, which is great, as I’d really like to get a number of them onto a PCB!

Kevin

#arduinoUno #esp32c3 #ESP32s3 #rp2040 #st7735 #tftDisplay #WaveshareZero

diyelectromusicdiyelectromusic
2025-04-27

The designs are up for my single-knob, MIDI controller using a Duppa small RGB LED ring and in this case a Waveshare Zero RP2040 board.

diyelectromusic.com/2025/04/27

Photo of a stack comprising: Waveshare Zero format board, upside down at the bottom, plugged into a bespoke PCB in the middle with a Duppa small 24-RGB LED ring PCB on the top.  There is a potentiometer poking through the centre of the Duppa board.Photo of the same device, but this time in a cubic 3D printed case.  There are 24 holes in a ring on the top for the LEDs and a black knob on the shaft of the potentiometer.  A USB cable is plugged in on one side and a TRS socket can be seen slightly poking out another.
Simple DIY Electronic Music Projectsdiyelectromusic.com@diyelectromusic.com
2025-04-27

Duppa I2C MIDI Controller 3D Print Case

This is a simple 3D printed case for my Duppa I2C MIDI Controller PCB.

https://makertube.net/w/nf7u1sYBRRzj2TUBRduQC2

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

If you are new to microcontrollers, see the Getting Started pages.

Parts list

OpenSCAD Design

This uses some of the techniques from my Raspberry Pi 2,3,4 A+/B+ Synth Cases to define a basic box, then some cut-outs, and then to split the box and add some overlapping “lips” for a snap-fit.

There a number of functions to achieve this, but some of them are just collecting together the others in the right sequence.

  • rounded – a basic “rounded” box module.
  • standoff – the PCB supports.
  • build_lips/build_lip – as expected, creates the overlapping lips. There is a parameter (solid) which determines if the lip is added to or subtracted from the case.
  • base – the main box shape, less the actual top.
  • top – the top plate that includes holes for the potentiometer and the LED ring.
  • box – uses base() and top() to build a complete box.
  • box_base/box_top – uses box and an intersection to produce the two halves of the main box.

At the top level box_base, box_top and standoff (four times) actually builds the complete case.

In terms of assumptions about the build:

  • Most importantly, this assumes the use of PH5.0 headers to mount the Waveshare Zero device.
  • It also assumes the use of a serial MIDI TRS socket.
  • It should allow for M3 spaces and is build to assume two sets of 10mm spacers as described in the Build Guide.

Notes on printing:

  • I found getting adhesion for the top with all those circular holes quite a challenge. In the end I increased the bed temperature and slowed the print right down to around 40% for the first layer and that seemed to improve thing quite a bit.
  • Once complete I had to tidy up the LED holes a little by hand with a 2.5mm drill bit.
  • The additional tag above the USB socket is quite delicate, so care is needed when snapping the case together.

Errata/Improvements:

  • For my own build, the potentiometer shaft doesn’t stick out as much as I’d like. It is hard to find a knob that doesn’t have to be altered to fit and stay in place.
  • I did wonder about using a thinner layer of 3D print over the LEDs rather than complete holes. I might still try that as an option to see how it works.

Find it on GitHub here.

Closing Thoughts

This is a little tall, but I’m not sure what, in reality I could do about that. There might be some option for shrinking it a little, especially if the Waveshare Zero RP2040 is soldered directly to the PCB. But it would only save, maybe up to 6 mm in height, so it is probably not worth the effort.

But apart from that, this seems to have come out really well. The holes the LEDs I thought were perhaps a bit of a compromise, but actually they seem to work fine.

Kevin

#controlChange #duppa #midi #potentiometer #WaveshareZero

Simple DIY Electronic Music Projectsdiyelectromusic.com@diyelectromusic.com
2025-04-27

Duppa I2C MIDI Controller PCB Build Guide

Here are the build notes for my Duppa I2C MIDI Controller PCB.

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments! 

If you are new to microcontrollers, see the Getting Started pages.

Bill of Materials

  • Duppa I2C MIDI Controller PCB (GitHub link below)
  • Waveshare Zero format dev board
  • 1x Duppa Small RGB LED Ring
  • 10KΩ potentiometer
  • 5-pin plug and lead (see photo).
  • 1x 100nF ceramic capacitor
  • Optional: 1×10Ω, 1×33Ω resistor
  • Optional: 1x 3.5mm stereo TRS socket – PCB mount (see footprint and photos)
  • Optional: 2x 9-way header sockets. Ideally low-profile, PH5.0 sockets.

There are a range of possibilities for the potentiometer, so one has to consider if mountings are required or if a knob will be used. These are some of the pots I could have used:

I used the one with a nut in the end and plan to add a knob at some point.

On that lead… The Duppa ring is described as requiring a “5-way Molex Picoblade, 1.25mm pitch” connector. The lead I ended up with was described on an online, overseas marketplace, as “JST 1.25mm” which I’m not sure is strictly a thing, but that is what worked for me.

Build Steps

Taking a typical “low to high” soldering approach, this is the suggested order of assembly:

  • Resistors and diode.
  • Disc capacitors.
  • TRS socket (if used).
  • If using headers for the devboard, now is a good time to solder those.
  • Potentiometer.
  • Duppa connector cable.

Be sure to get the connector cable the right way round. For the colouring of the cable above, and orientation of the pins, the I2C connectors ended up being the red and black ones for me. More about that in a moment.

Here are some build photos.

The cable has to be cut and then positioned to correctly align with the positions of the wires on the Duppa connector. The following shows which wires align to which solder pads and the position in the connector.

Once all soldering is complete, I used 8x 10mm M3 spacers as shown below.

I’m planning on designing an enclosure that the above posts will slot into. You may need different senses and sizes of spacers depending on your final arrangements.

Testing

I recommend performing the general tests described here: PCBs.

Note that the LED ring is configured using solder jumpers as described previously, for S1, S5 and to use pull-ups, as shown below.

PCB Errata

There are the following issues with this PCB:

  •  None at this time.

Enhancements:

  • The schematic already supports MIDI IN in addition to MIDI OUT, so at some point I could add that too. 

Find it on GitHub here.

Sample Applications

This is designed for use with my Duppa I2C MIDI Controller – Part 4. The Arduino code for that works directly when used with a Waveshare Zero RP2040 with the following configuration:

#define WAVESHARE_RP2040

#define MIDI_USB
#define MIDI_SER

#define LED_PER_CC
#define LED_SCALE_TO_RING

#define CC_POTENTIOMETER
#define PIN_ALG A3
#define MAX_POT_VALUE 1023

The full code is available on Github here.

Closing Thoughts

I’m really pleased with how this turned out. These LED rings are really neat!

Now on to that case…

Kevin

#controlChange #define #midi #pcb #potentiometer #WaveshareZero

Simple DIY Electronic Music Projectsdiyelectromusic.com@diyelectromusic.com
2025-04-27

Duppa I2C MIDI Controller PCB Design

This is the design for a simple carrier PCB for a Waveshare Zero format microcontroller and a Duppa small LED Ring. It is essentially a PCB version of Duppa I2C MIDI Controller – Part 4.

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments! 

If you are new to microcontrollers, see the Getting Started pages.

The Circuit

This connects a Waveshare Zero format board to a MIDI IN and OUT interface and a potentiometer. There is a header required to connect to the Duppa Small LED ring.

The following IO pins are used:

Physical PinGPIO: C3, S3, RP2040Function1Power5V2GroundGND3Power3V34GP0, GP1, A3Potentiometer13GP9, GP10, GP5LED SCL14GP10, GP11, GP4LED SDA17GP20, RX, GP1MIDI RX18GP21, TX, GP0MIDI TX

For the RP2040 this is using I2C0 and UART0.

PCB Design

I’ve actually opted not to include MIDI IN functionality in order to keep within a minimal PCB footprint. I’m aiming to have it occupy essentially the same space as one of the small Duppa LED rings itself. I’m also only support MIDI OUT via a TRS jack.

But I have attempted to ensure that both the Waveshare USB socket and TRS socket will protrude enough to be brought out to the edge of a case.

I’ve included a 2.54mm pitch set of header pads that I plan to solder a connecting wire to for the Duppa ring.

Closing Thoughts

I was in two minds about including MIDI IN. It is nice to be able to use this to merge into an existing MIDI stream, but then I also considered that it would probably be used just as a controller in most cases, so went with the small PCB footprint.

I also considered the four control options I’ve experimented with so far. In the end I decided I still liked having an absolute-value potentiometer for a MIDI Controller like this over either a rotary encoder or an endless potentiometer, so that is what I’ve used.

Kevin

#controlChange #midi #pcb #potentiometer #WaveshareZero

Simple DIY Electronic Music Projectsdiyelectromusic.com@diyelectromusic.com
2025-04-06

Duppa I2C MIDI Controller – Part 4

This is revisiting my Duppa I2C MIDI Controller this time using a Waveshare Zero format device.

  • Part 1 – getting to know the devices and testing them out.
  • Part 2 – adding MIDI to the LED ring and I2C encoder.
  • Part 3 – adding normal encoder, plain potentiometer, and endless potentiometer control.
  • Part 4 – revisits the idea with Waveshare Zero format devices and adds USB MIDI.

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

If you are new to Arduino, see the Getting Started pages.

Parts list

  • Waveshare Zero ESP32-S3 or RP2040.
  • DuPPa small RGB LED Ring.
  • 10K potentiometer.
  • Bespoke hook-up wires (available from duppa.net).
  • Optional: 3V3 MIDI Interface.
  • Breadboard and jumper wires.

Waveshare Zero, Duppa LED Ring, Potentiometers

I’m planning on being able to use any Waveshare Zero format board that I have (so that includes ESP32-S3, ESP32-C3 and RP2040) with the Duppa Ring so that means finding common pins to support I2C.

From the various pinouts (see Waveshare Zero, Pimoroni Tiny, and Neopixels) I can see I can use two pins in the bottom right-hand (with the USB connector at the top) corner of the board.

I’ll also need an analog connection and potentially connecting RX/TX to MIDI.

The various pins I’ll be using are as follows:

PinFunctionESP32-S3ESP32-C3RP204015V2GND33V34ADCGP1GP0GP29/A313SCLGP10GP9GP514SDAGP11GP10GP417RXGP44GP20GP118TXGP43GP21GP0

Note, I’m not using physical pins 11 and 12, even though they also support I2C, as for the RP2040, these are on I2C bus 1, not 0 (see note later).

As the Pimoroni Tiny2040 is largely compatible too, that could also be used, but it will be physical pins 11 and 12, corresponding to GP5 and GP4, and 15 and 16 for GP1, GP0 (RX,TX).

The LEDs on the LED ring are powered from 5V, which comes directly off the Waveshare Zero USB port. The logic “VIO” is powered from 3V3.

The Code

I2C LED Ring

As the I2C pins to be used are configurable, this means changing the Duppa example code (and any other Arduino code) to initialise the I2C bus on specific pins as follows:

Wire.begin(11,10);    // SDA, SCL for ESP32-S3
Wire.begin(10,9); // SDA, SCL for ESP32-C3

Using the ESP32 Arduino Core, there is a specific board entry for the Waveshare Zero ESP32-S3. There isn’t one for the ESP32-C3 so I just used “ESP32C3 Dev Module”.

I used the Arduino core for RP2040 from here rather than the official core: https://github.com/earlephilhower/arduino-pico

But the I2C initialisation is a little different.

  Wire.setSDA(4);
Wire.setSCL(5);
Wire.begin();

If I’d have been using GP6 and GP7, then these would have required the initialisation of Wire1 rather than Wire with the RP2040 core.

Note: to use the serial port once a sketch has been loaded onto the board, requires the following to be set (via the Arduino Tools menu):

USB CDC On Boot -> Enabled

Once again, I’ve soldered the jumpers on the LED ring to enable pull-ups and set the address for S1 and S5, so that has to be changed in the demo code too.

Analog Potentiometer

In terms of analog read, the ESP32 has a resolution of 0..4095 compared to the Arduino’s 0..1023, so that has to be taken into account when calculating the MIDI CC values.

To do this, the reading has to be divided by the ratio of Pot Range / 128.

int newpot = algpot.avgeAnalogRead(PIN_ALG) / ((MAX_POT_VALUE+1)/128);

Serial MIDI

For these boards, the serial port has to be specified. There are different options depending on the board being used (more here).

To use the pins nominally designated as RX/TX on all of these boards, use:

// ESP32-S3 GP43,GP44 or ESP32-C3 GP20,GP21
MIDI_CREATE_INSTANCE(HardwareSerial, Serial0, MIDI);
// RP2040 GP1,GP0
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);

It is a quirk of the RP2040 Arduino core that UART0 appears on Serial1 and UART1 on Serial2. Serial0 does not exist but USB is Serial (more here).

Also, for the RP2040 the pins can be changed prior to calling MIDI.begin() if required as follows:

Serial1.setRX(rxpin);
Serial1.setTX(txpin);
MIDI.begin();

MIDI USB

I want to make this a fairly stand-alone MIDI USB device, so for the ESP32 and RP2040 this means using the TinyUSB stack. There is an Adafruit library for Arduino that supports both and also works with the Arduino MIDI Library. References:

I’ve cribbed most of the code from: https://github.com/adafruit/Adafruit_TinyUSB_Arduino/blob/master/examples/MIDI/midi_test/midi_test.ino

And added the appropriate parts to my own midiSetup() and midiLoop() functions.

MIDI USB – ESP32-S3

For this to work on the ESP32-S3, the board settings (via the Arduino Tools menu) need to be changed as follows:

USB CDC On Boot -> Enabled
USB Mode -> USB-OTG (TinyUSB)
USB Firmware MSC On Boot=Disabled
USB DFU On Boot=Disabled

Naturally this means USB can’t be used for serial output anymore.

It also means that automatic sketch reset and download often didn’t work for me. It was quite normal to now have to use the BOOT and RESET buttons to get the ESP32 back into listening for a new sketch – not always, but also not uncommon. But this might be some serial port remapping weirdness that often occurs when the USB stack is running on the same microprocessor as the main code…

MIDI USB – RP2040

For the RP2040, the USB stack needs to be changed from the Pico SDK to TinyUSB, so in the Tools menu:

USB Stack -> Adafruit TinyUSB

There are some other RP2040 specific notes here, but I don’t believe they apply unless one is interested in rebuilding the core, default TinyUSB support directly.

USB MIDI – ESP32-C3

I don’t believe USB MIDI works on the ESP32-C3

Adafruit TinyUSB doesn’t seem to anyway and I haven’t looked into what the options might be yet.

Other Notes

I’ve left in all the conditional compilation from Duppa I2C MIDI Controller – Part 3 but for now am just working with potentiometer control.

Pretty much everything is configurable, but the most important config option is to specify the board at the top:

//#define WAVESHARE_ESP32S3
//#define WAVESHARE_ESP32C3
#define WAVESHARE_RP2040

I could probably auto detect from the build settings but for now, this will do.

Other options include GPIO pins, whether to include serial or USB MIDI (or both), and whether to enable MIDI THRU or not.

Find it on GitHub here.

Closing Thoughts

This is the first go at getting my Duppa controller working on 3V3 Waveshare Zero format boards, and so far it looks pretty good.

For the ESP32-S3 and RP2040 being able to enable MIDI USB is particularly useful. I might see if I can support MIDI THRU across the interfaces, which might be handy for a built-in USB to serial MIDI converter, but for now MIDI THRU is on the same port only.

I’ve not tested this with encoders or the endless potentiometer, but in theory it ought to work. I’d have to add some conditional compilation for GPIO numbers if I want to keep the same physical pins again.

Kevin

#controlChange #duppa #endlessPotentiometer #esp32c3 #ESP32s3 #i2c #midi #potentiometer #rgbLed #rotaryEncoder #rp2040 #WaveshareZero

Simple DIY Electronic Music Projectsdiyelectromusic.com@diyelectromusic.com
2025-04-04

Forbidden Planet “Krell” Display – MIDI CC Controller – Part 2

This revisits my Forbidden Planet “Krell” Display – MIDI CC Controller using my Forbidden Planet “Krell” Display PCB with a Waveshare RP2040 to create more of a “all in one” device.

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

If you are new to Arduino, see the Getting Started pages.

Parts list

PCB

This requires a built of the Forbidden Planet “Krell” Display PCB with the following:

  • 2 potentiometers
  • MIDI IN and OUT

I’ve used potentiometers that are their own knob, as they only poke through the casing by around 5mm or so.

If it you are able to get longer shaft pots, then that would probably be worthwhile.

Updated 3D Printed Case

This requires the following from the Krell Display 3D Printed Case:

This requires the following options in the OpenSCAD code:

show_frame = 1;
show_quadframe = 0;
show_insert = 1;
show_support = 0;
show_quadsupport = 0;
show_eurorack = 0;
show_eurorack_support = 1;

alg_pot1 = 1;
alg_pot2 = 1;
alg_cv = 0;

The frame does not really take into account the PCB at present, but I’ve reached the “good enough I want to do something else” stage, so I’ve just added a couple of small cut-outs (using a hacksaw) for the two MIDI sockets, and am content that the components stick out a bit from the back.

This cutout has to be 10.5mm from the end, 6mm wide, and 5mm deep.

At some point I might go back and design a deeper frame that has the cut-outs included and some kind of snap-on back to make it a self-contained box.

But for now, this is left as an exercise for, well, anyone else 🙂

Construction

I’ve used four brass 6mm spacers to screw into the mounting holes in the frame. Then the PCB can be inserted, taking care to squeeze in the 3D printed support around the LEDs and pots, and fixed with 20mm spacers which will also act as “legs”.

The Code

I’ve used a Waveshare Zero RP2040 and Circuitpython for this build. This is a combination of some of the test code used for the Forbidden Planet “Krell” Display PCB but with added MIDI.

The code supports both Serial and USB MIDI.

I wanted an equivalent of the Arduino map() and constrain() functions and didn’t immediate spot them in Circuitpython so wrote my own:

def algmap(val, minin, maxin, minout, maxout):
if (val < minin):
val = minin
if (val > maxin):
val = maxin
return minout + (((val - minin) * (maxout - minout)) / (maxin - minin))

This allows me to map the analog read values (0 to 65535) down to MIDI CC values (0 to 127) whilst also allowing for some inaccuracies (I’ve treated anything below 256 as zero for example):

alg1cc = int(algmap(alg1_in.value,256,65530,0,127))

I’ve used the Adafruit MIDI library, which I’m still not really a fan of, but I wanted to include MIDI THRU functionality to allow the controller to sit inline with an existing MIDI stream. But it doesn’t seem to work very well.

I was already only updating the LEDs/MIDI CC if the pot values had changed, to cut down on the number of Neopixel writes required.

I experimented with changing the scheduling of the analog reads and MIDI but that didn’t seem to help very much. In the end I made sure that all MIDI messages queued up in the system would be read at the same time before going back to checking the pots.

    msg = midiuart.receive()
while (msg is not None):
if (not isinstance(msg, MIDIUnknownEvent)):
midiuart.send(msg)
msg = midiuart.receive()

It will do for now. Moving forward, I might try the Winterbloom SmolMIDI library. If that still doesn’t give me some useful performance then I might have to switch over to Arduino C.

Find it on GitHub here.

Closing Thoughts

The MIDI throughput is disappointing, but then I’ve never really gotten on with the Adafruit MIDI library. I use it as USB MIDI on Circuitpython is so easy, so will need to do something about that.

I’m still deciding on the PCB-sized supports too. The original seemed to have nicer diffusion of the LEDs, but that could have been the difference between 5mm SMT neopixels and these THT APA106s which seem more directional in the first place.

And I really ought to finish the 3D printed case properly too.

So this is “that will do” for now, but I ought to come back and finish it off properly at some point.

Kevin

#APA106 #circuitpython #ForbiddenPlanet #Krell #midi #midiController #NeoPixel #potentiometer #rp2040 #WaveshareZero

Simple DIY Electronic Music Projectsdiyelectromusic.com@diyelectromusic.com
2025-03-30

Forbidden Planet “Krell” Display PCB Design

This is a PCB to support one of my dual Forbidden Planet “Krell” Displays. Rather than using ready made programmable LED rings, this is using through-hole APA-106 programmable RGB LEDs.

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

If you are new to microcontrollers and electronics, see the Getting Started pages.

The Circuit

I want this circuit to support the following:

I’ve chosen to include a single 5V power jumper for power in, so will consider any EuroRack style powering options as a separate project.

A standalone instance of this would be fine to be powered using the USB connection of the Waveshare Zero board chosen.

I’ve included some optional breakout headers for spare GPIO pins.

I’m using the GPIO of a Waveshare Zero compatible board as follows:

5V Power IN5VTXMIDI OUTGroundGNDRXMIDI IN3V3 Power OUT3V3GPIOLower LEDsLower Analog INADCGPIOUpper LEDsUpper Analog INADCGPIOADCGPIOADCGPIOGPIOGPIOGPIOGPIO

The upper analog input I’m anticipating will be an (optional) potentiometer.

The lower analog input I’m planning to be either an (optional) potentiometer or a (optional) CV input, so I’ve include some (also optional) CV input protection circuitry and a simple resistor divider to scale a 0 to 5V analog CV to a 0 to 3V3 range for use with the ADCs.

PCB Design

The size of the PCB is designed to fit inside my Forbidden Planet “Krell” Display.

The LEDs and potentiometers are on the non-component side of the PCB. I’ve used a staggered LED pin footprint to hopefully make soldering a little easier, but this does mean that the LEDs probably won’t fit flush to the board.

I’ve overlapped the footprints of the lower potentiometer and a “Thonkiconn” style mono jack, so the board can use one or the other (or neither).

MIDI circuitry is optional. CV in circuitry is also optional. I’ve attempted to highlight each within a silkscreen box to make it clearer which components relate to which part of the circuit.

The 2-pin power input header is also designed to be used to connect the board to a secondary power board (to be discussed in a future post).

There are additional breakout headers for a range of unused signals.

I’ve also included a breakout header for the additional analog and IO signals that could be used for a single microcontroller to link to a second PCB to support a four-way Krell display. These would have to be patch-wired into the appropriate header signals on the unpopulated microcontroller headers on the secondary PCB.

Closing Thoughts

Unfortunately I already know the Waveshare Zero footprint is 2.54mm too wide, as I used the same footprint as my Waveshare Zero MIDI Proto PCB Design.

Still, I should be able to provide the same workaround here when it comes to building the boards.

Kevin

#APA106 #Krell #midi #pcb #WaveshareZero

Simple DIY Electronic Music Projectsdiyelectromusic.com@diyelectromusic.com
2025-03-14

Waveshare Zero MIDI Proto PCB Design

In the spirit of several of the other microconroller prototyping MIDI boards I’ve already made, this is one for Waveshare Zero format boards.

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

If you are new to microcontrollers, see the Getting Started pages.

The Circuit

This is essentially a 3V3 MIDI IN/OUT circuit, a 7805 based power supply and headers for the prototyping area and the Waveshare Zero format board itself. I’ve included a solder jumper to allow the bypassing of the regulator if a 5V barrel supply is used instead (this can only be used if no regulator is fitted however).

The Waveshare Zero boards can be powered via 5V directly into the 5V pin.

The only pins on the Waveshare that are connected are the power, GND and RX/TX, as these tend to all be in the same place on these boards (more here: Waveshare Zero, Pimoroni Tiny, and Neopixels). All other pins find their way to headers.

PCB Design

This follows the format of my Nano MIDI Proto PCB Design and my XIAO MIDI Proto PCB.

There are a number of additional breakout header sections for the Waveshare Zero IO pins, plus 5V, 3V3, and GND.

All the power related circuitry is together near the top of the board. It includes a 5V header and an option for direct 5V via the barrel jack, if the regulator is left out. It also includes a 3-pin 2.54mm pitch header which can be used for a power switch for the barrel jack connection.

There are overlapping footprints for MIDI DIN and TRS, so either can be populated.

Closing Thoughts

Annoyingly there were two mistakes in the first version of this PCB:

  • The TRS sockets didn’t line up properly over the MIDI sockets.
  • The header sockets for the Waveshare Zero were 2.54mm too far apartt.

Both of these could be worked around (mostly), but these issues were fixed in the above versions of the board.

Kevin

#midi #pcb #waveshare #WaveshareZero

Client Info

Server: https://mastodon.social
Version: 2025.07
Repository: https://github.com/cyevgeniy/lmst