rzeldent / esp32-smartdisplay

PlatformIO library LVGL Drivers for Sunton Smart display boards (CYD Cheap Yellow Display). This library supports these boards without any effort. ESP32-2432S024N/R/C, ESP32-2432S028R/C, ESP32-3248S035R/C, ESP32_8048S070N/C
https://github.com/rzeldent/platformio-espressif32-sunton
GNU General Public License v3.0
423 stars 74 forks source link

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

Open AllanOricil opened 8 months ago

AllanOricil commented 8 months ago

@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 commented 8 months ago

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

image
rzeldent commented 8 months ago

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....

AllanOricil commented 8 months ago

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?

rzeldent commented 8 months ago

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

AllanOricil commented 8 months ago

But it was already set with SPI2_HOST

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

rzeldent commented 8 months ago

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

AllanOricil commented 8 months ago

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 commented 8 months ago

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 commented 8 months ago

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 commented 8 months ago

@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 commented 8 months ago

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 commented 8 months ago

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 commented 8 months ago

@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 commented 8 months ago

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 commented 8 months ago

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 commented 8 months ago

@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 commented 8 months ago

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

AllanOricil commented 8 months ago

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
rzeldent commented 8 months ago

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....

AllanOricil commented 8 months ago

@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 commented 8 months ago

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()

rzeldent commented 8 months ago

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

AllanOricil commented 8 months ago

@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 commented 8 months ago

@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
rzeldent commented 8 months ago

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,,,

AllanOricil commented 8 months ago

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 commented 8 months ago

@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 commented 7 months ago

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"

plueschpruem commented 1 month ago

@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.