esp32-smartdisplay icon indicating copy to clipboard operation
esp32-smartdisplay copied to clipboard

ESP32-2432S028 - Can't use SD card after initializing the UI

Open AllanOricil opened this issue 11 months ago • 29 comments

@rzeldent

I isolated the problem to the UI initialization. If I remove it from my code entirely, I no longe have any issues reading/writing/append to files from the SD Card. Bellow you can see a simple evidence of the issue.

image

According to chat gpt, the issue might be related to the way the SPI is configured to the LCT, Toutch and SD card. There might exist a problem that does not let the 3 work together. Is there a way to bypass it?

Could you maybe create a lock/unlock for the display when the SD card wants to use the SPI?

AllanOricil avatar Mar 12 '24 13:03 AllanOricil

I further isolated the issue to smartdisplay_init(). After calling it, I can no longer use the sd card

image

AllanOricil avatar Mar 12 '24 14:03 AllanOricil

Hi Allan,

I think it is caused by the SPI bus using the same SPI bus as the SD card.

In the file esp32-2432S028R.json you can trt to change the SPI host to : "'-D ILI9341_SPI_HOST=SPI2_HOST'"

Choices are:

SPI1_HOST=0,    ///< SPI1
SPI2_HOST=1,    ///< SPI2

#if SOC_SPI_PERIPH_NUM > 2 SPI3_HOST=2, ///< SPI3

Or change the SPI HOST for the SD card....

rzeldent avatar Mar 12 '24 15:03 rzeldent

ILI9341_SPI_HOST

@rzeldent I'm using esp32-2432S028Rv3.json and there is no -D ILI9341_SPI_HOST=SPI2_HOST in extra_flags.

Besides that, inpecting esp32-2432S028R.json I saw that it has is already using SPI2_HOST

"'-D ILI9341_SPI_HOST=SPI2_HOST'",

v2 and v3 use this other one

"'-D ST7789_SPI_HOST=SPI2_HOST'",

Is this ST7789_SPI_HOST equivalent to ILI9341_SPI_HOST? Should I change it SPI1_HOST?

AllanOricil avatar Mar 12 '24 16:03 AllanOricil

Yes, then try the "'-D ST7789_SPI_HOST=SPI2_HOST'" flag!

rzeldent avatar Mar 12 '24 16:03 rzeldent

But it was already set with SPI2_HOST

Look, https://github.com/rzeldent/platformio-espressif32-sunton/blob/e864619f48bb75cfb7d1db3387ffa5897126aa5f/esp32-2432S028Rv3.json#L16

AllanOricil avatar Mar 12 '24 16:03 AllanOricil

Yes, that is how it is now. But try to change this to SPI1_HOST or even SPI3_HOST.... The CS Card can also work in 2 modes, SPI or a 4 bits protocol. https://esp32.com/viewtopic.php?t=110

rzeldent avatar Mar 12 '24 16:03 rzeldent

None worked.

I changed -D ST7789_SPI_HOST=SPI2_HOST to -D ST7789_SPI_HOST=SPI3_HOST at ~/.platformio/platforms/espressif32/boards/esp32-2432S028Rv3.json, full clean, build, upload and monitor and got the same result

I changed -D ST7789_SPI_HOST=SPI2_HOST to -D ST7789_SPI_HOST=SPI1_HOST at ~/.platformio/platforms/espressif32/boards/esp32-2432S028Rv3.json, then did a full clean, build, upload and monitor and got the same result

AllanOricil avatar Mar 12 '24 17:03 AllanOricil

I also noticed that SPI3_HOST is already being used by the XPT2046 in all revisions of esp32-2432S028R.json

"'-D XPT2046_SPI_HOST=SPI3_HOST'",

AllanOricil avatar Mar 12 '24 17:03 AllanOricil

I just tried to free the SPI2_HOST and SPI3_HOST to let the sd card use them, and got the same result. Maybe I did it wrong?

// all the following operations work
create_dir(SD, "/test3");
write_file(SD, "/test3/test.txt", "bla");
read_file(SD, "/test3/test.txt");

// SETUP UI
smartdisplay_init();
  
pinMode(TF_CS, OUTPUT);
pinMode(ST7789_SPI_CONFIG_CS_GPIO_NUM, OUTPUT);

digitalWrite(TF_CS, LOW); //enable SD card => option as it was already HIGH in the setup
digitalWrite(ST7789_SPI_CONFIG_CS_GPIO_NUM, HIGH); // disable toutch or the screen, you can change to the toutch pin here

