How to run LVGL on M5Stack
-
I found something interesting:
rst:0xc (SW_CPU_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0018,len:4 load:0x3fff001c,len:1044 load:0x40078000,len:10124 load:0x40080400,len:5856 entry 0x400806a8 Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled. Core 0 register dump: PC : 0x400d864f PS : 0x00060b30 A0 : 0x800d7c45 A1 : 0x3ffe3a10 A2 : 0x00000000 A3 : 0x3ffba588 A4 : 0x00000120 A5 : 0x00003400 A6 : 0xffffffff A7 : 0x00000000 A8 : 0x3ffcfdcc A9 : 0x00000020 A10 : 0x00000000 A11 : 0x40086244 A12 : 0x00000000 A13 : 0x00000120 A14 : 0x00000001 A15 : 0x00000120 SAR : 0x00000011 EXCCAUSE: 0x0000001c EXCVADDR: 0x00000022 LBEG : 0x400888a4 LEND : 0x400888c0 LCOUNT : 0xffffffff ELF file SHA256: 0000000000000000 Backtrace: 0x400d864f:0x3ffe3a10 0x400d7c42:0x3ffe3a30 0x400f2833:0x3ffe3a50 0x400d1585:0x3ffe3a70 0x400d15fe:0x3ffe3a90 0x400d1b9d:0x3ffe3ab0 0x4010a0ef:0x3ffe3bb0 0x40082c8d:0x3ffe3bd0 0x40082eb4:0x3ffe3c20 0x40079247:0x3ffe3c40 0x400792ad:0x3ffe3c70 0x400792b8:0x3ffe3ca0 0x40079465:0x3ffe3cc0 0x400806da:0x3ffe3df0 0x40007c15:0x3ffe3eb0 0x4000073d:0x3ffe3f20 Rebooting...
I think, I've a lot of things to learn about Cpp and its ecosystem before continue ^^'
-
Honestly I started off reading the LVGL online help and even though I am still learning I did not have much problem making the lib work on the Core2.
However I spent some significant time before understanding the whole concept (probably because I am getting too old :) ) and you seem to be way more experienced than me so you will make it work quickly :)My GitHub project is private (because it might end up being commercially used) but if you want I can extract the minimum code I used to display something if it can help and make it public.
By looking at the error (If I remember I got more or less the same) this looks like invalide pointer / memory allocation.
I realized that just initializing everything for LVGL to work is a real pain (when you've never played with it) but after you've understood the basic concepts it comes much clearer.
At this stage all basic things are working fine I am now moving on to Event management (button press, sliders move etc...).Btw you can also have a look at the EdgeLine application which is a kind of LVGL companion allowing you to WYSIWYG to C/Python code automatically for you. I am very bad at designing UIs so I am starting using it for my project and it can also help you understand the code which is generated.
-
Haha, thank you, but I started learning C/C++ this Monday 👀
I'll try to investigate more about pointers /memory exceptions.
Everything I'll do will be on my GitHub in public repositories, my aim is to create a Tamagotchi for my daughter ^^' -
FYI, I correctly display a button, I have many things left to do next, like finding the reason why my DrawingBoard.cpp pointers are badly set, but in the end, you help me a lot!
Thanks again!For people reading this, I'll do my best to improve my GitHub repository in order to have a simple example for M5Core, explaining which parameters must be configured in lv_conf.h :)
-
Hi Pierre,
Sorry I don't feel I did much for you but my (real) work is really taking much of my time (even what is supposed to be my free time) and I wish I could have spent more time working this out with you.
In any case my offer still stands, I can help you building up a simple template with comments for people to get started.
I already spent much time on it and I believe I have understood all the basic concepts .
As already said, now i need to go one step further with event management.
Also I am quite used to code in C (this is the language I started with a loooong time ago) I am not an expert but at least I can understand the most of what I do :)
Btw a good platform that I have adopted now since several months is VSCode + PIO...Very neat combination! -
I will omit the details,
Currently, M5Stack Core2 is working with LVGL v8.1.0 and Arduino IDE.About lv_conf.h
The following three settings are required.lvgl-master v8.1.0 / src / lv_conf.h
-
/* clang-format off */
#if 1 /Set it to "1" to enable content/ -
#define LV_COLOR_DEPTH 16
-
#define LV_TICK_CUSTOM 1
#if LV_TICK_CUSTOM
#define LV_TICK_CUSTOM_INCLUDE "Arduino.h"
-
-
Thank you @macsbug , this is exactly what I add to edit in my lv_conf.h in order to make it works!
https://github.com/PierreRambaud/drawing-board/blob/master/drawing-board.ino#L4@erich I updated my repository, it now works, but not as expected. I've two issues:
- I'm not able to change the label text each time I press a button (the reason of the seg fault)
- I'm not able to draw on the right side like the lvgl take the wrong space, or the tft I don't know yet which one ^^'
After that, everything will be ok (at least for this first project)
As you said, a good platform for development is the key, I work with emacs for years, but I never configured it for C language.
I've Arduino software open beside, only to compile & transfer. -
Thank you @GoT , This is a great program.
Thank you for publishing to github.problem
- not able to change the label text.
- The right side cannot be drawn.
Change DrawingBoard.cpp.
static lv_style_t style_color_label;
static lv_style_t style_size_label;
static lv_style_t style_clear_label;
static lv_style_t style_label;void DrawingBoard::setup() {
//lv_obj_t* _size_label = lv_label_create(lv_scr_act());
_size_label = lv_label_create(lv_scr_act());//lv_obj_add_style(_size_label, &style_label, 0);
lv_obj_add_style(_size_label, &style_size_label, 0);//lv_obj_add_style(_clear_label, &style_label, 0);
lv_obj_add_style(_clear_label, &style_clear_label, 0);void DrawingBoard::drawPoint(int32_t x, int32_t y) {
//_tft.drawCircle(x, y, _size, getColor());
//_tft.fillCircle(x, y, _size, getColor());
M5.Lcd.drawCircle(x, y, _size, getColor());
M5.Lcd.fillCircle(x, y, _size, getColor());void DrawingBoard::changeSize() {
//lv_label_set_text_fmt(_size_label, "Size: %d", _size);
lv_label_set_text_fmt(_size_label, "Size: %d", _size);void DrawingBoard::clear() {
//_tft.fillScreen(TFT_BLACK);
M5.Lcd.fillScreen(TFT_WHITE);postscript:
All 'tft's are possible with 'M5.Lcd'.
It is possible with M5.Lcd without using TFT_eSPI.
Development environment: LVGL 8.1.0 + Arduino IDE 1.8.19 -
@macsbug you're right, I did mention using TFT_eSPI instead of M5.Lcd only for portability reason.
I would like to create a set of sample files that I can use with any display and not only with M5Stack devices. -
OMG, it works as expected! <3
If both of you have GitHub account, I'd be glad to add you as credit for the awesome help! -
Great, I'm glad it works for you!
I don't feel I did much to help but anyways here is my GH account: https://github.com/erich74
At the moment I juste have a couple of private reps but I am planning to add public stuff when I get more used to M5Stack devices as this is becoming my main development/iot device platform.
I will come back to this thread as I will probably need some help when I progress with my current project ;) -
@erich you did more than you think.
Feel free to ask when you will need it, if the M5Core2 is enough to run your program, I would be glad to help as you did -
@got thanks, I will for sure ;)
-
Here is what I came up with (and works with lvgl/lvgl 8.1 on my Core 2).
#include <M5Core2.h> #include <Arduino.h> #include <lvgl.h> #include <Wire.h> #include <SPI.h> // init the tft espi static lv_disp_draw_buf_t draw_buf; static lv_disp_drv_t disp_drv; // Descriptor of a display driver static lv_indev_drv_t indev_drv; // Descriptor of a touch driver M5Display *tft; static void ta_event_cb(lv_event_t * e); static lv_obj_t * kb; static void ta_event_cb(lv_event_t * e) { lv_event_code_t code = lv_event_get_code(e); lv_obj_t * ta = lv_event_get_target(e); if(code == LV_EVENT_CLICKED || code == LV_EVENT_FOCUSED) { /*Focus on the clicked text area*/ if(kb != NULL) lv_keyboard_set_textarea(kb, ta); } else if(code == LV_EVENT_READY) { LV_LOG_USER("Ready, current text: %s", lv_textarea_get_text(ta)); } } static void btnPowerOff_event(lv_event_t * event) { M5.Axp.PowerOff(); } void tft_lv_initialization() { M5.begin(); lv_init(); static lv_color_t buf1[(LV_HOR_RES_MAX * LV_VER_RES_MAX) / 10]; // Declare a buffer for 1/10 screen siz static lv_color_t buf2[(LV_HOR_RES_MAX * LV_VER_RES_MAX) / 10]; // second buffer is optionnal // Initialize `disp_buf` display buffer with the buffer(s). lv_disp_draw_buf_init(&draw_buf, buf1, buf2, (LV_HOR_RES_MAX * LV_VER_RES_MAX) / 10); tft = &M5.Lcd; } // Display flushing void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) { uint32_t w = (area->x2 - area->x1 + 1); uint32_t h = (area->y2 - area->y1 + 1); tft->startWrite(); tft->setAddrWindow(area->x1, area->y1, w, h); tft->pushColors((uint16_t *)&color_p->full, w * h, true); tft->endWrite(); lv_disp_flush_ready(disp); } void init_disp_driver() { lv_disp_drv_init(&disp_drv); // Basic initialization disp_drv.flush_cb = my_disp_flush; // Set your driver function disp_drv.draw_buf = &draw_buf; // Assign the buffer to the display disp_drv.hor_res = LV_HOR_RES_MAX; // Set the horizontal resolution of the display disp_drv.ver_res = LV_VER_RES_MAX; // Set the vertical resolution of the display lv_disp_drv_register(&disp_drv); // Finally register the driver lv_disp_set_bg_color(NULL, lv_color_hex3(0x000)); // Set default background color to black } void my_touchpad_read(lv_indev_drv_t * drv, lv_indev_data_t * data) { TouchPoint_t pos = M5.Touch.getPressPoint(); bool touched = ( pos.x == -1 ) ? false : true; if(!touched) { data->state = LV_INDEV_STATE_RELEASED; } else { data->state = LV_INDEV_STATE_PRESSED; data->point.x = pos.x; data->point.y = pos.y; } } void init_touch_driver() { lv_disp_drv_register(&disp_drv); lv_indev_drv_init(&indev_drv); indev_drv.type = LV_INDEV_TYPE_POINTER; indev_drv.read_cb = my_touchpad_read; lv_indev_t * my_indev = lv_indev_drv_register(&indev_drv); // register } void setup() { tft_lv_initialization(); init_disp_driver(); init_touch_driver(); lv_obj_t * btn1 = lv_btn_create(lv_scr_act()); lv_obj_t * label = lv_label_create(btn1); lv_obj_align(btn1, LV_ALIGN_CENTER, 0, 0); lv_label_set_text(label, "Power Off"); lv_obj_center(label); lv_obj_add_event_cb(btn1, btnPowerOff_event, LV_EVENT_CLICKED, NULL); } void loop() { M5.update(); lv_task_handler(); }
-
@jackrazors Thanks for sharing!
-
I'm struggling with edgline but just realized the code which is automatically generated is not compatible with LVGL 8.x, only version 7.
Looks like they have not updated the tools since a while, not even sure if they still want to maintain it.
I am going back to old school manual coding...I don't mind writing lines of code but I am bad at designing UIs and EdgeLine seemed to be my savior (but not anymore unfortunately) -
@jackrazors hello, I tried to run your code, but the function my_touchpad_read is never called..
Would be possible for you to share the repo ?
Thanks !! -
@lunard said in How to run LVGL on M5Stack:
@jackrazors hello, I tried to run your code, but the function my_touchpad_read is never called..
Would be possible for you to share the repo ?
Thanks !!Ok @JackRazors was missing lv_tick_inc(1); in the loop function
-
Hello@erich
LVGL 8.0.2 is listed below.
LVGL 8.0.2
LVGL 8 demo with M5Stack , M5Stamp C3
https://forum.m5stack.com/topic/4161/lvgl-8-demo-with-m5stack-m5stamp-c3 -
Would be perfect to use with the M5Stack Atom Display with a 7 inch display.
But does it run on an Atom ?