Description
I am working with an ESP32, Adafruit Feather V2 and a waveshare7.5in V2 B/W display. I’m currently trying to get started with LVGL by running a simple program that would display a short text segment in the center of my display. I am running into an issue where my DRAM segment data doesn’t fit, overflowing by ~10944 bytes.
What MCU/Processor/Board and compiler are you using?
ESP32 - Adafruit Feather V2
Arduino IDE
What do you want to achieve?
Draw a line of text in the center of my display
What have you tried so far?
I have tried messing with the memory allocated to LVGL through my lv_conf file, I am currently at 64*1024
#define LV_MEM_SIZE (64 * 1024)
I have also tried disabling some widgets to reduce memory usage, but I found that I was not able to disable a few that I wasn’t using → e.g., dropdown and textarea
Code to reproduce
Add the relevant code snippets here.
Here is my lv_conf.h file – I havev this located in the same folder as my .ino file
#if 1 /*Set it to "1" to enable content*/
#ifndef LV_CONF_H
#define LV_CONF_H
// #include <stdint.h>
// enum {
// LV_COLOR_FORMAT_L1 = 0, // 1-bit per pixel (monochrome)
// // Add other formats as needed
// } lv_color_format_t;
#define LV_HOR_RES_MAX 800
#define LV_VER_RES_MAX 480
// #include <stdint.h>
/*====================
COLOR SETTINGS
*====================*/
#define LV_COLOR_DEPTH 1
#define LV_COLOR_16_SWAP 0
#define LV_COLOR_SCREEN_TRANSP 0
/*=========================
MEMORY SETTINGS
*=========================*/
#define LV_MEM_CUSTOM 1
#if LV_MEM_CUSTOM == 0
#define LV_MEM_SIZE (64 * 1024)
// #define LV_MEM_SIZE (32U * 1024U)
#else
#define LV_MEM_CUSTOM_INCLUDE <stdlib.h>
#define LV_MEM_CUSTOM_ALLOC malloc
#define LV_MEM_CUSTOM_FREE free
#endif
/*====================
HAL SETTINGS
*====================*/
#define LV_TICK_CUSTOM 1
#if LV_TICK_CUSTOM == 1
#define LV_TICK_CUSTOM_INCLUDE "Arduino.h"
#define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis())
#endif
/*=======================
* FEATURE CONFIGURATION
*=======================*/
/*1: Enable the Animations */
#define LV_USE_ANIMATION 0
/*1: Enable shadow drawing*/
#define LV_USE_SHADOW 0
/*1: Enable object groups (for keyboard/encoder navigation) */
#define LV_USE_GROUP 1
/*1: Enable GPU interface*/
#define LV_USE_GPU 0
/*1: Enable file system (might be required for images */
#define LV_USE_FILESYSTEM 0
/*1: Enable drawing complex multi-line TrueType based fonts */
#define LV_USE_FREETYPE 0
/*=====================
* COMPILER SETTINGS
*====================*/
/*For big endian systems set to 1*/
#define LV_BIG_ENDIAN_SYSTEM 0
/*=====================
* WIDGET USAGE
*====================*/
#define LV_USE_ARC 1
// Required? ^
#define LV_USE_BAR 0
#define LV_USE_BTN 0
#define LV_USE_BTNMATRIX 0
#define LV_USE_CANVAS 0
#define LV_USE_CHECKBOX 0
#define LV_USE_DROPDOWN 1
// Required? ^
#define LV_USE_IMG 1
#define LV_USE_LABEL 1
#define LV_USE_LINE 1
#define LV_USE_ROLLER 0
#define LV_USE_SLIDER 0
#define LV_USE_SWITCH 0
#define LV_USE_TEXTAREA 1
// Required? ^
#define LV_USE_TABLE 0
And my main .ino file in case it is needed
#include <GxEPD2_BW.h>
#include <lvgl.h>
#include <Fonts/FreeMonoBold12pt7b.h>
// Pin Definitions
#define EPD_BUSY 33
#define EPD_RST 27
#define EPD_DC 13
#define EPD_CS 12
#define EPD_SCK 5
#define EPD_MOSI 19
#define EPD_PWR 15
// Initialize display object
GxEPD2_BW<GxEPD2_750_T7, GxEPD2_750_T7::HEIGHT> display(GxEPD2_750_T7(EPD_CS, EPD_DC, EPD_RST, EPD_BUSY));
// Display dimensions
#define DISPLAY_WIDTH 800
#define DISPLAY_HEIGHT 480
// LVGL specific variables
static lv_display_t* disp;
static uint8_t* draw_buf;
// Global label for easy access
static lv_obj_t* infoLabel;
// LVGL display flush function
void my_display_flush(lv_display_t* disp, const lv_area_t* area, uint8_t* color_p) {
uint32_t w = lv_area_get_width(area);
uint32_t h = lv_area_get_height(area);
// Set partial window for update
display.setPartialWindow(area->x1, area->y1, w, h);
// Convert LVGL buffer to e-paper display
for (uint16_t y = 0; y < h; y++) {
for (uint16_t x = 0; x < w; x++) {
// Calculate byte and bit position in the 1-bit buffer
size_t byte_index = (y * w + x) / 8;
uint8_t bit_mask = 1 << (x % 8);
// Check if the pixel is black
bool isBlack = (color_p[byte_index] & bit_mask) != 0;
// Draw pixel on e-paper display
display.drawPixel(area->x1 + x, area->y1 + y, isBlack ? GxEPD_BLACK : GxEPD_WHITE);
}
}
// Update display
display.display();
// Notify LVGL that flush is complete
lv_display_flush_ready(disp);
}
void setup() {
Serial.begin(115200);
// Initialize e-paper display pins and power
pinMode(EPD_BUSY, INPUT);
pinMode(EPD_RST, OUTPUT);
pinMode(EPD_DC, OUTPUT);
pinMode(EPD_CS, OUTPUT);
pinMode(EPD_PWR, OUTPUT);
digitalWrite(EPD_PWR, HIGH);
digitalWrite(EPD_CS, HIGH);
// Initialize SPI and display
SPI.begin();
display.init(115200);
// LVGL Initialization
lv_init();
// Alternative buffer allocation method
static uint8_t* draw_buf;
size_t buf_size = (DISPLAY_WIDTH * DISPLAY_HEIGHT) / 8; // 1-bit per pixel
draw_buf = (uint8_t*)malloc(buf_size);
// Create display
disp = lv_display_create(DISPLAY_WIDTH, DISPLAY_HEIGHT);
// Set display callbacks and properties
lv_display_set_flush_cb(disp, my_display_flush);
lv_display_set_color_format(disp, LV_COLOR_FORMAT_I1); // Use LV_COLOR_FORMAT_I1 for monochromatic displays
lv_display_set_buffers(disp, draw_buf, NULL, buf_size, LV_DISPLAY_RENDER_MODE_PARTIAL);
// Create label in bottom right corner
lv_obj_t* screen = lv_screen_active();
infoLabel = lv_label_create(screen);
lv_obj_set_pos(infoLabel, DISPLAY_WIDTH - 250, DISPLAY_HEIGHT - 50);
lv_label_set_text(infoLabel, "Hello E-Paper!");
// Optional: Set text style
lv_obj_set_style_text_color(infoLabel, lv_color_black(), LV_PART_MAIN);
}
// Function to update label text
void updateLabelText(const char* newText) {
lv_label_set_text(infoLabel, newText);
// Force a redraw
lv_display_send_event(disp, LV_EVENT_DRAW_MAIN, NULL);
}
void loop() {
// Example of periodic label update
static unsigned long lastUpdate = 0;
if (millis() - lastUpdate > 5000) { // Every 5 seconds
String timeStr = "Time: " + String(millis() / 1000) + " sec";
updateLabelText(timeStr.c_str());
lastUpdate = millis();
}
// Process LVGL tasks
lv_timer_handler();
}