LVGL on Arduino Mega 2560

Description

Good Day at all. I’m trying to get LVGL to work on an Arduino Mega 2560 with a 3.2 ITDB02 shield. On an ESP8266 I managed to do this with another LDC display and the TFT_eSPI library. On the Mega where I use the UTFT library for the display, this doesn’t work.
The following error message appears:
libraries\URTouch/URTouch.h:64:3: error: ‘regtype’ does not name a type
regtype *P_CLK, *P_CS, *P_DIN, *P_DOUT, *P_IRQ;

libraries\URTouch/URTouch.h:65:3: error: ‘regsize’ does not name a type
regsize B_CLK, B_CS, B_DIN, B_DOUT, B_IRQ;

libraries\UTFT/UTFT.h:210:49: error: ‘bitmapdatatype’ has not been declared
void drawBitmap(int x, int y, int sx, int sy, bitmapdatatype data, int scale=1);

libraries\UTFT/UTFT.h:211:49: error: ‘bitmapdatatype’ has not been declared
void drawBitmap(int x, int y, int sx, int sy, bitmapdatatype data, int deg, int rox, int roy);

libraries\UTFT/UTFT.h:233:3: error: ‘regtype’ does not name a type
regtype *P_RS, *P_WR, *P_CS, *P_RST, *P_SDA, *P_SCL, *P_ALE;

libraries\UTFT/UTFT.h:234:3: error: ‘regsize’ does not name a type
regsize B_RS, B_WR, B_CS, B_RST, B_SDA, B_SCL, B_ALE;

Desktop\Test_Porting\Test_Porting.ino: In function ‘void ex_disp_flush(int32_t, int32_t, int32_t, int32_t, const lv_color_t*)’:
Test_Porting:27:18: error: ‘disp’ was not declared in this scope
lv_flush_ready(disp);

Test_Porting:27:22: error: ‘lv_flush_ready’ was not declared in this scope
lv_flush_ready(disp);

Desktop\Test_Porting\Test_Porting.ino: In function ‘void setup()’:
Test_Porting:62:23: error: ‘my_disp_flush’ was not declared in this scope
disp_drv.flush_cb = my_disp_flush;

I don’t know where that comes from.
The code works fine on the ESP8266 with other graphics libraries. Does anyone have experience with an Arduino Mega and LVGL?

Thanks in advance for answers.

best regards
David

What MCU/Processor/Board and compiler are you using?

Arduino Mega 2560 with Arduino IDE

What LVGL version are you using?

V7 latest

What do you want to achieve?

Get the LVGL running on the Arduino Mega 2560 and the 3.2 ITDB02 shield

What have you tried so far?

Description

Code to reproduce

Add a code snippet which can run in the simulator. It should contain only the relevant code that compiles without errors when separated from your main code base.

The code block(s) should be formatted like:

#include <URTouch.h>
#include <URTouchCD.h>
#include <memorysaver.h>
#include <UTFT.h>
#include <lvgl.h>


static lv_disp_buf_t disp_buf;
static lv_color_t buf[LV_HOR_RES_MAX * 10];
UTFT myGLCD(ITDB32S, 38, 39, 40, 41);
URTouch  myTouch( 6, 5, 4, 3, 2);


static void ex_disp_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const lv_color_t * color_p) 
{

  int32_t x;
  int32_t y;
  for (y = y1; y <= y2; y++) {
    for (x = x1; x <= x2; x++)
    {
      LCD_WritePixel(x, y, color_p->full);
      color_p++;
    }
  }

  lv_flush_ready(disp);
}


void timer_1(void)
{
  if (millis() % 1000 > 1)
  {
    lv_tick_inc(1);
  }
}

void LCD_WritePixel(int x, int y, int color)
{
  myGLCD.setColor(color);
  myGLCD.drawPixel(x, y);
}





void setup() 
{
  
  myGLCD.InitLCD();
  myGLCD.clrScr();

  lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10);

  /*Initialize the display*/
  lv_disp_drv_t disp_drv;
  lv_disp_drv_init(&disp_drv);
  disp_drv.hor_res = 320;
  disp_drv.ver_res = 240;
  disp_drv.flush_cb = my_disp_flush;
  disp_drv.buffer = &disp_buf;
  lv_disp_drv_register(&disp_drv); /*Register the driver and save the created display objects*/
}