// THIS FAILS even when disabling touch or lcd CS_GPIO pins
read_file(SD, "/test3/test.txt");

AllanOricil avatar Mar 12 '24 17:03 AllanOricil

@rzeldent I changed both lcd and touch to use SPI2_HOST and then set the sd card to use SPI3_HOST and it worked. In the board esp32-2432S028Rv3.json I added the following changes:

"'-D ST7789_SPI_HOST=SPI2_HOST'",
"'-D XPT2046_SPI_HOST=SPI2_HOST'",
"'-D TF_SPI_HOST=SPI3_HOST'",

It was the only thing I could do to make it work. I also tried changing both to SPI3_HOST, and le tthe SD card using SPI2_HOST, but this setup did not work. However, I can no longer use the touch, and I need it. So, I think you have to create some sort of multiplexing to allow both touch and screen share the same SPI host. At least, that was what chat gpt told me. Is he right?

Here is the evidence that proves I can now read from the SD card after calling smartdisplay_init. However, I got an error, possibly related to the touch sensor, and I can no longer use the touch feature.

image

AllanOricil avatar Mar 12 '24 18:03 AllanOricil

I have also tried this combination, and my code breaks at runtime. Apparently, SPI1_HOST can only be used to flash.

"'-D ST7789_SPI_HOST=SPI2_HOST'",
"'-D XPT2046_SPI_HOST=SPI1_HOST'",
"'-D TF_SPI_HOST=SPI3_HOST'",

This means that in order to use the SD card, it will be necessary to have it sharing the same SPI_HOST with another peripheral. And, based on my tests, I believe the touch is the best option. However, it will be necessary to implement some sort of multipler. Is this possible?

AllanOricil avatar Mar 12 '24 18:03 AllanOricil

I also tried this chatgpt suggestion. Put both touch and SD card on the same SPI3_HOST, then used the following code when trying to interact with the sd card. And again, it did not work.

digitalWrite(XPT2046_SPI_CONFIG_CS_GPIO_NUM, HIGH); // Deselect touch sensor 
mySPI.beginTransaction(SPISettings(SPI_CLOCK_DIV2, MSBFIRST, SPI_MODE0));
digitalWrite(TF_CS, LOW); // Select SD card
read_file(SD, "/test3/test.txt");
// Further file operations
digitalWrite(TF_CS, HIGH); // Deselect SD card
mySPI.endTransaction();
digitalWrite(XPT2046_SPI_CONFIG_CS_GPIO_NUM, LOW);

AllanOricil avatar Mar 12 '24 19:03 AllanOricil

@rzeldent Im blocked until this issue could be resolved. I tried everything I could have asked to chatgpt. I ran out of questions D:

AllanOricil avatar Mar 12 '24 19:03 AllanOricil

According to chat gpt I have no option. This board was created without support for using SD card while touch and lcd are using the available spi buses. If you find a solution @rzeldent I would appreciate. I don't believe chat gpt is fully right.

AllanOricil avatar Mar 12 '24 19:03 AllanOricil

Or could you make your lib handle both touch and screen on the same spi bus? I read that it is possible to have multiple peripherals on the same SPI bus.

https://learn.sparkfun.com/tutorials/serial-peripheral-interface-spi/all

AllanOricil avatar Mar 12 '24 20:03 AllanOricil

@rzeldent This video shows an implementation which uses a SPI Semaphore to control which peripherals can use the the spi bus. Maybe you can do the same for your lib, and expose this as a global spi semaphore which people can use to register their peripherals with ease.

https://m.youtube.com/watch?v=8BU07bUQKvg

AllanOricil avatar Mar 12 '24 20:03 AllanOricil

https://randomnerdtutorials.com/esp32-spi-communication-arduino/

AllanOricil avatar Mar 12 '24 20:03 AllanOricil

This did not work as well. Both LCD and SD on the same SPI bus (SPI2_HOST).

image

The screen freezes, and the sd card cant find the file (the file exists, and it is closed!!!)

image

AllanOricil avatar Mar 12 '24 22:03 AllanOricil

Hi Allan,

The TFT_CS and ST7789_SPI_CONFIG_CS_GPIO_NUM should indeed do the multiplexing. CS stands for Chip Select.

Did you call the SD.begin(cspin) with the cspin specified? This should be handled automatically....

rzeldent avatar Mar 12 '24 22:03 rzeldent

@rzeldent I did. Look at the last picture.

