ILI9488 TFT Display SD card function not working

Hi!
I am working on a project in which I use multiple MKRs 1310 WAN to send data(ENV parameters) through LoRa. On a particular one I have connected a TFT ILI9488 Display with touchscreen and SD card Slot. My intention is to store the received data on the SD card attached to the display and then display those parameters and add graphs for the evolution of them. The problem is I cannot initialize the SD card. I tried SD, SDFat, TFT_SDFat and now SDFat-Adafruit-Fork libraries but none of them seems to help. For the display and touchscreen function I use TFT_eSPI and it works fine after modyfing in User_Setup.h, which after some research it says it has no control over SD card function. All I found regarding this problem was for ESP32, not for something related to MKR 1310. Any ideas how to solve this problem?
Thanks in advance!
UPDATE: I also have MKR SD Proto Shield and when I connect both this shield and the display it fails to initialize the SD card. When its just the Proto shield I manage to access the SD card. Surely it is a SPI problem. I tried to set HIGH the CS pins for both devices before initialization but it didn't work. (SDCard is FAT32)

In the absence of a sketch and schematic, all I can suggest is to lift the display's MISO line to see if you're running into the classic "SPI LCD display doesn't tri-state MISO when not selected" problem. Good luck with your project.

I will provide now some more information about the setup.



SDcard_test.ino (2.3 KO)
User_Setup.h (18.4 KO)

So the pins summary:
-TFT_MOSI and T_MOSI = pin 8
-TFT_SCLK and T_SCLK = pin 9
-T_MISO = pin 10
-D/C = pin 2
-TFT_CS = pin 6
-T_CS = pin 5
Note: Pins 3 and 4 are used by the proto Shield for Flash memory(pin3) and Chip select(pin4)

Meanwhile I tried to change the library, instead of TFT_eSPI I installed LovyanGFX as I saw it is compatible with SAMD21(the chip from MKR1310) but I didn't manage to configure it.
So, now are 2 questions: to go find the SPI interference problem or to work out how to configure other libraries which might handle better the SPI communication.

I don't have any experience with SAMD21 programming, so I don't know if it applies to your case, but I'll share my experience with the XIAO ESP32S3, which has only one hardware SPI bus available, just like your board.

I modified the following code.

Before:

if (!SD.begin(SD_CS)) {
  Serial.println("SD Card init failed!");
  ...

After:

#define SPI_SD_FREQUENCY 50000000 // 50MHz
#define SD_CONFIG SD_CS, tft.getSPIinstance(), SPI_SD_FREQUENCY

if (!SD.begin(SD_CONFIG)) {
  Serial.println("SD Card init failed!");
  ...

You might also be interested in the following article, although I'm not sure if it also will be of any use to you.

Good luck!

Thank you for your response! I will try it!

Apparently the MISO not tri-stating was the problem, because I had the TDO pin from touchscreen connected to it. After removing it I was able to use SD card and screen simultaneously. However I need to use touchscreen so I need to solve this 'tristating problem'. I tried with pull-up resistor but didn't work. Only solution is to use IC 74AHC125? Thank you for your help!

I assume that the CS lines are high when idle. Is the display output pin also high when idle?

If all that is true, possible solutions might include:

  1. A buffer with active-low output enable, with /OE connected to the CS line for the display. A single-gate should work: SN74AHC1G125

  2. The first less-elegant solution. If touchscreen input will never take place while the SD card is active, then a diode inserted into the display output line would work, so the display can only bring that line low, not high. Might have to add a pullup resistor.

  3. Second less-elegant solution. I've never actually tried this, but it may work. You could insert a resistor into the display's output line. Something like 3.3K or 4.7K. Then even if the line is active when it shouldn't be, it would only act as a pullup or pulldown resistor, and the SD would still drive the line ok against that. The display would still drive the line when it needs to because the SD MISO line would be tristate. Speed might not be so great.

Edit: I think this would also work. If you have a PNP transistor like a 2N3906, you could use it as the tristate buffer. The emitter is connected to the MISO line of the processor, with a pullup resistor. The collector is connected to the display output, and the base is connected through a resistor to the /CS line of the display. If /CS is high, the base will be at or above any possible voltage on the emitter, so the transistor will be off even if the display output goes low. And if /CS is low, then the emitter will follow the collector with no inversion. This would work the same as just using a diode, but if someone touched the screen during SD operation, it wouldn't mess up the SD.

Well as I not have home SN74AHC1G125 or something related I tried again the method with pull-up resistor and it worked for 1k ohms (I connected it in series with the wire coming from TDO - touchscreen's data out - and MISO pin of the board).
I ran 2 separate sketches:
-First Display: initializes touch screen and prints the coordonates of the area touched and I measured the voltage on TDO pin and it drops from 1V(when screen is not touched) to 0.2V(when screen is touched) while the SD DO pin's voltage drops from 1.5V to 1V
-SD card test: seems to have constant voltage for both pins, TDO stays at 0.2V and SD DO at 1V.
//First display

#include <TFT_eSPI.h>
#include <XPT2046_Touchscreen.h> 

#define CS_PIN  3   // Chip Select for Touch
XPT2046_Touchscreen ts(CS_PIN);
    
TFT_eSPI tft = TFT_eSPI();

void setup() {
    Serial.begin(9600);
    tft.init();
    tft.setRotation(1);  // Adjust as needed
    tft.fillScreen(TFT_BLACK);
    tft.setTextColor(TFT_WHITE);
    tft.setTextSize(2);
    tft.setCursor(20, 40);
    tft.println("Hello, MKR 1310!");

    ts.begin();
    ts.setRotation(1);
    Serial.println("Touchscreen initialized!");

}

void loop() {
    if (ts.touched()) {
        TS_Point p = ts.getPoint();  // Get raw touch data

        Serial.print("Raw X: "); Serial.print(p.x);
        Serial.print(" Raw Y: "); Serial.print(p.y);
        Serial.print(" Pressure: "); Serial.println(p.z);

        delay(1000);  // Slow down prints
    }
}

//SD card test

#include <TFT_eSPI.h>     // ILI9488 TFT library
#include <SD.h>           // SD card library
#include <SPI.h>

TFT_eSPI tft = TFT_eSPI();  // Create TFT object

#define SD_CS 4           // SD Card Chip Select
#define TOUCH_CS 3        // Touchscreen Chip Select (Update if needed)

void setup() {
  Serial.begin(115200);
  while (!Serial);

  // Initialize TFT
  tft.begin();
  tft.setRotation(1);  // Landscape mode
  tft.fillScreen(TFT_BLACK);
  tft.setTextSize(2);
  tft.setTextColor(TFT_GREEN, TFT_BLACK);
  tft.setCursor(10, 10);
  tft.println("SD Test Starting...");

 
  if (!SD.begin(SD_CS)) {
    Serial.println("SD Card init failed!");
    tft.setTextColor(TFT_RED, TFT_BLACK);
    tft.setCursor(10, 40);
    tft.println("SD init FAILED!");
    while (1);
  }

  Serial.println("SD Card initialized.");
  tft.setCursor(10, 40);
  tft.setTextColor(TFT_GREEN, TFT_BLACK);
  tft.println("SD init SUCCESS");

  // Write test data
  File dataFile = SD.open("data2.txt", FILE_WRITE);
  if (dataFile) {
    dataFile.println("Temp: 20.5 C");
    dataFile.println("Humidity: 30.3 %");
    dataFile.println("Pressure: 100 hPa");
    dataFile.close();
    Serial.println("Data written to SD.");
    tft.setCursor(10, 70);
    tft.println("Write OK");
  } else {
    Serial.println("Failed to write to file.");
    tft.setCursor(10, 70);
    tft.setTextColor(TFT_RED, TFT_BLACK);
    tft.println("Write FAIL");
  }

  // Read data back and display
  dataFile = SD.open("data2.txt");
  if (dataFile) {
    tft.setCursor(10, 110);
    tft.setTextColor(TFT_WHITE, TFT_BLACK);
    tft.println("Reading SD:");

    while (dataFile.available()) {
      String line = dataFile.readStringUntil('\n');
      Serial.println(line);
      tft.println(line);
      delay(300);  // Delay for readability on screen
    }
    dataFile.close();
  } else {
    Serial.println("Failed to read file.");
    tft.setCursor(10, 110);
    tft.setTextColor(TFT_RED, TFT_BLACK);
    tft.println("Read FAIL");
  }

}

void loop() {
  // No actions in loop
}

Now I should test a sketch where both touch and sd card are working to see if pull-up resistor method still performs, otherwise I will comeback to test the other suggestions you have made.

Thanks a lot for your responses and help!!

I don't understand those voltages, or how they could work with a 3.3V processor.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.