void loop()
{
  timer_1();

  //No Realtime
  if (millis() % 1000 > 5)
  {
    lv_task_handler();
  }
}

Screenshot and/or video

Hi,
the code given is a mess :frowning:
ex_disp_flush() defined, but my_disp_flush used, lv_flush_ready wrongly used. Correct these fatal errors first and at least try to get the sketch compilable without all lvgl stuff…
EDIT: Also your millis() % XXX > YYY is wrong IMO if you try to call lv_tick_inc once per second and lv_task_handler once per 5ms.

Hello Pablo2048. Thank you first for your quick answer. You’re right. So many careless mistakes. I am absolutely not a professional in this area. I’ve corrected it as far as I understand. However, I still get an error message that I cannot fix. This is as follows:

Desktop\Porting_for_Arduino\Porting_for_Arduino.ino: In function ‘void my_flush_cb(lv_disp_drv_t*, const lv_area_t*, lv_color_t*)’:
Porting_for_Arduino:63:23: error: ‘disp’ was not declared in this scope
lv_disp_flush_ready(disp);

Desktop\Porting_for_Arduino\Porting_for_Arduino.ino: In function ‘void my_flush_cb(lv_disp_drv_t*, const lv_area_t*, lv_color_t*)’:
Porting_for_Arduino:63:23: error: ‘disp’ was not declared in this scope
lv_disp_flush_ready(disp);

The Code:

#include <lvgl.h>
#include "Arduino.h"
#include <URTouch.h>
#include <URTouchCD.h>
#include <UTFT.h>


static lv_disp_buf_t disp_buf;
static lv_color_t buf[LV_HOR_RES_MAX * 10];

UTFT myGLCD(ITDB32S, 38, 39, 40, 41);
URTouch  myTouch( 6, 5, 4, 3, 2);
int x;
int y;
int state = 0;


void timer_1(void)
{
  if (millis() % 5 > 1) //Every 5 ms
  {
    lv_tick_inc(1);
  }
}

void LCD_WritePixel(int x, int y, int color)
{
  myGLCD.setColor(color);
  myGLCD.drawPixel(x, y);
}


void setup()
{
  Serial.begin(9600);
  myGLCD.InitLCD();

  lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10);

  lv_disp_drv_t disp_drv;
  lv_disp_drv_init(&disp_drv);
  disp_drv.hor_res = 320;
  disp_drv.ver_res = 240;
  disp_drv.buffer = &disp_buf;
  disp_drv.flush_cb = my_flush_cb;
  lv_disp_t * disp;
  lv_disp_drv_register(&disp_drv); /*Register the driver and save the created display objects*/
}

void my_flush_cb(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
  /*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/
  int32_t x, y;
  for (y = area->y1; y <= area->y2; y++) {
    for (x = area->x1; x <= area->x2; x++) {
      LCD_WritePixel(x,  y, color_p->full);
      color_p++;
    }
  }

  /* IMPORTANT!!!
     Inform the graphics library that you are ready with the flushing*/
  lv_disp_flush_ready(disp);
}

void loop()
{
  timer_1();


  if (millis() % 5 > 1)
  {
    lv_task_handler();
  }
}

Change it to lv_disp_flush_ready(disp_drv).

Hello Embedded. Many thanks. The code is now compiled. But the IDE now tells me that 22813 bytes of global variables are used and that 278% are too many.
The Arduino Mega have 8 KB SRAM and 4KB EEPROM. Is that not enough?

best regards
David

That’s… very small. Our official minimum requirement is 16KB and that is for a very stripped down UI with a few widgets. If the 4KB of EEPROM is the only code space you have, I don’t think it is possible to fit LVGL into this platform. You would want a device with 64KB of Flash at least and I would go with 128-256 KB.

I think I looked wrong There are 256 kb flash memory, of which 8 kb is for the bootloader. Also 8 kb SRAM and 4 kb EEPROM. It would be a real shame if this beautiful library couldn’t be used.

best regards
David