Could you write a minimal example demonstrating that it endeed works? I could not make one. Then you can share here with everyone.

AllanOricil avatar Mar 12 '24 22:03 AllanOricil

Look, it does not work. This function called add_new_secret is called whenever a mqtt message is received.

image

Obs: disregard the name of the function. Obs: I'm just trying to read the file in that function because I did it without a problem in the setup, before calling before calling smartdisplay_init()

AllanOricil avatar Mar 12 '24 22:03 AllanOricil

Cograts! https://hackaday.com/2024/03/07/an-esp32-multifactor-totp-generator/

rzeldent avatar Mar 12 '24 22:03 rzeldent

@rzeldent I think the solution would be to use this TFT_eTouch and TFT_eSPI, according to this forum. It seems these libraries allow both Touch and LCD to work on the same SPI bus.

image

With your library, I tried setting both touch and lcd to SPI2_HOST, and let the sd card alone in SPI3_HOST, but it did not work. I also did the opposite, and put both in SPI3_HOST, and left the SD card on SPI2_HOST, and again no success. In both cases the LCD works, and the touch is disabled. As an evidence that both LCD and Touch are on the same SPI bus, see the picture shown below

image

Still, I don't know why the SD Card isn't working anywhere after calling smartdisplay_init(). This is how I'm configuring the SD card to run exclusively on SPI3_HOST

SPIClass custom_spi = SPIClass(VSPI); // using SPI3_HOST exclusively for the SD card

void init_sd_card_reader(){
  custom_spi.begin(TF_SPI_SCLK, TF_SPI_MISO, TF_SPI_MOSI, TF_CS); // 18, 19, 23, 5 respectively

  if(!SD.begin(TF_CS, custom_spi, 80000000)){
    Serial.println("sd card mount failed");
    return;
  }
  uint8_t cardType = SD.cardType();
  if (cardType == CARD_NONE) {
    Serial.println("No SD card attached");
    return;
  }

  Serial.print("SD Card Type: ");
  if (cardType == CARD_MMC) {
      Serial.println("MMC");
  } else if (cardType == CARD_SD) {
      Serial.println("SDSC");
  } else if (cardType == CARD_SDHC) {
      Serial.println("SDHC");
  } else {
      Serial.println("UNKNOWN");
  }

  Serial.printf("SD Card Size: %lluMB\n", SD.cardSize() / (1024 * 1024));
  Serial.printf("Total space: %lluMB\n", SD.totalBytes() / (1024 * 1024));
  Serial.printf("Used space: %lluMB\n", SD.usedBytes() / (1024 * 1024));
}

Inside the setup, before calling smartdisplay_init(), I can read/append/write to files without a problem. I'm also sure to close the file with file.close() after reading it, so that I can later reopen it without a problem. But whenever I try doing it after calling smartdisplay_init(), the same problem happens. Even when using a exclusive SPI bus for the SD card.

This is my board config for the experiment described above

