ESP32 Development
Introduction
Workshop4 is a comprehensive software from 4D Systems providing a code and graphics editor for ESP32-S3 based modules. It can be used to design graphical interfaces for all sorts of applications using the IDE's various widgets. All application code can also be developed within the Workshop4 IDE, easily coupling it with the design, so is a one-stop shop for development with these modules.
The Workshop4 IDE utilises the Arduino IDE 2.x CLI to handle the compiling, linking and downloading of ESP32-S3 based projects, using the ESP32 Arduino Core and associated libraries, without having to interface with Arduino IDE at all.
Development Setup
This section describes how to set up Workshop4 and Arduino IDE for developing applications for 4D System's ESP32-S3 based display modules.
Both Workshop4 and Arduino IDE 2.x should be installed in your Windows computer.
To install Workshop4, please refer to the Installation section of the Workshop4 User Manual.
You can refer to this Arduino documentation for instructions on how to download and install Arduino IDE 2.
Note
Workshop4 is a Windows-only application.
ESP32 Arduino Boards
After installing both Workshop4 and Arduino IDE 2 on your system, Arduino needs to add the supported ESP32 boards which includes 4D Systems' ESP32-S3 based displays through its Boards Manager.
Follow these steps to install ESP32 Arduino compatible boards using Boards Manager.
-
Start Arduino IDE and open the Preferences Window.
-
Find Additional boards manager URLs and click the button to edit the list.
-
Add a reference to
https://espressif.github.io/arduino-esp32/package_esp32_index.json
and save. -
Open Boards Manager from Tools > Board menu.
-
Search and install esp32 by Espressif Systems.
You can refer to the official Espressif documentation for updated boards URL and more details.
GFX4dESP32 Library
Workshop4 development for 4D Systems' ESP32-S3 based displays relies on GFX4dESP32 library. This library needs to be installed alongside the Arduino IDE.
Install via Library Manager
Install the library using Arduino IDE's Library Manager by following the procedure below:
-
Open Library Manager by navigating menu: Sketch > Include Library > Manage Libraries
-
Search and install GFX4dESP32 by 4D Systems Pty Ltd.
-
Arduino IDE will prompt to install additional dependencies that are not currently installed.
Install from a ZIP Library
-
Download a ZIP copy of the library from the GitHub repository
-
Select the Add ZIP Library option from Sketch > Include Library menu.
-
Navigate to the downloaded zip file and click Open.
As of writing this document, this method doesn't prompt to automatically install dependencies. Therefore, dependencies need to be installed manually. As of the initial version of the library, the only dependency is SdFat library (GitHub Repository - v2.2.2).
Development Roadmap
After having completed the Development Setup, we can create and develop projects using Workshop4.
This section discusses the overall development process including graphics design, writing code and uploading to the display module.
Creating a New Project
Create a new project by following the procedure below:
-
Open Workshop4.
-
Select New and filter the ESP32 display modules by selecting Arduino Embedded from the dropdown menu
-
Find your display module from the list, select the orientation and confirm your selection.
A fresh project for the selected display will open in a new tab.
As shown, the project starts with an initial code. Please refer to the Preliminary Code section for a brief discussion.
Designing a Graphical Interface
By using Workshop4, it's easier than ever to design graphical user interfaces for ESP32 applications. It provides an easy-to-use WYSIWYG editor with support for multiple types of widgets including buttons, sliders, knobs and gauges.
You can refer to the Workshop4 Widgets Reference Manual for more information.
The widgets available for ESP32 devices mainly include GCI widgets and primitive shapes. Workshop4 provides all the available widgets for ESP32-S3 displays under the Widgets menu.
Writing Code
Workshop4 utilises Arduino CLI for compiling, linking and downloading of ESP32-S3 based projects. This lets user develop Arduino code from within Workshop4 IDE while working on a user interface.
Preliminary Code
Workshop4 provides initial code to start with. This includes setup code required for the screen and touch handling code for touch enabled display modules.
The code starts with including the appropriate header file from the GFX4dESP32 library.
Note
%%displaynm%%
is automatically replaced by Workshop4 with the name of the target display module,
making it easier to change between different 4D Systems ESP32-S3 modules without the need to
change this part of the code.
The setup code includes:
gfx.begin();
gfx.Cls();
gfx.ScrollEnable(false);
gfx.BacklightOn(true);
gfx.Orientation(%%orientation%%);
gfx.SmoothScrollSpeed(5);
gfx.TextColor(WHITE, BLACK);
gfx.Font(2);
gfx.TextSize(1);
gfx.Open4dGFX("NoName1"); // Opens DAT and GCI files for read
// using filename without extension.
gfx.touch_Set(TOUCH_ENABLE); // Global touch enabled
Note
%%orientation%%
is automatically replaced by Workshop4 depending on the target display orientationNoName1
is the default format for the name of an unsaved project file. This is carried over to the GCI/DAT files that's copied to the uSD card for GCI widgets. It is also automatically replaced when the project is saved assumming it wasn't edited manually.gfx.touch_Set(TOUCH_ENABLE);
is only generated for touch enabled display modules
The loop function includes touch handling code for touch enabled display modules:
int itouched, val;
if (gfx.touch_Update()) {
itouched = gfx.imageTouched();
// start touched selection
switch (itouched) { // **do not alter, remove or duplicate this line**
// case iKnob1: // case statement for Knobs and Sliders
// break;
// end touched selection
default: // **do not alter, remove or duplicate this line**
int button = gfx.ImageTouchedAuto(); // use default for keyboards and buttons
val = gfx.getImageValue(button);
// start button selection
switch (button) { // **do not alter, remove or duplicate this line**
// case one for each button or keyboard, default should end up as -1
} // end button selection **do not alter, remove or duplicate this line**
}
}
Warning
Please take note of the items are commented with "do not alter, remove or duplicate this line". These lines are used by Workshop4 to locate various sections of the code, for when the Paste Code option is used.
Generating Widget Code
Workshop4 is primarily designed for products powered by 4D graphics processors: PIXXI-44, PIXXI-28, DIABLO-16, PICASO and GOLDELOX. It provides multiple environments for developers allowing different level of expertise, from no coding at all to writing code from scratch.
Workshop4's ViSi environment provides the most versatility by allowing users to write their own code while providing a graphics editor. Furthermore, it provides a simple utility that generates code for each widget or object used in the project with a click of a button.
Similar to Workshop4's ViSi environment, ESP32-S3 project provides a Paste Code utility that can be used to generate relevant code for the widgets.
This option generates code to update or show widgets at the current cursor position, or more appropriate location or multiple locations in the project.
The following is a list of code snippets Workshop4 generate for a target Workshop4 object.
- Show widget initially - This is generated for all widgets in the setup function. This needs to run at least once when switching forms. The generated code must be edited to only show the current Form and widgets in it.
- Enabling touch - This is generated in the setup function together with showing the touch input widget once. The generated code must be edited to only enable the input widgets in the current active Form.
- Touch handling - This is generated in switch-case block in the loop function and can be used to handle which input widget is touched and its new value.
- Update widget value - This is generated for output widgets in the current cursor position.
Note
Workshop4 also generates code inside a header file <project name>Const.h
based on the widgets added to the project when the graphics is built.
This contains constants that can be seen generated with the Paste Code option.
If there's no generated graphics, this file will not be generated and should be commented out.
Here's an example single form project containing a gauge, a slider input and 2 buttons.
From this project, Paste Code option is used for all four widgets while the cursor is in the same position.
The generated code is as shown:
#include "gfx4desp32_%%displaynm%%.h"
gfx4desp32_%%displaynm%% gfx = gfx4desp32_%%displaynm%%();
#include "PasteCodeConst.h"
// Note. This file will not be created if there are no generated graphics
void setup()
{
gfx.begin();
gfx.Cls();
gfx.ScrollEnable(false);
gfx.BacklightOn(true);
gfx.Orientation(%%orientation%%);
gfx.SmoothScrollSpeed(5);
gfx.TextColor(WHITE, BLACK); gfx.Font(2); gfx.TextSize(1);
gfx.Open4dGFX("PasteCode"); // Opens DAT and GCI files for read using
// filename without extension.
gfx.touch_Set(TOUCH_ENABLE); // Global touch enabled
gfx.UserImages(iCoolgauge1,0) ; // init_Coolgauge1 show initially, if required
gfx.imageTouchEnable(iSlider1, true); // init_Slider1 enable touch of widget (on Form1)
gfx.UserImages(iSlider1,0) ; // init_Slider1 show initially, if required (on Form1)
gfx.imageTouchEnable(iWinbutton1, true, MOMENTARY);
// init_Winbutton1 enable touch of widget (on Form1)
gfx.UserImages(iWinbutton1,0) ; // init_Winbutton1 show initially,
// if required (on Form1)
gfx.imageTouchEnable(iWinbutton2, true, MOMENTARY);
// init_Winbutton2 enable touch of widget (on Form1)
gfx.UserImages(iWinbutton2,0) ; // init_Winbutton2 show initially,
// if required (on Form1)
} // end Setup **do not alter, remove or duplicate this line**
void loop()
{
// cursor position is below this comment during each use of 'Paste Code' option
gfx.UserImages(iCoolgauge1, frame) ; // where frame is 0 to 100 (for a displayed 0 to 100)
// cursor position is above this comment during each use of 'Paste Code' option
int itouched, val ;
if(gfx.touch_Update())
{
itouched = gfx.imageTouched() ;
switch (itouched)
{ // start touched selection **do not alter, remove or duplicate this line**
// case iKnob1 : case statement for Knobs and Sliders
// break ;
case iSlider1 : // process_Slider1 process (on Form1)
val = gfx.imageAutoSlider(iSlider1, HORIZONTAL_SLIDER, gfx.touch_GetX(), 8, 8);
// process Slider based on val
break ;
default: // end touched selection **do not alter, remove or duplicate this line**
int button = gfx.ImageTouchedAuto(); // use default for keyboards and buttons
val = gfx.getImageValue(button);
switch (button)
{ // start button selection **do not alter, remove or duplicate this line**
// case one for each button or keyboard, default should end up as -1
case iWinbutton1 : // process_Winbutton1 process Button (on Form1)
// process win button, for toggle val will be 1 for down and 0 for up
break ;
case iWinbutton2 : // process_Winbutton2 process Button (on Form1)
// process win button, for toggle val will be 1 for down and 0 for up
break ;
} // end button selection **do not alter, remove or duplicate this line**
}
}
}
Notice that despite the cursor being positioned at the same place for each widget, update code is only generated for the CoolGauge since it is the only output widget.
// cursor position is below this comment during each use of 'Paste Code' option
gfx.UserImages(iCoolgauge1, frame) ; // where frame is 0 to 100 (for a displayed 0 to 100)
// cursor position is above this comment during each use of 'Paste Code' option
Note
Notice that the generated code for CoolGauge includes the variable frame which pertains to the new value to update the gauge to. This variable is not automatically declared since users may prefer to use their own more meaningful variable names.
In the setup function, you'll find code to draw widgets initially and to enable touch for input widgets.
gfx.UserImages(iCoolgauge1,0) ; // init_Coolgauge1 show initially, if required
gfx.imageTouchEnable(iSlider1, true); // init_Slider1 enable touch of widget (on Form1)
gfx.UserImages(iSlider1,0) ; // init_Slider1 show initially, if required (on Form1)
gfx.imageTouchEnable(iWinbutton1, true, MOMENTARY);
// init_Winbutton1 enable touch of widget (on Form1)
gfx.UserImages(iWinbutton1,0) ; // init_Winbutton1 show initially,
// if required (on Form1)
gfx.imageTouchEnable(iWinbutton2, true, MOMENTARY);
// init_Winbutton2 enable touch of widget (on Form1)
gfx.UserImages(iWinbutton2,0) ; // init_Winbutton2 show initially,
// if required (on Form1)
This should be edited as needed as it is only generated to give a suitable starting point. Common changes that needs to be done are:
- handling multiple forms - not all forms are drawn at the start and therefore this needs to be edited to suit the project
- enabling/disabling touch - some applications may need to initially disable touch for input widgets and only enable at certain conditions
- hiding widgets initially - some applications may need to initially hide widgets and only show at certain conditions
Users can freely adjust their application code to suit their needs.
In the loop function, code is generated for each input widget inside the touch handling block from the initial code.
int itouched, val ;
if (gfx.touch_Update())
{
itouched = gfx.imageTouched() ;
switch (itouched)
{ // start touched selection **do not alter, remove or duplicate this line**
// case iKnob1 : case statement for Knobs and Sliders
// break ;
case iSlider1 : // process_Slider1 process (on Form1)
val = gfx.imageAutoSlider(iSlider1, HORIZONTAL_SLIDER, gfx.touch_GetX(), 8, 8);
// process Slider based on val
break ;
default: // end touched selection **do not alter, remove or duplicate this line**
int button = gfx.ImageTouchedAuto(); // use default for keyboards and buttons
val = gfx.getImageValue(button);
switch (button)
{ // start button selection **do not alter, remove or duplicate this line**
// case one for each button or keyboard, default should end up as -1
case iWinbutton1 : // process_Winbutton1 process Button (on Form1)
// process win button, for toggle val will be 1 for down and 0 for up
break ;
case iWinbutton2 : // process_Winbutton2 process Button (on Form1)
// process win button, for toggle val will be 1 for down and 0 for up
break ;
} // end button selection **do not alter, remove or duplicate this line**
}
}
The pasted code allows you to simply handle the new value of each input widget. Comments are provided to show which part of the code the touch input value can be handled.
Users can freely add code for handling the new value. However, it is always advisable to refrain from using blocking code as it can affect touch handling.
Warning
Please take note of the items are commented with "do not alter, remove or duplicate this line". These lines are used by Workshop4 to locate various sections of the code, for when the Paste Code option is used.
Programming the Display
Set Target Options
When working with ESP32-S3 devices, several options such as partition table, USB options, etc. can be set. In Arduino, these options can be set from Tools menu.
In Workshop4, the same option can be set by going to the Project menu and opening Project Options window by clicking the button as shown.
From this window, find 4D Systems gen4-ESP32 Modules (ESP32-S3R8N16)
Right click on it to open a dropdown menu.
Select the options as needed by your project and press OK.
System-Wide Target Options
Unlike Arduino IDE, Workshop4 provides both system-wide (IDE-wide) and project options. Changing the project target options won't affect the system-wide settings.
The system-wide options are used when creating a new project.
To change the system-wide options in Workshop4, go to File -> Options -> Arduino.
Uploading the Project
After setting the target options, the project can be compiled and uploaded.
Connect the display module via the USB-C port or using a 4D-UPA (revision 1.4 or higher) via the 30-way interface.
Select the target COM port for the display module.
From the Home menu, click Comp'nLoad to compile and load the program to the display.
Revision History
Document Revision
Revision Number | Date | Description |
---|---|---|
1.0 | 25/09/2023 | Initial Public Release Version |
1.1 | 20/02/2024 | Added note regarding Arduino ESP32 Core v3.0.0 |
1.2 | 29/04/2024 | Finalized PDF formatting |
1.3 | 10/06/2024 | Removed information regarding v3.0 alpha release since this version has been officially released |