How to create a separate thread for LVGL GUI and Loop in Arduino code

Hi all

The essence of the problem is the slow response to pressing the button. Not instantly. Please share a simple code example.

Physical button or touch on display screen? You show code, we can help…

1 Like

display screen

My code:

#include "Arduino_H7_Video.h"
#include "Arduino_GigaDisplayTouch.h"
#include "lvgl.h"
#include <Adafruit_MAX31865.h>
#include "SPI.h"

static void btn_event_cbStop(lv_event_t * e) {
  StartWork = false;
}

void setup() 
{

  //3. create a Stop button
  lv_obj_t * btnStop = lv_btn_create(tab1);
  lv_obj_set_size(btnStop, 300, 140);
  lv_obj_set_pos(btnStop, 425, 215);
  lv_obj_add_event_cb(btnStop, btn_event_cbStop, LV_EVENT_CLICKED, NULL);

  static lv_style_t style_btn_red;
  lv_style_init(&style_btn_red);
  lv_style_set_bg_color(&style_btn_red, lv_color_make(255, 0, 0)); // BLUE RED GREEN 
  lv_style_set_bg_opa(&style_btn_red, LV_OPA_COVER);
  lv_obj_add_style(btnStop, &style_btn_red, 0);

  static lv_style_t style_btn_blue;
  lv_style_init(&style_btn_blue);
  lv_style_set_bg_color(&style_btn_blue, lv_color_make(0, 0, 255)); // BLUE RED GREEN 
  lv_style_set_bg_opa(&style_btn_blue, LV_OPA_COVER);

  //4. create a caption for the Stop button
  lv_obj_t * labelStop = lv_label_create(btnStop);
  lv_label_set_text(labelStop, "STOP");
  lv_obj_center(labelStop);
  lv_obj_add_style(labelStop, &style_lab_btn_montserrat_32, 0);

}

void loop() 
{
  /* Feed LVGL engine */
  lv_timer_handler();

uint8_t fault1 = max_1.readFault();
    if (fault1)
    {
       ErrorMax_1 = true;
       
       Serial.print("max_1 Fault 0x"); Serial.println(fault1, HEX);

       if (fault1 & MAX31865_FAULT_HIGHTHRESH)
       {
          Serial.println("max_1 RTD High Threshold"); 
       }
       if (fault1 & MAX31865_FAULT_LOWTHRESH)
       {
          Serial.println("max_1 RTD Low Threshold"); 
       }
       if (fault1 & MAX31865_FAULT_REFINLOW)
       {
          Serial.println("max_1 REFIN- > 0.85 x Bias"); 
       }
       if (fault1 & MAX31865_FAULT_REFINHIGH)
       {
          Serial.println("max_1 REFIN- < 0.85 x Bias - FORCE- open"); 
       }
       if (fault1 & MAX31865_FAULT_RTDINLOW)
       {
          Serial.println("max_1 RTDIN- < 0.85 x Bias - FORCE- open"); 
       }
       if (fault1 & MAX31865_FAULT_OVUV)
       {
          Serial.println("max_1 Under/Over voltage"); 
       }

       max_1.clearFault();
    }
    else
    {
       ErrorMax_1 = false;
    }

 //1. max_1 = Adafruit_MAX31865(5, 11, 12, 13);
    if (ErrorMax_1 == false)
    {
       
       if (max_1.temperature(100, RREF) < -100 || max_1.temperature(100, RREF) > 800)  goto labErrorMax_1;
       
       str = "Temp 1:   " + String(max_1.temperature(100, RREF)) + " °C";
       lv_label_set_text(labelTemp1, str.c_str());

       if (max_1.temperature(100, RREF) <= MinTemp)
       {
          digitalWrite(0, HIGH);
          lv_obj_remove_style_all(labelTemp1);
          lv_obj_set_pos(labelTemp1, 60, 60);
          lv_obj_add_style(labelTemp1, &style_lab_CaptionHot, 0);
       } 
       if (max_1.temperature(100, RREF) >= MidlTemp)
       {
          digitalWrite(0, LOW);
          lv_obj_remove_style_all(labelTemp1);
          lv_obj_set_pos(labelTemp1, 60, 60);
          lv_obj_add_style(labelTemp1, &style_lab_CaptionCold, 0);
       } 
    }
    else
    {
labErrorMax_1:
       str = "Temp 1:  Fehler: " + String(max_1.readFault());
       lv_label_set_text(labelTemp1, str.c_str());
       lv_obj_remove_style_all(labelTemp1);
       lv_obj_set_pos(labelTemp1, 60, 60);
       lv_obj_add_style(labelTemp1, &style_lab_CaptionError, 0);
       digitalWrite(0, LOW);
    }

} 

I see two fails here

  1. you dont show touch read method
  2. you read MAX data in max speed lvgl cant in loop work without delay

for example your code call lv_label_set_text( … and repeat this in next loop and your MCU is quick … do this call 10000 x per second I ask can you see this text changes?

Your question sometimes you require separate task, but this require more knowledge and thread safe methods. Your code dont require this , but add time management. I use looper5 counter and call show only when data real change.

unsigned int looper5=0;
void loop() {
  // put your main code here, to run repeatedly:
  lv_timer_handler(); /* let the GUI do its work */
  delay(5);
  looper5++;

if( (looper5%2000)==0 ) do somethink every 10sec ...
1 Like

Yes I can see test changes in real time. The text can change constantly, because… The temperature of the PCB heater changes. Frequent changes in the temperature label are not important to me. For me, the quick response of the Stop button is important so that the user can stop the drying process of printed circuit boards. Plus, if the user tries to open other interface bookmarks, it happens even slower.

You see 10000per sec display changes on display with 60Hz refresh hmmm you are Terminator

But real when your MCU handle MAX cant handle touch … result is slow reaction.

1 Like

That’s why I asked about creating two independent threads for the IVGL graphical interface and the Loop loop itself in the Arduino code

The code marian suggested would basically do this: the problem is that you seem to be constantly calling functions that change UI (lv_*...), causing LVGL to also be busy with its functionality as well as you constantly changing values in a label (thousands of times per second) on a screen that can most probably only display changes 60 times per second (60Hz).

Putting the functionality of changing labels in another function and only calling that once every x amount of times you loop through the code, will already be a drastic change.

So for instance:

void updateLabels();	// Function for updating all labels 
void printSerial(); 	// Function for serial print of data

#define DELAY 3
#define LV_UPD_INTERVAL 50

static uint16_t lvUpdateWait = LV_UPD_INTERVAL;

void main()
{
	while (1)
	{
		lv_timer_handler();
		printSerial();
		
		delay(DELAY); // 3 ms delay 
		
		lvUpdateWait--;
		if (lvUpdateWait <= 0)
		{
			updateLabels();
			lvUpdateWait = LV_UPD_INTERVAL;
		}
	}	
}
1 Like

Operating system and interrupts — LVGL documentation

but your design dont require this.

For tasks such as regularly updating labels, it is recommended to use a Timer to achieve it, so that you do not need to manually manage the update frequency.