ArduinoMenu demo TTGO T-Display

This page is "work in progress". Although it is almost finished there still might be missing or incorrect parts on this page.

This page contains instructions on howto use a modified and extended version of the ArduinoMenu example sketch for the TFT_eSPI library which works better and a bit more advanced on the LilyGO TTGO T-display.

This article assumes you already have a basic knowledge of programming and Arduino.

Warning: Everything on this page is provided "as is". I can not guarantee the correctness and effectiveness of the provided information and sketch. I can not be held responsible for any damage to your dev board and accessories caused by using my information and sketch.

Introduction

ArduinoMenu is a "Generic menu/interactivity system for the arduino framework". It aims to help Arduino developers to create menu's more easily and supports a lot of different types of development boards, displays and input types: as long as they all have support in the Arduino IDE and are mentioned on the list on the Github page of ArduinoMenu: https://github.com/neu-rah/ArduinoMenu.

ArduinoMenu does have support for the TFT_eSPI library which is needed to drive the ST7789V display of the LilyGO TTGO T-display. ArduinoMenu also provides an example sketch on https://github.com/neu-rah/ArduinoMenu/blob/master/examples/adafruitGfx_eTFT/TFT_eSPI/TFT_eSPI.ino but this doesn't work without some modifications. Besides that the example could have shown some more capabilities of the LilyGO TTGO T-display. That is why I decided to create an modified and extended version of the example sketch and called it a demo sketch.

Sketch files

Below are the sketch files needed for this demo: ArduinoMenu_LilyGo_TTGO_T-display_demo.ino and bmp.h. You need to download both files and place them both in the same directory. To prevent a warning telling you that the sketch needs his own directory it's best to name the directory exactly the same as the INO file but without the .ino extension.

The differences between the original ArduinoMenu TFT_eSPI example sketch and my demo sketch are explained below. Below I also tell which settings are important, why they are important and how to configure some basic settings. I don't explain how ArduinoMenu works because this can be found on the Wiki pages of ArduinoMenu: https://github.com/neu-rah/ArduinoMenu/wiki

Arduino Community logo provided by Arduino.License: Commons license CC-SA-BY-NC 3.0

Differences and important settings

Summary

  • Added a bootlogo.

  • Added Button2 library to handle the buttonpresses of the 2 onboard buttons.

  • Added backlight control (intensity).

  • Added some serial output for debugging during boot (setup() fase).

In depth differences and important settings

All comparison is done against the TFT_eSPI example sketch of ArduinoMenu: https://github.com/neu-rah/ArduinoMenu/blob/master/examples/adafruitGfx_eTFT/TFT_eSPI/TFT_eSPI.ino

Bootlogo

The bootlogo is placed in the file bmp.h. It is is being referenced from the ArduinoMenu_LilyGo_TTGO_T-display_demo.ino file with a #include "bmp.h". Both files should show up as seperate tabs in the Arduino IDE.

After the design has finished and being saved as a 16 bit BMP file I converted the file to 16 bit R5G6B5 data with Riuson LCD Image Converter. Clear instructions how to convert color images can be found at https://www.instructables.com/id/Converting-Images-to-Flash-Memory-Iconsimages-for-/.

So far I didn't had any luck with converting monochrome images but you can use https://convertio.co/nl/image-converter/ for that: convert a monochrome BMP to XBM and copy the contents of the XBM file to the sketch. I won't explain it in any further detail because that is outside of the scope of this demo sketch.

Main edit window of LCD Image Converter

Conversion preview in LCD Image Converter

Variables, initializers, etc.

  • Right below #include <TFT_eSPI.h> I added the Button2 library with #include <Button2.h> and the bootlogo with #include "bmp.h".

  • Then I added:

#ifndef TFT_DISPOFF

#define TFT_DISPOFF 0x28

#endif


#ifndef TFT_SLPIN

#define TFT_SLPIN 0x10

#endif

This is a thing of which I don't know what it does and how it works. I just copied it from the examples of LilyGO's TTGO T-Display repository: https://github.com/Xinyuan-LilyGO/TTGO-T-Display/blob/master/TTGO-T-Display.ino

  • Then I added #define TFT_BL 4 from the TTGO T-display example sketch. This sets the pinnumber of the backlight of the ST7789V screen.

  • Adding a external led is optional. If an external led is connected you can set the correct pinnumber at #define LED_CTRL 0. You can leave this on 0 (zero) when you don't use an external led.

  • The backlight can be controlled with a PWM signal so I added an option to the menu to set the initial backlight intensity. The initial value can be set up at int ledBacklight = 80; The default of my demo sketch is 80 but you can set it to any number in the range of 0 to 255. If you set it at 0 the backlight will be off. All graphics will be send to the display but you won't see anything on the screen. The default TFT_eSPI and ArduinoMenu examples dont't set the backlight and the first issue I encoutered was seeing nothing on the display. The actual issue was not setting the backlight to the on state.

  • #define BTN_UP 35 and #define BTN_DWN 0 defines the pinnumbers of the onboard buttons. You don't need to change this unless you have attached external buttons and want to provide their pinnumbers.

  • I've changed TFT_eSPI gfx; to TFT_eSPI gfx = TFT_eSPI(135, 240); to provide the TFT_eSPI library the dimensions of the screen. The screen is driven as portrait mode and so the width is the small side with 135 pixels and the height is the long side with 240 pixels. In the sketch image rotation is enabled and thus everything will be displayed in landscape mode (quarter clockwise).

  • After the initialization of the screen I added the initializers of the 2 buttons right from LilyGO's example sketch:

Button2 btnUp(BTN_UP);

Button2 btnDwn(BTN_DWN);

  • Because PWM parameters on a ESP32 can't be set with the analogWrite() function because of lack of support for it in the board properties we need to set the PWM frequency, resolution and channel manually. After that we need to attach a pin to a PWM channel. Later on in the script you'll see how this works but first right after int ledCtrl=LOW; we set the values we need:

const int pwmFreq = 5000;

const int pwmResolution = 8;

const int pwmLedChannelTFT = 0;

You don't need to change these settings.

  • To be able to adjust the intensity of the backlight of the ST7789V screen I added in the main menu somewhere below

MENU(mainMenu,"Main menu",doNothing,noEvent,wrapStyle

this line:

,FIELD(ledBacklight,"Backlight: ","",0,255,10,5,doNothing,noEvent,wrapStyle)

ledBlacklight is the variable which holds the current intensity value (default of the sketch is 80 unless you changed it at the top of the sketch. In the menu you'll see Backlight: and the current value. When you enter the menu option you can increase or decrease the value by 10 and when you select the menu option again (long press on upper button) you can increase and degree by 5. The intensity is applied to the screen immediately so that you can see the impact of the intensity you have chosen.

  • I've changed:

#define GFX_WIDTH 128

#define GFX_HEIGHT 64

into:

#define GFX_WIDTH 240

#define GFX_HEIGHT 135

to meet the correct pixel dimensions of the screen.

  • I've changed:

#define fontW 6

#define fontH 9

into:

#define fontW 12

#define fontH 18

for better readability of the menu. Elsewise the text on the display would be hard to read. The display is clear but you would still need very good eyes to be able to read the text.

  • The idle function in the example sketch of ArduinoMenu for the TFT_eSPI library was very simple, a bit ugly and only showed "Suspended... press [select] to continue". I changed the idle function and wrote a better looking idle text with a big yellow "IDLE" and below that a text saying in white "Long press a button to exit".

  • I added a button handler based on the examples of the Button2 library on https://github.com/LennartHennigs/Button2/tree/master/examples. The function name of the handler is button_init(). The handler handles the following button press types:

    • Upper button

      • Short press: move selection upwards / decrease value

      • Long press: enter / select

    • Lower button

      • Short press: move selection downwards / increase value

      • Long press: back / exit (in the main menu this will start the idle function)

  • Below the button_init() function there is a function called button_loop() which will be called at each loop() iteration to process the button presses.

setup() function

  • In the setup() function I commented out the SPI.begin(); line since the TFT-eSPI library does handle the SPI. Leaving this uncommented causes the screen to display nothing.

  • The next part in the setup() function is configuring the PWM parameters, attaching it to the backlight pin and set the correct intensity:

    • ledcSetup(pwmLedChannelTFT, pwmFreq, pwmResolution); configures a PWM channel with the right PWM frequency and the right PWM resolution. All variables have been configured in the top of the sketch. The ESP32 has 16 PWM channels. We start with PWM channel 0.

    • ledcAttachPin(TFT_BL, pwmLedChannelTFT); attaches the configured PWM channel to the backlight pinnumber.

    • ledcWrite(pwmLedChannelTFT, ledBacklight); adjusts the backlight intensity by sending the intensity to the PWM channel which is attached to the backlight pin.

  • gfx.setRotation(1); rotates the screen a quarter clockwise so that everything is displayed in landscape mode.

  • gfx.setSwapBytes(true); is needed to do the Big / Little Endian conversion so that gfx.pushImage(0, 0, 240, 135, bootlogo); can be used to push the bootlogo to the screen.

  • Then I added a check whether a pinnumber for an external led has been set and if so this will be set to it's initial state.

  • gfx.fillScreen(Black); will blank the screen so that the menu can be printed to the screen without issues.

loop() function

  • button_loop(); is added to poll the button states of both buttons of the board.

  • Then again a check whether a pinnumber for an external connected led is provided or not. If so the current provided value for the external led will be set at that point. This will take effect immediately on the moment you change the value in the menu.

  • ledcWrite(pwmLedChannelTFT, ledBacklight); adjust the backlight intensity in the PWM channel that is attached to the backlight pin. It will be immediately adjusted as soon you change the value of the backlight intensity in the menu.

Uploading and running the sketch

Now you should be able to upload and run the sketch. It starts with a bootlogo and in the background of the bootlogo all things that needs to be setup at the setup() function are being executed. After that the loop() begins and the menu will be shown to you.

Again, here is how to use the buttons to navigate through the menu:

  • Upper button

    • Short press: move selection upwards / decrease value

    • Long press: enter / select

  • Lower button

    • Short press: move selection downwards / increase value

    • Long press: back / exit (in the main menu this will start the idle function)

When you open the Serial Monitor of Arduino (or another console which can read and write to the COM port) with a baudrate of 115200 you can see some debugging texts.

You can also operate the menu from the Serial Monitor by entering one of the following characters in the input field and press Enter or click on Send. The image shows Arduino in Dutch and thus the send button is labeled Verzenden.

  • -

    • Go up in the menu / decrease a value.

  • +

    • Go down in the menu / increase a value.

  • *

    • Select / enter.

  • /

    • Back / exit.

Ideas for future releases

Changelog

Version 0.3, September 27th, 2020

  • Fixed not working links to ArduinoMenu repository.

Version 0.2, September 8th, 2019

  • Updated description and quick instructions on top of the INO file.

  • Demo is now also available on the Github repository of ArduinoMenu, so I put a link to it in the Sketch files section of this page.

Version 0.1, August 29th, 2019

  • Initial version