Okay, with 256KB of flash memory that part wouldn’t be a problem. 8KB of SRAM is still a tight squeeze but let’s see what we can do.

You’re going to want to start by disabling most of the features in lv_conf.h so that the library is as small as possible to start with. In particular you need to reduce this value. I would recommend starting with 2KB and increasing it as you need.

See after that if the IDE is still complaining.

That is another problem. At the beginning I set the value to 2KB. As always with the ESP32 as well as with the Arduino Mega, error message belongs:

Arduino\libraries\lvgl-master\src\lv_misc\lv_mem.c:122:33: error: size of array ‘work_mem_int’ is too large
static LV_MEM_ATTR MEM_UNIT work_mem_int[LV_MEM_SIZE / sizeof(MEM_UNIT)];

I got around the problem by entering the array static LV_MEM_ATTR MEM_UNIT work_mem_int [LV_MEM_SIZE / sizeof (MEM_UNIT)] in the lv_mem.c file; simply entered 2000 blindly. The code was then compilable. If I bring this back to the old state, the code can no longer be compiled.

best regards
David

That’s strange. I would expect 2000 to be a larger number, because then you are asking for 2000 4-byte integers.

With LV_MEM_SIZE = (2 * 1024), that would be 2048, divided by sizeof(MEM_UNIT) which should be 4, giving you a total of 512 4-byte integers (smaller than the original 2000 you provided).

Was that the value you used for LV_MEM_SIZE? If so something strange has happened to the macro logic.

Yes, I used # define LV_MEM_SIZE (2U * 1024U) and got this error message. But also with the esp32 which has a lot more memory.

best regards
David

I believe you, but the compiler’s behavior doesn’t make sense. For testing what happens if you manually enter 512 as the array size? Or, is it possible that you have more than one lv_conf.h file and you’re changing the wrong one?

I don’t know why but I need the lv_config.h file 3 times. I have deactivated the widgets in all files that I don’t need. Now I come to 33% for the program storage space. I put in the array static LV_MEM_ATTR MEM_UNIT work_mem_int [LV_MEM_SIZE / sizeof (MEM_UNIT)]; manually entered 512. But the error remains the same and the size of the global variable remains unchanged at 21851 bytes, i.e. 266% of the dynamic memory.

best regards
David

So work_mem_int compiles fine if you manually enter 2000 but has an error when you manually enter 512?

Alternatively, do you or @Pablo2048 happen to know whether Arduino ships with a built-in heap? If so you should configure LVGL to use that - it would save some memory.

Another thing you will need to do is reduce your buffer size (buf) to LV_HOR_RES_MAX (make sure to change the array size as well as the value passed to lv_disp_buf_init). I looked up your display and it is 320 pixels wide, so your current buffer is taking up 6.4 kilobytes. With just one row instead of 10 it will take up 640 bytes, which is still a lot, but is the best you can do. I’m pretty sure LVGL cannot handle buffers smaller than one display row.

With an array width of 2000kb, the same error of 266% is too much. Okay where can I change that there are only one row and no longer 10?

best regards
David

It is compiled at 2000kb and 512kb. With both, however, the message comes with the 266% global memory.

best regards
David

There is standard GCC heap allocator in the Arduino framework AFAIK, but the CPU has only 8kB of RAM so I don’t think that LVGL fits…

@kisvegabor Do you have any suggestions about how to fit LVGL into this platform? I know the official statistic says 8KB, but by the time one allocates a 2KB stack, 2KB of heap, and another 1KB for a display buffer, there is a minimal amount of RAM left for the application. Perhaps this statistic was measured using 6.1 and needs to be updated?

Either way, it would be awesome to find a way to make it work on the Mega. Tomorrow I will see if there is a way to expand the Ram of the Mega by code.

Best regards
David

It’s useless I think, because even if it will fit, it will be very slow and very limited. Anyway if you want to continue, the best way to do is:

  1. make the screen working only with UTFT (just the initialization of the LCD) and check, how much RAM is consumed (make screenshot of compilation result).
  2. add the LVGL code and check, how much RAM is consumed now (make screenshot of compilation result)
  3. put those results (please make screenshots of compiler output - not just write some numbers), current sketch and your lv_conf.h file here so someone can reproduce it.