DFR0669 + DFR0654: trouble with "createbutton" function

Hello everyone,
I’m a beginner in C programming and I’m using a 3.5″ DFR0669 screen with a FireBeetle ESP32, coding on the Arduino platform.
My project is to build an alarm clock by adding a DFPlayer Pro module, a speaker, and a large physical button for stop/snooze. Eventually, it will support up to four alarms with recurrence and allow me to choose a custom song for each.
The first screen connects the FireBeetle ESP32 to the network and lets you select the language, using credentials stored in a text file on an SD card attached to the display. After that, I plan to turn off Wi-Fi and synchronize with an NTP server once a day.
I’ve created my first screen and I’m now trying to add buttons to switch to the “Help” screen and to the next screen (Clock/Settings). I’m struggling with the createButton() function: I tested the example and it works fine, but I can’t implement it in my own code.
Actually, the font changes and a blue/gray area appears on the left as soon as I add the button, and my icon disappears, it doesn’t look right. Can someone help me fix this? Thanks!
I'm sharing the working/not working codes with pictures :-)
Working code and the result:
#include "WiFi.h"
#include "SD.h"
#include "SPI.h"
#include "DFRobot_UI.h"
#include "DFRobot_GDL.h"
#include "DFRobot_Touch.h"
#include "time.h"
#include "icon.h"
#define TFT_DC D2
#define TFT_CS D6
#define TFT_RST D3
#define TFT_SD D7
#define TFT_BL D13
DFRobot_ILI9488_320x480_HW_SPI screen(TFT_DC, TFT_CS, TFT_RST, TFT_BL);
DFRobot_Touch_GT911 touch;
DFRobot_UI ui(&screen, &touch);
// Placeholder color (light gray)
#define CLR_PLACEHOLDER COLOR_RGB565_LGRAY
// Wi-Fi and language configuration
char ssid[64] = "";
char password[64] = "";
char lang[4] = "en";
// Day names in French and English
const char* dayNames_fr[] = {
"DIMANCHE","LUNDI","MARDI","MERCREDI","JEUDI","VENDREDI","SAMEDI"
};
const char* dayNames_en[] = {
"SUNDAY","MONDAY","TUESDAY","WEDNESDAY","THURSDAY","FRIDAY","SATURDAY"
};
// Layout constants
const int padH = 15;
const int padV = 13;
const int iconSize = 48;
const int iconSpacing = 6;
const int box1Size = 60;
const int box2Size = 138;
const int boxSpacing = 18;
const int radius = 12;
// Draw a small icon with a rounded border
void drawIconBox(int x, int y, const unsigned char* icon, uint16_t color) {
screen.drawRoundRect(x, y, box1Size, box1Size, radius, color);
screen.drawBitmap(x + iconSpacing, y + iconSpacing,
icon, iconSize, iconSize, color);
}
// Draw a larger “language” box with label
void drawLangBox(int x, int y, const unsigned char* icon,
const char* label, uint16_t color) {
screen.drawRoundRect(x, y, box2Size, box1Size, radius, color);
screen.drawBitmap(x + iconSpacing, y + iconSpacing,
icon, iconSize, iconSize, color);
screen.setTextColor(color);
screen.setTextSize(3);
screen.setCursor(x + box1Size + iconSpacing, y + 18);
screen.print(label);
}
void setup() {
Serial.begin(115200);
delay(500);
ui.begin();
// 1) Initialize display
screen.setRotation(1);
screen.fillScreen(COLOR_RGB565_BLACK);
// 2) Initialize SPI for SD card and then Wi-Fi and NTP
SPI.begin(18, 19, 23, TFT_SD);
// Placeholder: draw all status icons in gray
int x0 = padH;
int y0 = padV + box1Size + boxSpacing;
drawIconBox(x0 + 0*(box1Size+boxSpacing), y0, icon_sd_nok, CLR_PLACEHOLDER);
drawIconBox(x0 + 1*(box1Size+boxSpacing), y0, icon_file_nok, CLR_PLACEHOLDER);
drawLangBox(x0 + 2*(box1Size+boxSpacing), y0, icon_lang, " ", CLR_PLACEHOLDER);
drawIconBox(x0 + 4*(box1Size+boxSpacing), y0, icon_wifi_off, CLR_PLACEHOLDER);
// 3) Check SD card
delay(500);
bool sdOk = SD.begin(TFT_SD);
uint16_t sdColor = sdOk ? COLOR_RGB565_GREEN : COLOR_RGB565_RED;
// Clear area before redrawing
screen.fillRect(x0 + 0*(box1Size+boxSpacing),
y0,
box1Size,
box1Size,
COLOR_RGB565_BLACK);
drawIconBox(x0 + 0*(box1Size+boxSpacing), y0,
sdOk ? icon_sd_ok : icon_sd_nok,
sdColor);
// 4) Check setup.txt on SD
bool fileOk = false;
if (sdOk) {
File f = SD.open("/setup.txt");
if (f) {
fileOk = true;
while (f.available()) {
String L = f.readStringUntil('\n');
L.trim();
if (L.startsWith("SSID=")) strncpy(ssid, L.c_str()+5, sizeof(ssid)-1);
if (L.startsWith("PASS=")) strncpy(password, L.c_str()+5, sizeof(password)-1);
if (L.startsWith("LANG=")) strncpy(lang, L.c_str()+5, sizeof(lang)-1);
}
f.close();
}
}
uint16_t fileColor = fileOk ? COLOR_RGB565_GREEN : COLOR_RGB565_RED;
screen.fillRect(x0 + 1*(box1Size+boxSpacing),
y0,
box1Size,
box1Size,
COLOR_RGB565_BLACK);
drawIconBox(x0 + 1*(box1Size+boxSpacing), y0,
fileOk ? icon_file_ok : icon_file_nok,
fileColor);
// 5) Display language status
delay(500);
bool validLang = (strcmp(lang,"fr")==0)||(strcmp(lang,"en")==0);
char langLabel[3] = {0};
if (validLang) strcpy(langLabel, strcmp(lang,"fr")==0?"FR":"EN");
else strncpy(langLabel, lang, 2);
uint16_t langColor;
if (!fileOk) langColor = COLOR_RGB565_ORANGE; // default if no file
else if (validLang) langColor = COLOR_RGB565_GREEN;
else langColor = COLOR_RGB565_RED;
screen.fillRect(x0 + 2*(box1Size+boxSpacing),
y0,
box2Size,
box1Size,
COLOR_RGB565_BLACK);
drawLangBox(x0 + 2*(box1Size+boxSpacing), y0,
icon_lang, langLabel, langColor);
// 6) Wi-Fi connection attempt
delay(500);
WiFi.begin(ssid, password);
unsigned long t0 = millis();
while (WiFi.status()!=WL_CONNECTED && millis()-t0<10000) {
delay(200);
}
bool wifiOk = (WiFi.status()==WL_CONNECTED);
uint16_t wifiColor = wifiOk ? COLOR_RGB565_GREEN : COLOR_RGB565_RED;
screen.fillRect(x0 + 4*(box1Size+boxSpacing),
y0,
box1Size,
box1Size,
COLOR_RGB565_BLACK);
drawIconBox(x0 + 4*(box1Size+boxSpacing), y0,
wifiOk ? icon_wifi_on : icon_wifi_off,
wifiColor);
// 7) Configure NTP so getLocalTime() will work
configTzTime("CET-1CEST,M3.5.0/2,M10.5.0/3", "pool.ntp.org");
// 8) Draw Help / Refresh / Check icons (temporary buttons)
drawIconBox(405, padH, icon_help, COLOR_RGB565_BLUE);
drawIconBox(405 - (18 + 60), 247, icon_refresh, COLOR_RGB565_ORANGE);
drawIconBox(405, 247, icon_check, COLOR_RGB565_DGREEN);
}
void loop() {
ui.refresh(); // handle UI touch callbacks (if any)
// Update date/time once per minute
static char lastDate[32] = "";
static char lastTime[6] = "";
static unsigned long lastCheck = 0;
if (millis() - lastCheck < 1000) return;
lastCheck = millis();
struct tm ti;
if (!getLocalTime(&ti)) return;
// Format date string and time string
char d[32], t[6];
const char** dn = (strcmp(lang,"fr")==0) ? dayNames_fr : dayNames_en;
snprintf(d, sizeof(d),
"%s %02d.%02d.%04d",
dn[ti.tm_wday],
ti.tm_mday,
ti.tm_mon + 1,
ti.tm_year + 1900);
snprintf(t, sizeof(t),
"%02d:%02d",
ti.tm_hour,
ti.tm_min);
// Redraw if changed
if (strcmp(d, lastDate) || strcmp(t, lastTime)) {
strcpy(lastDate, d);
strcpy(lastTime, t);
screen.fillRect(15, 180, 300, 70, COLOR_RGB565_BLACK);
screen.setTextColor(COLOR_RGB565_WHITE);
screen.setTextSize(3);
screen.setCursor(15, 180);
screen.print(d);
screen.setCursor(15, 210);
screen.print(t);
}
}
I add the first button:
#include "WiFi.h"
#include "SD.h"
#include "SPI.h"
#include "DFRobot_UI.h"
#include "DFRobot_GDL.h"
#include "DFRobot_Touch.h"
#include "time.h"
#include "icon.h"
#define TFT_DC D2
#define TFT_CS D6
#define TFT_RST D3
#define TFT_SD D7
#define TFT_BL D13
DFRobot_ILI9488_320x480_HW_SPI screen(TFT_DC, TFT_CS, TFT_RST, TFT_BL);
DFRobot_Touch_GT911 touch;
DFRobot_UI ui(&screen, &touch);
// Placeholder color (light gray)
#define CLR_PLACEHOLDER COLOR_RGB565_LGRAY
// Wi-Fi and language configuration
char ssid[64] = "";
char password[64] = "";
char lang[4] = "en";
// Day names in French and English
const char* dayNames_fr[] = {
"DIMANCHE","LUNDI","MARDI","MERCREDI","JEUDI","VENDREDI","SAMEDI"
};
const char* dayNames_en[] = {
"SUNDAY","MONDAY","TUESDAY","WEDNESDAY","THURSDAY","FRIDAY","SATURDAY"
};
// Layout constants
const int padH = 15;
const int padV = 13;
const int iconSize = 48;
const int iconSpacing = 6;
const int box1Size = 60;
const int box2Size = 138;
const int boxSpacing = 18;
const int radius = 12;
// Draw a small icon with a rounded border
void drawIconBox(int x, int y, const unsigned char* icon, uint16_t color) {
screen.drawRoundRect(x, y, box1Size, box1Size, radius, color);
screen.drawBitmap(x + iconSpacing, y + iconSpacing,
icon, iconSize, iconSize, color);
}
// Draw a larger “language” box with label
void drawLangBox(int x, int y, const unsigned char* icon,
const char* label, uint16_t color) {
screen.drawRoundRect(x, y, box2Size, box1Size, radius, color);
screen.drawBitmap(x + iconSpacing, y + iconSpacing,
icon, iconSize, iconSize, color);
screen.setTextColor(color);
screen.setTextSize(3);
screen.setCursor(x + box1Size + iconSpacing, y + 18);
screen.print(label);
}
//Callback function for three buttons
void btnCallback(DFRobot_UI::sButton_t &btn,DFRobot_UI::sTextBox_t &obj) {
/* String text((char *)btn.text);
if(text == "ON"){
obj.setText("you have touch button on");
}
else if(text == "OFF"){
obj.setText("you have touch button off");
}
else if(text == "clr"){
obj.deleteChar();
}*/
}
void setup() {
Serial.begin(115200);
delay(500);
ui.begin();
//ui.setTheme(DFRobot_UI::MODERN);
// 1) Initialize display
screen.setRotation(1);
screen.fillScreen(COLOR_RGB565_BLACK);
// 2) Initialize SPI for SD card and then Wi-Fi and NTP
SPI.begin(18, 19, 23, TFT_SD);
// Placeholder: draw all status icons in gray
int x0 = padH;
int y0 = padV + box1Size + boxSpacing;
drawIconBox(x0 + 0*(box1Size+boxSpacing), y0, icon_sd_nok, CLR_PLACEHOLDER);
drawIconBox(x0 + 1*(box1Size+boxSpacing), y0, icon_file_nok, CLR_PLACEHOLDER);
drawLangBox(x0 + 2*(box1Size+boxSpacing), y0, icon_lang, " ", CLR_PLACEHOLDER);
drawIconBox(x0 + 4*(box1Size+boxSpacing), y0, icon_wifi_off, CLR_PLACEHOLDER);
// 3) Check SD card
delay(500);
bool sdOk = SD.begin(TFT_SD);
uint16_t sdColor = sdOk ? COLOR_RGB565_GREEN : COLOR_RGB565_RED;
// Clear area before redrawing
screen.fillRect(x0 + 0*(box1Size+boxSpacing),
y0,
box1Size,
box1Size,
COLOR_RGB565_BLACK);
drawIconBox(x0 + 0*(box1Size+boxSpacing), y0,
sdOk ? icon_sd_ok : icon_sd_nok,
sdColor);
// 4) Check setup.txt on SD
bool fileOk = false;
if (sdOk) {
File f = SD.open("/setup.txt");
if (f) {
fileOk = true;
while (f.available()) {
String L = f.readStringUntil('\n');
L.trim();
if (L.startsWith("SSID=")) strncpy(ssid, L.c_str()+5, sizeof(ssid)-1);
if (L.startsWith("PASS=")) strncpy(password, L.c_str()+5, sizeof(password)-1);
if (L.startsWith("LANG=")) strncpy(lang, L.c_str()+5, sizeof(lang)-1);
}
f.close();
}
}
uint16_t fileColor = fileOk ? COLOR_RGB565_GREEN : COLOR_RGB565_RED;
screen.fillRect(x0 + 1*(box1Size+boxSpacing),
y0,
box1Size,
box1Size,
COLOR_RGB565_BLACK);
drawIconBox(x0 + 1*(box1Size+boxSpacing), y0,
fileOk ? icon_file_ok : icon_file_nok,
fileColor);
// 5) Display language status
delay(500);
bool validLang = (strcmp(lang,"fr")==0)||(strcmp(lang,"en")==0);
char langLabel[3] = {0};
if (validLang) strcpy(langLabel, strcmp(lang,"fr")==0?"FR":"EN");
else strncpy(langLabel, lang, 2);
uint16_t langColor;
if (!fileOk) langColor = COLOR_RGB565_ORANGE; // default if no file
else if (validLang) langColor = COLOR_RGB565_GREEN;
else langColor = COLOR_RGB565_RED;
screen.fillRect(x0 + 2*(box1Size+boxSpacing),
y0,
box2Size,
box1Size,
COLOR_RGB565_BLACK);
drawLangBox(x0 + 2*(box1Size+boxSpacing), y0,
icon_lang, langLabel, langColor);
// 6) Wi-Fi connection attempt
delay(500);
WiFi.begin(ssid, password);
unsigned long t0 = millis();
while (WiFi.status()!=WL_CONNECTED && millis()-t0<10000) {
delay(200);
}
bool wifiOk = (WiFi.status()==WL_CONNECTED);
uint16_t wifiColor = wifiOk ? COLOR_RGB565_GREEN : COLOR_RGB565_RED;
screen.fillRect(x0 + 4*(box1Size+boxSpacing),
y0,
box1Size,
box1Size,
COLOR_RGB565_BLACK);
drawIconBox(x0 + 4*(box1Size+boxSpacing), y0,
wifiOk ? icon_wifi_on : icon_wifi_off,
wifiColor);
// 7) Configure NTP so getLocalTime() will work
configTzTime("CET-1CEST,M3.5.0/2,M10.5.0/3", "pool.ntp.org");
// 8) Draw Help / Refresh / Check icons (temporary buttons)
//Create a button control on the screen
DFRobot_UI::sButton_t & btn1 = ui.creatButton();
//Set the name of the button
btn1.setText("HELP");
btn1.bgColor = COLOR_RGB565_BLUE;
btn1.setCallback(btnCallback);
// btn1.setOutput(&tb);
ui.draw(&btn1,405,padH,box1Size,box1Size);
//drawIconBox(405, padH, icon_help, COLOR_RGB565_BLUE);
drawIconBox(405 - (18 + 60), 247, icon_refresh, COLOR_RGB565_ORANGE);
drawIconBox(405, 247, icon_check, COLOR_RGB565_DGREEN);
}
void loop() {
ui.refresh(); // handle UI touch callbacks (if any)
// Update date/time once per minute
static char lastDate[32] = "";
static char lastTime[6] = "";
static unsigned long lastCheck = 0;
if (millis() - lastCheck < 1000) return;
lastCheck = millis();
struct tm ti;
if (!getLocalTime(&ti)) return;
// Format date string and time string
char d[32], t[6];
const char** dn = (strcmp(lang,"fr")==0) ? dayNames_fr : dayNames_en;
snprintf(d, sizeof(d),
"%s %02d.%02d.%04d",
dn[ti.tm_wday],
ti.tm_mday,
ti.tm_mon + 1,
ti.tm_year + 1900);
snprintf(t, sizeof(t),
"%02d:%02d",
ti.tm_hour,
ti.tm_min);
// Redraw if changed
if (strcmp(d, lastDate) || strcmp(t, lastTime)) {
strcpy(lastDate, d);
strcpy(lastTime, t);
screen.fillRect(15, 180, 300, 70, COLOR_RGB565_BLACK);
screen.setTextColor(COLOR_RGB565_WHITE);
screen.setTextSize(3);
screen.setCursor(15, 180);
screen.print(d);
screen.setCursor(15, 210);
screen.print(t);
}
}
The UI button drawing might set a font/color internally and not reset it. Always set your desired font and color after you draw buttons:
// After drawing buttons
screen.setTextColor(COLOR_RGB565_WHITE);
screen.setTextSize(3);
screen.setFont(&FreeSans9pt7b); // or whatever font you want

Thank you !
For now, I’ve placed the touchscreen on the side and I’m using an RGB button and an AD keyboard, and that gets the job done.