Lv_msgbox_create

It all depends on how the parenthesis get used. the C compiler does not support chained comparison.

In python this


if 1 < = 2 < = 3:

evaluates to

if 1 <= 2:
   if 2 <= 3:

The addition of parenthesis changes the evaluation

if (1 <= 2) <= 3:

evaluates to

var = int(bool(1 <= 2))

if var <= 3:

The reason why the c compiler complained about missing parenthesis is because the compiler does not support chained comparison and it added the missing parenthesis for you. But the evaluation would be similar to the one see in the last example here.

in C a boolean value may not be as simple as a true or false it could be -1 and 0 which is integer. In python it is always true and false but also integer at the same time. 0 = false and everything else is true. I would imagine the C compiler would not make assumptions and that is why type casting is needed. In python assumptions get made and typecasting gets handled behind the scenes so when a comparison between a bool and an integer is done the bool gets cast to integer to allow the comparison.

@Anhell

Can you please do the following:
In your Configurar_screen_init add the following lines:

printf ("adr0: 0x%08lx\n", textos);
printf ("text0[0]: 0x%08lx\n", textos[0]);
printf ("text0[1]: 0x%08lx\n", textos[1]);

printf ("text0[0][0]: 0x%02x\n", textos[0][0]);
printf ("text0[0][1]: 0x%02x\n", textos[0][1]);
printf ("text0[0][2]: 0x%02x\n", textos[0][2]);
printf ("text0[0][3]: 0x%02x\n", textos[0][3]);

In your event_Config_Button1 add the following lines:

printf ("adr1: 0x%08lx\n", textos);
printf ("text1[0]: 0x%08lx\n", textos[0]);
printf ("text1[1]: 0x%08lx\n", textos[1]);

printf ("text1[0][0]: 0x%02x\n", textos[0][0]);
printf ("text1[0][1]: 0x%02x\n", textos[0][1]);
printf ("text1[0][2]: 0x%02x\n", textos[0][2]);
printf ("text1[0][3]: 0x%02x\n", textos[0][3]);

I have done what you asked me and this is the result:

