Open AllanOricil opened 8 months ago
I further isolated the issue to smartdisplay_init()
. After calling it, I can no longer use the sd card
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
SPI3_HOST=2, ///< SPI3
Or change the SPI HOST for the SD card....
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?
Yes, then try the "'-D ST7789_SPI_HOST=SPI2_HOST'" flag!
But it was already set with SPI2_HOST
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
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
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'",
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");
@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.
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?
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);
@rzeldent Im blocked until this issue could be resolved. I tried everything I could have asked to chatgpt. I ran out of questions D:
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.
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
@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.
This did not work as well. Both LCD and SD on the same SPI bus (SPI2_HOST).
The screen freezes, and the sd card cant find the file (the file exists, and it is closed!!!)
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 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.
Look, it does not work. This function called add_new_secret
is called whenever a mqtt message is received.
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 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.
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
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"
}
@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.
Now, I can receive messages from my server using mqtt, and the folder is created
UPDATE:
I added all the other operations just to be sure that they work
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,,,
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
@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!
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"
@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.
@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.
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?