Bits and Droids logo
Mail icon

Custom ESP32 LCD PFD for MFS2020, part 1

3/30/2024 | by Bits and Droids

I wanted to create a single video explaining the basics of creating your own custom LCD PFD. After 6 hours of recording, I realized nobody would watch a full-fledged documentary even though you like the topic.

This episode will focus on the wiring and the inner workings of components wiring and inner workings components. The next one will explore basic graphics, followed by an episode about the touch functionalities. I aim to add a communications hub, GPS, and aircraft statistics for now, but more might follow over time. Don't forget that you can customize this fully to your liking.

Over time, we will add more windows, functionalities, and, most importantly, personality, so stay tuned, and let's dive right in.

flightcontroller side view
flight controller top view
flight controller back view

What do we need?

Some items are necessary to follow this series, while others are more of a personal preference.

Required:

Optional:

First of all, I wanted to address the elephant in the room. We won't be using an Arduino. The reasoning is simple. An Arduino can't keep up with an LCD screen of this size. The images will appear very flickering, or our Arduino will draw shapes at a snail's pace. Therefore, I'd recommend going with an ESP32. These boards are beefier, have WI-FI and Bluetooth capabilities, and can even run on the Arduino coding environment. The beauty is that these boards only set you back around 10 bucks. If you buy them per 3 (https://amzn.to/3yiIYC8), it can even drop to $8 per piece.

A Teensy is even more powerful but also costs more. If you want the most horsepower, you can pick one up (https://amzn.to/3jfLO4y) for $30https://amzn.to/3jfLO4y.

I've made the rotary encoders optional because they provide a way to navigate the screens and send inputs. If you want to use a different input method or don't want to use the same enclosure as me, you can swap them out for buttons.

The ESP32

The ESP32 is a board that can work with microcontrollers to a level that outshines our basic Arduinos. But even those of us who are just starting it out have ensured that you can use most of the Arduino functionalities and coding on this board, and they add even more where needed. Remember the video where I controlled my coffee maker over WIFI whenever I landed (https://youtu.be/U6VIocU2aFw)? Instead of an Arduino, I've used an ESP 32 for that project specifically because of its WIFI capabilities. An Arduino UNO has a clock speed of 16MHZ, while the ESP32 can dish out a whopping 240MHZ clock speed. I hope I've convinced you why we need a board of this caliber for this project.

esp32 pinout

4" SPI LCD with touch capabilities

If you don't use an ESP32, the pins on your board might not match these. I'd recommend reading the pinout of your board of choice.

The screen we will be using is a generic 4" TFT display. They are cheap but get the job done. Because we tried to save a buck and went with a rather low-cost screen, there will be some limitations, especially when displaying colors. A more high-end screen usually supports a color depth of 24 bits, while this one only supports up to 16.

If you want to follow along with all of the coding examples, I'd recommend using the same pins as I did.

Our screen uses the SPI protocol, allowing us to send a continuous data stream. Other protocols, like I2C (which we've used for smaller 16-digit LCD screens), usually send the data in packets. The ISP protocol is built around a master and slave data flow.

There are 4 pins of importance for this.

  • MOSI (Master output/slave input)
  • MISO (Master input/slave output)
  • CLK (Clock)
  • CS (Chip select)

Multiple SPI-enabled components can share the same MOSI, MISO, and CLK pins. Even though our screen has 1 row of available pins, 2 (and if you include the SD card, even 3) components use the SPI interface. The touch controller and LCD driver are separate entities. Therefore, the CLCK and MOSI lines of the touch screen and display can be routed to the same pin on our ESP32 (CLK = 18, MOSI = 23).

The clock pin determines the rhythm at which our data gets transported (it isn't called a clock without reason). For now, we won't dive too deep into this. Just make sure to use pin 18 for the clock on our ESP32.

On our touch pins, there is no marking called MOSI. They've gone with another term, T_DIN (Touch data in). MOSI refers to Master Out Slave In. Our touch driver has a pin called touch data in. Can you see the link? The T_DIN pin will probably receive data from our ESP32 and do something with that data. Our screen uses the same naming scheme (SDI or Screen data i). This is the pin that will receive the data displayed from the controller.

On the other hand, our touch controller also has a T_DO pin. This stands for touch data. Perhaps it might not be a surprise, but this will send data from our touchscreen toward our microcontroller (MISO = pin 19 on our ESP). Since we don't want to retrieve data from our display, we won't utilize its MISO (or SDO/screen data out) pin.

With ISP, it's important to utilize the correct pins on your microcontroller for it to work.

Function Pin

MOSI 23

MISO 19

CLK 18

I've already mentioned that we can merge our components to the same MISO/MOSI/CLK line. But how does our controller know which one to control at any given time? For this, we use the CS (Chip Select) pins. For this, we can use any open GPIO pin on our board. I went with 21 for the touchscreen and 2 for our display (DC/RS). By enabling/disabling the signal towards these pins, we ensure we don't send the wrong data to the wrong place (don't worry, the library will handle this all for us).

esp32 lcd wiring diagram

Dual concentric rotary encoders

Every hardcore flight simmer will tell you that dual concentric rotary encoders are the holy grail of components. These beauties control autopilots, radios, and many more. They are significantly more expensive than regular rotary encoders, though. With an ESP32 or Arduino, I always love to use the EC11EBB24C03 dual concentric rotary encoders. You can obtain them for around $7 apiece from AliExpress.

They look quite different from regular KY-40 encoders, for example, and they have 8 pins that aren't marked. So how do we know what pin to solder to our encoder? Simple: We Google the part number (EC11EBB24C03) and try to find a datasheet. You'll usually find a link to the pdf from wholesalers that carry your component (this time, I found https://bit.ly/37f2lQK).

dual concentric encoder diagram

The image above shows that 7 pins are marked A, C, B, D, and E. We also know that our switch has a momentary button (if you press the shaft). In almost all instances, a button consists of 2 pins. Therefore, I'm assuming that pins D and E are linked to this functionality by looking at the image. Using the same logic, I know that encoders usually have an A and B pin, so I'm guessing they match the A and B on the sheet. This is confirmed by the image below.

dual concentric encoder circuit diagram

We see an A terminal on the left side and a B terminal on the right. This diagram tells us that the C terminal needs to be connected to the ground (the //// icon at the bottom). It also expects us to apply a voltage with resistors on the A and B terminals. Instead of connecting the 5v line directly through some resistors towards our terminals, we can also use our board's internal pull-up resistors. The ESP32 has pullup resistors available on almost all GPIO pins. This lets us connect the A + B terminals directly to an open GPIO pin.

We could connect 3 ground wires for the inner, outer, and switch encoder. But just soldering these 3 pins together (see the connection diagram below) will reduce our outgoing wires from 8 to 6.

In the end, I've connected my double rotary encoder like this:

  • A-left → 32
  • B-left → 33
  • A-right → 25
  • B-right → 5

And the three ground pins to ground.

KY-40 / HW-40 rotary encoder

Last but not least, we've got a single rotary encoder to connect. For this, I've gone with a regular HW-40 encoder. These are the same as the well-known KY-40 encoders but have a shorter shaft. Luckily, these usually come pre-mounted on a small PCB that marks each pin. The only thing left is to connect these to our ESP32.

  • GND → GND
  • 5 V→ 5V
  • SW → to any open GPIO pin (I went with 12)
  • DT → to any open GPIO pin (I went with 14)
  • CLK → to any open GPIO pin (I went with 27)

Headers, connectors, and crimping

This step is completely optional, but I wanted to create something serviceable. If, for some reason, a component dies, I don't want to spend hours resoldering everything, organizing wires, or, god forbid, replacing the ESP32. I've picked up a crimping tool kit to create custom connectors.

This way, I can replace the ESP32 with a hot swap in under a minute. The modular encoders have already saved my life. One of my dual rotary encoders died (definitely due to my mishandling), and I only had to resolder the component on the proofing board and plug the connector back in. I was good to go.

I'd never seen the added value something as simple as this brings, but once you start using these puppies, you'll never want to go back.

esp32 removed from proofing board

esp32 on proofing board
esp32 on proofing board with cables attached