{
  "build": {
    "arduino": {
      "ldscript": "esp32_out.ld"
    },
    "core": "esp32",
    "extra_flags": [
      "'-D ARDUINO_ESP32_DEV'",
      "'-D ESP32_2432S028Rv3'",
      "'-D LCD_WIDTH=240'",
      "'-D LCD_HEIGHT=320'",
      "'-D LVGL_BUFFER_PIXELS=(LCD_WIDTH*LCD_HEIGHT/4)'",
      "'-D LVGL_BUFFER_MALLOC_FLAGS=(MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)'",
      "'-D GPIO_BCKL=21'",
      "'-D LCD_ST7789_SPI'",
      "'-D ST7789_SPI_HOST=SPI2_HOST'",
      "'-D ST7789_SPI_DMA_CHANNEL=SPI_DMA_CH_AUTO'",
      "'-D ST7789_SPI_BUS_MOSI_IO_NUM=13'",
      "'-D ST7789_SPI_BUS_MISO_IO_NUM=GPIO_NUM_NC'",
      "'-D ST7789_SPI_BUS_SCLK_IO_NUM=14'",
      "'-D ST7789_SPI_BUS_QUADWP_IO_NUM=GPIO_NUM_NC'",
      "'-D ST7789_SPI_BUS_QUADHD_IO_NUM=GPIO_NUM_NC'",
      "'-D ST7789_SPI_BUS_MAX_TRANSFER_SZ=0'",
      "'-D ST7789_SPI_BUS_FLAGS=0'",
      "'-D ST7789_SPI_BUS_INTR_FLAGS=0'",
      "'-D ST7789_SPI_CONFIG_CS_GPIO_NUM=15'",
      "'-D ST7789_SPI_CONFIG_DC_GPIO_NUM=2'",
      "'-D ST7789_SPI_CONFIG_SPI_MODE=SPI_MODE3'",
      "'-D ST7789_SPI_CONFIG_PCLK_HZ=24000000'",
      "'-D ST7789_SPI_CONFIG_TRANS_QUEUE_DEPTH=10'",
      "'-D ST7789_SPI_CONFIG_LCD_CMD_BITS=8'",
      "'-D ST7789_SPI_CONFIG_LCD_PARAM_BITS=8'",
      "'-D ST7789_SPI_CONFIG_FLAGS_DC_AS_CMD_PHASE=false'",
      "'-D ST7789_SPI_CONFIG_FLAGS_DC_LOW_ON_DATA=false'",
      "'-D ST7789_SPI_CONFIG_FLAGS_OCTAL_MODE=false'",
      "'-D ST7789_SPI_CONFIG_FLAGS_LSB_FIRST=false'",
      "'-D ST7789_DEV_CONFIG_RESET_GPIO_NUM=GPIO_NUM_NC'",
      "'-D ST7789_DEV_CONFIG_COLOR_SPACE=ESP_LCD_COLOR_SPACE_RGB'",
      "'-D ST7789_DEV_CONFIG_BITS_PER_PIXEL=16'",
      "'-D ST7789_DEV_CONFIG_FLAGS_RESET_ACTIVE_HIGH=false'",
      "'-D ST7789_DEV_CONFIG_VENDOR_CONFIG=NULL'",
      "'-D LCD_SWAP_XY=false'",
      "'-D LCD_MIRROR_X=false'",
      "'-D LCD_MIRROR_Y=false'",
      "'-D BOARD_HAS_TOUCH'",
      "'-D TOUCH_XPT2046_SPI'",
      "'-D XPT2046_SPI_HOST=SPI2_HOST'",
      "'-D XPT2046_SPI_DMA_CHANNEL=SPI_DMA_CH_AUTO'",      
      "'-D XPT2046_SPI_BUS_MOSI_IO_NUM=32'",
      "'-D XPT2046_SPI_BUS_MISO_IO_NUM=39'",
      "'-D XPT2046_SPI_BUS_SCLK_IO_NUM=25'",
      "'-D XPT2046_SPI_BUS_QUADWP_IO_NUM=GPIO_NUM_NC'",
      "'-D XPT2046_SPI_BUS_QUADHD_IO_NUM=GPIO_NUM_NC'",
      "'-D XPT2046_SPI_CONFIG_CS_GPIO_NUM=33'",
      "'-D XPT2046_SPI_CONFIG_DC_GPIO_NUM=GPIO_NUM_NC'",
      "'-D XPT2046_SPI_CONFIG_SPI_MODE=SPI_MODE0'",
      "'-D XPT2046_SPI_CONFIG_PCLK_HZ=2000000'",
      "'-D XPT2046_SPI_CONFIG_TRANS_QUEUE_DEPTH=3'",
      "'-D XPT2046_SPI_CONFIG_LCD_CMD_BITS=8'",
      "'-D XPT2046_SPI_CONFIG_LCD_PARAM_BITS=8'",
      "'-D XPT2046_SPI_CONFIG_FLAGS_DC_AS_CMD_PHASE=false'",
      "'-D XPT2046_SPI_CONFIG_FLAGS_DC_LOW_ON_DATA=false'",
      "'-D XPT2046_SPI_CONFIG_FLAGS_OCTAL_MODE=false'",
      "'-D XPT2046_SPI_CONFIG_FLAGS_LSB_FIRST=false'",
      "'-D XPT2046_TOUCH_CONFIG_X_MAX=LCD_WIDTH'",
      "'-D XPT2046_TOUCH_CONFIG_Y_MAX=LCD_HEIGHT'",
      "'-D XPT2046_TOUCH_CONFIG_RST_GPIO_NUM=GPIO_NUM_NC'",
      "'-D XPT2046_TOUCH_CONFIG_INT_GPIO_NUM=36'",
      "'-D XPT2046_TOUCH_CONFIG_LEVELS_RESET=0'",
      "'-D XPT2046_TOUCH_CONFIG_LEVELS_INTERRUPT=0'",
      "'-D TOUCH_SWAP_XY=false'",
      "'-D TOUCH_SWAP_X=true'",
      "'-D TOUCH_SWAP_Y=false'",
      "'-D BOARD_HAS_TF'",
      "'-D TF_SPI_HOST=SPI3_HOST'",
      "'-D TF_CS=5'",
      "'-D TF_SPI_MOSI=23'",
      "'-D TF_SPI_SCLK=18'",
      "'-D TF_SPI_MISO=19'",
      "'-D BOARD_HAS_RGB_LED'",
      "'-D RGB_LED_R=4'",
      "'-D RGB_LED_G=16'",
      "'-D RGB_LED_B=17'",
      "'-D BOARD_HAS_CDS'",
      "'-D CDS=34'",
      "'-D BOARD_HAS_SPEAK'",
      "'-D SPEAK=26'"
    ],
    "f_cpu": "240000000L",
    "f_flash": "40000000L",
    "flash_mode": "dio",
    "mcu": "esp32",
    "variant": "esp32"
  },
  "connectivity": [
    "wifi",
    "bluetooth",
    "ethernet",
    "can"
  ],
  "debug": {
    "openocd_board": "esp-wroom-32.cfg"
  },
  "frameworks": [
    "arduino",
    "espidf"
  ],
  "name": "esp32-2432S028Rv3",
  "upload": {
    "flash_size": "4MB",
    "maximum_ram_size": 327680,
    "maximum_size": 4194304,
    "require_upload_port": true,
    "speed": 460800
  },
  "url": "https://www.aliexpress.com/item/1005004502250619.html",
  "vendor": "Sunton"
}