void event_Config_Button1(lv_event_t * e) {

printf ("adr1: 0x%08lx\n", textos);
printf ("text1[0]: 0x%08lx\n", textos[0]);
printf ("text1[1]: 0x%08lx\n", textos[1]);

printf ("text1[0][0]: 0x%02x\n", textos[0]);
printf ("text1[0][1]: 0x%02x\n", textos[1]);
printf ("text1[0][2]: 0x%02x\n", textos[2]);
printf ("text1[0][3]: 0x%02x\n", textos[3]);

printf result:

adr1: 0x3ffbdb68
text1[0]: 0x3ffb1c6c
text1[1]: 0x3ffb1c72
text1[0][0]: 0x3ffb1c6c
text1[0][1]: 0x3ffb1c72
text1[0][2]: 0x3ffb1c7c
text1[0][3]: 0x3ffb1d0e
----------------------------------------------------------------------
void ui_Configurar_screen_init(void)
{
 printf ("adr0: 0x%08lx\n", textos);
printf ("text0[0]: 0x%08lx\n", textos[0]);
printf ("text0[1]: 0x%08lx\n", textos[1]);

printf ("text0[0][0]: 0x%02x\n", textos[0]);
printf ("text0[0][1]: 0x%02x\n", textos[1]);
printf ("text0[0][2]: 0x%02x\n", textos[2]);
printf ("text0[0][3]: 0x%02x\n", textos[3]);

printf result:

adr0: 0x3ffbdb68
text0[0]: 0x3ffb1c6c
text0[1]: 0x3ffb1c72
text0[0][0]: 0x3ffb1c6c
text0[0][1]: 0x3ffb1c72
text0[0][2]: 0x3ffb1c7c
text0[0][3]: 0x3ffb1d0e

Not exactly my code. You forgot the second [] in the printf lines with text0[0][…] (and text1[1][…])

printf ("text0[0][0]: 0x%02x\n", textos[0]);

should be

printf ("text1[0][0]: 0x%02x\n", textos[0][0]);

And maybe you can add the following lines after your printf( "textos = %s\n", Qtextos[14]); (in function event_Config_Button1)

printf ("adr2: 0x%08lx\n", Qtextos);
printf ("textos = %s\n", Qtextos[0]);
printf ("textos = %s\n", textos[0]);
textos = � C?x
adr2: 0x3ffbdb68
textos = k�?�@���?
textos = 	k�?�@���?

This is what is displayed.

Still need the output from Configurar_screen_init

printf ("text0[0][0]: 0x%02x\n", textos[0][0]);
printf ("text0[0][1]: 0x%02x\n", textos[0][1]);
printf ("text0[0][2]: 0x%02x\n", textos[0][2]);
printf ("text0[0][3]: 0x%02x\n", textos[0][3]);

and event_Config_Button1

printf ("text1[0][0]: 0x%02x\n", textos[0][0]);
printf ("text1[0][1]: 0x%02x\n", textos[0][1]);
printf ("text1[0][2]: 0x%02x\n", textos[0][2]);
printf ("text1[0][3]: 0x%02x\n", textos[0][3]);

The array address seems to be ok, but I think the strings (chars) in RAM are corrupted.
To be sure I need these printfs.

Sorry, I don’t quite understand your request.
textos is defined: const char *textos[19]
but, you ask me for textos[0][0]
Do I have to mount a two-column array in textos?

Just do a copy and paste of the code I posted.
You did not write that what I recommended.

You wrote this:

printf ("text1[0][0]: 0x%02x\n", textos[0]);
printf ("text1[0][1]: 0x%02x\n", textos[1]);
printf ("text1[0][2]: 0x%02x\n", textos[2]);
printf ("text1[0][3]: 0x%02x\n", textos[3]);

but I want to have this:

printf ("text1[0][0]: 0x%02x\n", textos[0][0]);
printf ("text1[0][1]: 0x%02x\n", textos[0][1]);
printf ("text1[0][2]: 0x%02x\n", textos[0][2]);
printf ("text1[0][3]: 0x%02x\n", textos[0][3]);

The difference is, that with your code I get the address (which is already shown by the previous line),
and with my code I get the content of the string (chars to what the pointer points) .

And of course the same for the text0[0][0] …

Sorry but, my knowledge of C is not very good.
event_Config_Button1
text1[0][0]: 0x08
text1[0][1]: 0x6b
text1[0][2]: 0xfb
text1[0][3]: 0x3f
Configurar_screen_init
text0[0][0]: 0x41
text0[0][1]: 0x68
text0[0][2]: 0x6f
text0[0][3]: 0x72

No problem.
The output confirms what I suspected from the beginning.

The output from text0[0][0] (and following) is from Configurar_screen_init, and it shows, that the string (characters) are OK.
The 0x41 is ‘A’ , 0x68 is ‘h’, 0x6f is ‘o’ 0x72 is ‘r’.
The output from text1[0][1] (and following) is from event_Config_Button1.
And it shows different values. It’s not real ASCII. It should show the exact same values as before (as from text0[0][0])
When I interpret the four bytes as an 32-bit value (thats the reason why I wanted four bytes),
you get a 0x3ffb6b08. And this value looks a bit familiar. It’s an address to a RAM location.
Compare it with this output:

adr0: 0x3ffbdb68
text0[0]: 0x3ffb1c6c
text0[1]: 0x3ffb1c72
text0[0][0]: 0x3ffb1c6c
text0[0][1]: 0x3ffb1c72
text0[0][2]: 0x3ffb1c7c
text0[0][3]: 0x3ffb1d0e

My first guess was that the pointers within the textos array (starting at address 0x3ffbdb68) have been overwritten.
But the values of text0[0] and text1[0] are the same, This is the start address in memory where the ‘Ahora’ is located.
But something (I guess your code) is overwriting it.

And of course it doesn’t matter if you use the global textos[] array within your event_Config_Button1 or you use the passed in address of textos (via user data).

And of course I can’t tell you what you are doing wrong because I do not know your entire code.

Hello, this is what I have been able to discover.
When my program enters the loop, just before lv_timer_handler();
texto1[0][0]: 0x41
When you exit lv_timer_handler();
texto1[0][0]: 0x00
I mean, what is lv_timer_handler(); the one who corrupts textos[]
If you agree, any idea how to fix it?

void loop() {
  printf ("text1[0][0]: 0x%02x\n", textos[0][0]);
  lv_timer_handler(); /* El jefe */
  delay(5);
  printf ("text1[0][0]: 0x%02x\n", textos[0][0]);
    delay(50000);
  if ((millis() - timing) > 300000) {    // Ejecuto cada 5 mtos. eControl. 300.000 ms.
    timing = millis();   
    eControl();
    lv_event_send(ui_Inicio, LV_EVENT_REFRESH, NULL);
  }

  if ( (millis() - dormir) > 30000 && !TFT_On == 0) {  // Apago el TFT si nadie hace nada en 30 seg. 30000
    digitalWrite(mosfet, HIGH);
    TFT_On = 0;
  }

  esp_task_wdt_reset(); //Tranquilizo al perro

  buttonState = digitalRead(GPIO_NUM_35);
  if( buttonState == LOW ) esp_deep_sleep_start();
}

lv_timer_handler calls in succession call back functions which are passed when creating a timer by calling lv_timer_create ().
So if your code contains any lv_timer_create I would look at the related timer call back functions.

Hi, Consciously, I don’t use lv timer_create() in my program and have tried to pass more variables of pointers and before lv_timer_handler(); its exist and after it, its are corrupted.
I do not control what lv_timer_handler() is for, I use it because it is indicated that it has to be used.
I don’t know if apart from it I need other instructions so that Lvgl works correctly and doesn’t corrupt my global variables. You can help?
I attach the setup and loop of my program.

#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.hpp>
#include <ArduinoJson.h>
#include <esp_task_wdt.h>
#include "time.h"
#include <Preferences.h>

#include <lvgl.h>
#include <TFT_eSPI.h>
#include "ui.h"
#include "mi_EEPROM.h"
#include "config.h"

volatile unsigned long timing, dormir = 0;
#define WDT_TIMEOUT 10
// Pins para los led de estado 
#define rojo  16
#define amar  17
#define verd  22

#define mosfet 14

static const uint16_t screenWidth = 240;
static const uint16_t screenHeight = 320;

static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf[screenWidth * screenHeight / 10];

TFT_eSPI tft = TFT_eSPI(screenWidth, screenHeight); /* Instancio TFT */

#if LV_USE_LOG != 0
void my_print(const char *buf) /* Serial debugging */
{
  Serial.printf(buf);
  Serial.flush();
}
#endif

const int filas = 24;
const int colum = 4;
String tabla[filas][colum];
int estados[filas];
int estadop[filas];
String proxi[filas][colum];
int carga, cargap, dia_encurso = 0;
DynamicJsonDocument doc(2048);
int dia_guardado = 0;
String w_scro, x_scro;
double w_prec = 1.0000;
int w_hora, w_esta, f, c = 0;
int hora_encurso;
int buttonState = 1;
int TFT_On = 1;
int Wifi_On = 0;
const char *textos[19] = { "Ahora",  "Mejor hoy",  "Datos proporcionados por el\noperador del mercado disponibles\na partir de las 20:30h.\n El operador del mercado puede\nretrasarse en su publicacion.\n",  "Ha conectado a",  "Sin conesion a",  "SSID Wifi:",  "Contraseña",  "Nombre red wifi",  "Contraseña red wifi",  "Pais:",  "Idioma",  "Guardar",  "AVISO", "ERROR", "Registro Wifi OK.",  "Registro rechazado.",  "Ambos campos obligatorios.", "England\nSpain", "English\nSpanish" };
const char *L_textos[19] = { "Ahora",  "Mejor hoy",  "Datos proporcionados por el\noperador del mercado disponibles\na partir de las 20:30h.\n El operador del mercado puede\nretrasarse en su publicacion.\n",  "Ha conectado a",  "Sin conesion a",  "SSID Wifi:",  "Contraseña",  "Nombre red wifi",  "Contraseña red wifi",  "Pais:",  "Idioma",  "Guardar",  "AVISO", "ERROR", "Registro Wifi OK.",  "Registro rechazado.",  "Ambos campos obligatorios.", "England\nSpain", "English\nSpanish" };


/* 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);
}

/*Leo el touchpad*/
void my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) {
  uint16_t x = 0, y = 0;
  bool pressed = tft.getTouch(&x, &y);
  if (pressed) {
    data->point.x = x;
    data->point.y = y;
    data->state = LV_INDEV_STATE_PR;
      digitalWrite(mosfet, LOW);
      dormir = millis();
  } else {
    data->state = LV_INDEV_STATE_REL;
  }
}

void setup() {
  Serial.begin(115200);
  delay(1000);

  lv_init(); 
  
#if LV_USE_LOG != 0
  lv_log_register_print_cb(my_print); 
#endif
  
  // inicializamos los pin de estado.
  pinMode(rojo, OUTPUT);
  pinMode(verd, OUTPUT);
  pinMode(amar, OUTPUT);
  digitalWrite(rojo, LOW);
  digitalWrite(verd, LOW);
  digitalWrite(amar, LOW);
  // Realizamos el control del TFT.
  pinMode(mosfet, OUTPUT);
  digitalWrite(mosfet, LOW);
  // Estado del boton sleep
  buttonState = 1;

  // Leemos la EEPROM para saber el SSID y el password de la Wifi
  pais = "0";
  idioma = "0";
  String qq_ssid, qq_pass, qq_pais, qq_idio;
  Preferences preferences;
  preferences.begin("mylogin", false);
    if ( preferences.isKey("name_SSID") )   qq_ssid = preferences.getString("name_SSID");
    if ( preferences.isKey("E_password") )  qq_pass = preferences.getString("E_password");
    if ( preferences.isKey("E_pais") )      qq_pais = preferences.getString("E_pais");   
    if ( preferences.isKey("E_idioma") )    qq_idio = preferences.getString("E_idioma");
  preferences.end();
  ssid = qq_ssid.c_str();
  password = qq_pass.c_str();
  i_pais = qq_pais.toInt();
  i_idio = qq_idio.toInt();  
  pais =  qq_pais.c_str();
  idioma = qq_idio.c_str();
  if (ssid != "" && password != "") {
    Wifi_On = 0;  
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    Serial.println("Conectando a: " + String(ssid));
    int ws = 0;
    while (WiFi.status() != WL_CONNECTED && ws<50) {
      ws +=1;
      delay(500);        
    }
  }
  if ( WiFi.status() == WL_CONNECTED ) {
    Wifi_On = 1;
    StaticJsonDocument<1536> tex;
    String Link = "https://alquimistec.com/econtrol/idioma/" + String(idioma) + "/textos.json";
    String payload = datos_servidor(Link);  
    if ( !payload.isEmpty() ) {
      DeserializationError error = deserializeJson(tex, payload);
      if (error) Serial.println("ERROR al deserializar");
      else {
        int i = 0;
        for (JsonObject item : tex.as<JsonArray>()) {
          textos[i] = item["lit"];
          i += 1;
          if (i == 13) lit14 = item["lit"];
        }
      }
    }
  }
  pinMode(GPIO_NUM_35, INPUT);                  // activo el GPIO35 para despertar externo del botón
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_35, 1);

  eControl();

  tft.begin();
  tft.setRotation(1);
  uint16_t calData[5] = { 185, 3534, 246, 3604, 1 };
  tft.setTouch(calData);

  lv_disp_draw_buf_init(&draw_buf, buf, NULL, screenWidth * screenHeight / 10);
  static lv_disp_drv_t disp_drv; /*Inicializo el TFT*/
  lv_disp_drv_init(&disp_drv);
  disp_drv.hor_res = 320;  /*Indico la resolucion de la pantalla*/
  disp_drv.ver_res = 240;
  disp_drv.flush_cb = my_disp_flush;
  disp_drv.draw_buf = &draw_buf;
  lv_disp_drv_register(&disp_drv);
  static lv_indev_drv_t indev_drv; /*Inicializo el controlador del dispositivo de entrada (ficticio)*/
  lv_indev_drv_init(&indev_drv);
  indev_drv.type = LV_INDEV_TYPE_POINTER;
  indev_drv.read_cb = my_touchpad_read;
  lv_indev_drv_register(&indev_drv);

  ui_init();
  esp_task_wdt_init(WDT_TIMEOUT, true);   //Activamos perro para reiniciar ESP32
  esp_task_wdt_add(NULL);                 //añadir subproceso actual al reloj WDT
}

void loop() {
  lv_timer_handler(); /* El jefe */
  delay(5);

  if ((millis() - timing) > 300000) {    // Ejecuto cada 5 mtos. eControl. 300.000 ms.
    timing = millis();   
    eControl();
    lv_event_send(ui_Inicio, LV_EVENT_REFRESH, NULL);
  }

  if ( (millis() - dormir) > 30000 && !TFT_On == 0) {  // Apago el TFT si nadie hace nada en 30 seg. 30000
    digitalWrite(mosfet, HIGH);
    TFT_On = 0;
  }

  esp_task_wdt_reset(); //Tranquilizo al perro

  buttonState = digitalRead(GPIO_NUM_35);
  if( buttonState == LOW ) esp_deep_sleep_start();
}

Just before we go to the real problem. This will not work (It will always go into the if):

if (ssid != "" && password != "") {

ssid and password are of char*.
You can’t compare char strings with a !=. Comparison of char* strings are done with strcmp function(s).

Now to the real problem (as far as I can see):
In setup you have

  StaticJsonDocument<1536> tex;

  for (JsonObject item : tex.as<JsonArray>()) {
          textos[i] = item["lit"];
          i += 1;
          if (i == 13) lit14 = item["lit"];
  }

The manual about StaticJsonDocument states this:

If you declare a local variable of type [`StaticJsonDocument`](https://arduinojson.org/v6/api/staticjsondocument/), it allocates the memory pool in the stack memory.

That means, if you leave the function setup, the StaticJsonDocument tex is out of scope.
The data on the stack will be overwritten anywhere on succession of the program.
So it might be ok for some time, and will be destroyed somewhen.

That StaticJsonDocument contains the word static is a little confusing.

Thank you very much for your help :pray:, it works now, I would not have found the error in a thousand years.
I don’t know if it’s abusing :pensive:, but I only have one last problem, which is that it doesn’t refresh the data on the screen.
Every 5 minutes I run the eControl() function that checks what time it is and if it’s a new time it refreshes the price data for that new time on the screen, well, I can’t get it to do it.
I have tried with:
lv_event_send(NULL, LV_EVENT_REFRESH, NULL);
lv_obj_invalidate(lv_scr_act());
lv_refr_now(NULL);
and neither works, the data is not refreshed.

void loop() {
  lv_task_handler();
  delay(5);

  if ((millis() - timing) > 300000) {    // Ejecuto cada 5 mtos. eControl. 300.000 ms.
    timing = millis();   
    eControl();
    lv_event_send(NULL, LV_EVENT_REFRESH, NULL);
    lv_obj_invalidate(lv_scr_act());
    lv_refr_now(NULL);
  }

  if ( (millis() - dormir) > 30000 && !TFT_On == 0) {  // Apago el TFT si nadie hace nada en 30 seg. 30000
    digitalWrite(mosfet, HIGH);
    TFT_On = 0;
  }

  esp_task_wdt_reset(); //Tranquilizo al perro

  buttonState = digitalRead(GPIO_NUM_35);
  if( buttonState == LOW ) esp_deep_sleep_start();
}

if you didn’t compile LVGL with LV_TICK_CUSTOM set to 1 then you need to call lv_tick_inc before you call lv_task_handler

unsigned long curr_time = millis();
unsigned long last_time = curr_time;

void loop() {
  curr_time = millis();

  lv_tick_inc((uint32_t) (curr_time - last_time));
  lv_task_handler();
  delay(5);

  if ((millis() - timing) > 300000) {    // Ejecuto cada 5 mtos. eControl. 300.000 ms.
    timing = millis();   
    eControl();
    lv_event_send(NULL, LV_EVENT_REFRESH, NULL);
    lv_obj_invalidate(lv_scr_act());
    lv_refr_now(NULL);
  }

  if ( (millis() - dormir) > 30000 && !TFT_On == 0) {  // Apago el TFT si nadie hace nada en 30 seg. 30000
    digitalWrite(mosfet, HIGH);
    TFT_On = 0;
  }

  esp_task_wdt_reset(); //Tranquilizo al perro

  buttonState = digitalRead(GPIO_NUM_35);
  if( buttonState == LOW ) esp_deep_sleep_start();
}