AllanOricil avatar Mar 13 '24 15:03 AllanOricil

@rzeldent finally managed to make the SD card work after smartdisplay_init(). However the touch is no longer working. I think it is because the touch and lcd are sharing the same SPI bus, but your library wasn't made for that.

https://github.com/AllanOricil/esp32-mfa-totp-generator/blob/36ef7bac4e55dc0919e2a6bd2e6332146d0eea06/src/main.cpp#L43-L75

Now, I can receive messages from my server using mqtt, and the folder is created image

UPDATE:

I added all the other operations just to be sure that they work

image

AllanOricil avatar Mar 13 '24 15:03 AllanOricil

Hi Allan,

That's a pity touch is not working anymore. Now no time to look into that. However, maybe defining an esp32-2432S028N (No touch) might be something to prevent interference with touch,,,

rzeldent avatar Mar 14 '24 20:03 rzeldent

esp32-2432S028N

@rzeldent no problem. But I need the touch to work. I want to use all 3 peripherals. Would your suggestion enable it? Could you explain it in more details? Thank you

AllanOricil avatar Mar 14 '24 20:03 AllanOricil

@rzeldent I will put my project to rest for now. Once you you have time to fix this, I will go back to it. I don't have enough knowledge of microcontrolers like you, so it would take me ages to fix it by myself. Thank you anyway. Hope you find time soon!

AllanOricil avatar Mar 14 '24 20:03 AllanOricil

For those with the same issue, these repositories have a solution:

Solution Summary: use a bitbang implementation for the touch sensor instead of a hardware spi bus

https://github.com/AllanOricil/esp32-lvgl-lcd-touch-sd-card obs: main branch uses lvgl 7 obs: lvgl-8 branch used lvgl 8

https://github.com/AllanOricil/esp32-mfa-totp-generator obs: is using lvgl 8

@rzeldent you could add the same lib to your lib as a dependency, and create a feature flag such as "XPT2046_DONT_USE_SPI_BUS=1"

AllanOricil avatar Mar 20 '24 16:03 AllanOricil

@rzeldent finally managed to make the SD card work after smartdisplay_init(). However the touch is no longer working. I think it is because the touch and lcd are sharing the same SPI bus, but your library wasn't made for that.

Well, it works ONCE. I can init smartdisplay and read a file in loop() – but only once and then it gives errors again.

plueschpruem avatar Oct 04 '24 13:10 plueschpruem

I am using it with the 5 inch Not without problems

Mostly related to

https://github.com/espressif/arduino-esp32/pull/10122

So I have my own patched version of SD lib

Also worth to mention that SD.begin fails at least first time, so

        while (attempt <= 5)
        {
            if (SD.begin(10, SPI, 2000000U, "/sd", maxFiles))
            { ....

Cheers!!

xperiments avatar Nov 10 '24 03:11 xperiments