WROVER Dev Kit 4.1 LCD and SD Not Working

User avatar
ESP_Me-no-dev
Posts: 80
Joined: Mon Jan 04, 2016 6:30 pm

Re: WROVER Dev Kit 4.1 LCD and SD Not Working

Postby ESP_Me-no-dev » Mon Apr 27, 2020 2:48 pm

OK So I see two issues.

1. You should use SDMMC on Wrover-Kit
2. If you want to use SPI and use the LCD as well, you need to init first a new SPI port (HSPI) and then init the SD card to use that port.

LCD and SD do not share pins and the SPI port is going to the device initialised last.

ilioss
Posts: 17
Joined: Tue Sep 05, 2017 1:43 pm

Re: WROVER Dev Kit 4.1 LCD and SD Not Working

Postby ilioss » Mon Apr 27, 2020 3:39 pm

Hello ESP_Me-no-dev

Many thanks for your helpfull reply.
I will test your notes.
I will revert .
Kind regards,
ilioSS

User avatar
Segmentation Fault
Posts: 22
Joined: Sat Apr 04, 2020 1:49 am

Re: WROVER Dev Kit 4.1 LCD and SD Not Working

Postby Segmentation Fault » Tue Apr 28, 2020 11:17 pm

Hi ESP_Me-no-dev, thank you for looking into this.

Your advice on both SD and LCD on SPI absolutely makes sense, there should be different names for different SPI buses, duh!!

Doing that helps, but there is still an issue.

My modified code:

Code: Select all

#include <WiFiClient.h>
#include <WiFi.h>
#include <esp_wifi.h>
#include <ESP32Ping.h>
#include <HTTPClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#define FS_NO_GLOBALS
#include <SdFat.h>
#include <sdios.h>
#include <WROVER_KIT_LCD.h>
#include <FreeStack.h>
#include <My_library.h>
#include <SPI.h>
#include <SD.h>


int SERIAL_BAUD_RATE = 1500000;
#define SD_CS 13
#define RGB_LED_RED   0
#define RGB_LED_GREEN 2
#define RGB_LED_BLUE  4


SPIClass SD_SPI(HSPI);
WROVER_KIT_LCD tft; //object responsible for display control
#define USE_SDIO 0
SdFat sd((SPIClass*)&SD_SPI);


// global for card size
uint32_t cardSize;
// global for card erase size
uint32_t eraseSize;
// store error strings in flash
#define sdErrorMsg(msg) sd.errorPrint(F(msg));



void setup()
{
  // SET LEDs
  pinMode(RGB_LED_BLUE, OUTPUT);
  digitalWrite(RGB_LED_BLUE, LOW);
  pinMode(RGB_LED_RED, OUTPUT);
  digitalWrite(RGB_LED_RED, LOW);

  // SET Serial
  Serial.begin(SERIAL_BAUD_RATE);

  // Set SD
  SD_SPI.begin(14, 2, 15/*, SD_CS*/); // The bultin SD card SPI for WROVER
  
  // Initialize SD
  Serial.print("Initializing the SD card... ");
  if (SD.begin(SD_CS, SD_SPI))
  {
    Serial.println("OK!");
    // check for index.htm file
    Serial.print("Checking for index.htm... ");
    if (SD.exists("/index.htm"))
    {
    Serial.println("OK!");
    }
    else
    {
    Serial.println("Failed!");
    }
  }
  else
  {
    Serial.println("Failed!");
  }
  // CHeck sd fat
  Serial.println("Initialising sd FAT:");
  uint32_t t = millis();
  #if USE_SDIO
    if (!sd.cardBegin(SD_CS, SD_SCK_MHZ(10)))
    {
      Serial.print("cardBegin failed in #if USE_SDIO");
      sdErrorMsg("\ncardBegin failed");
    }
  #else  // USE_SDIO
    if (!sd.cardBegin(SD_CS, SD_SCK_MHZ(10)))
    {
      Serial.print("cardBegin failed in #else (of #if USE_SDIO)");
      sdErrorMsg("cardBegin failed");
    }
    else
    {
      if (!sd.fsBegin())
      {
        sdErrorMsg("\nFile System initialization failed.\n");
      }
    }
  #endif  // USE_SDIO 
  t = millis() - t;
  Serial.print("init time: ");
  Serial.print(t); Serial.println("ms");


  // Set LCD
  tft.begin();   
  tft.setRotation(1); // rotate to landscape
  // Write on LCD
  tft.fillScreen(WROVER_BLACK); // paints the entire canvas
  tft.setCursor(0, 0); // position the cursor at the origin
  tft.setTextColor(WROVER_WHITE);
  tft.setTextSize(1); // font size - 1
  tft.println("Chip: ESP32");
  tft.println("Board: ESP-WROVER-KIT V4.1");
  uint64_t chipid = ESP.getEfuseMac();
  tft.printf("Chip ID = %04X", (uint16_t)(chipid>>32));//print High 2 bytes
  tft.printf("%08X",(uint32_t)chipid);//print Low 4bytes.
  tft.println();  
  tft.print("Chip Size: "); tft.println(ESP.getFlashChipSize());
  tft.print("Chip Speed: "); tft.println(ESP.getFlashChipSpeed());
  tft.print("Chip Mode: "); tft.println(ESP.getFlashChipMode());
  tft.print("Running setup and loop on core: "); tft.println(xPortGetCoreID());  
}

void loop ()
{
  delay(1000);
  tft.println(".");
  Check_Serial_income();
}


void Check_Serial_income()
{
  if (Serial.available() > 0)
  {
    String IncomingData = Recieve_serial('\n');
    if (IncomingData == "CHECK_SD_FAT" )
    {  
      Serial.println("Initialising sd FAT:");
      uint32_t t = millis();
      if (!sd.cardBegin(SD_CS, SD_SCK_MHZ(10)))
      {
        Serial.print("cardBegin failed in #else (of #if USE_SDIO)");
        sdErrorMsg("cardBegin failed");
      }
      else
      {
        if (!sd.fsBegin())
        {
          sdErrorMsg("\nFile System initialization failed.\n");
        }
      }
      t = millis() - t;
      Serial.print("init time: ");
      Serial.print(t); Serial.println("ms");
    }
    else if  (IncomingData.substring(0, 8) == "LIST_SD:" )
    {
      String arg_ = IncomingData.substring(8, IncomingData.length());

      if (SD.begin(SD_CS, SD_SPI))
      {
        fs::File dir = SD.open(arg_);
        // return the command received
        Serial.println("LIST_SD:" + arg_);
        if (!dir.isDirectory())
        {
          dir.close();
          Serial.println("NOT DIR");
          Serial.println("---END---");
          return;
        }
        dir.rewindDirectory();

        // return the requested path
        if (arg_ != "/" && arg_.charAt(0) != '/')
        {
          Serial.print("/");
        }

        for (int cnt = 0; true; ++cnt)
        {
          fs::File entry = dir.openNextFile();
          if (!entry)
          {
            break;
          }
          String _name = entry.name();
          if (_name.charAt(0) == '/')
          {
            _name = _name.substring(1, _name.length());
          }
          Serial.print(_name);
          if (cnt > 0 && entry.isDirectory())
          {
            Serial.println("/");
          }
          else
          {
            Serial.println();
          }
          entry.close();
        }
        dir.close();
        Serial.println("---END---");
      }
      else
      {
        Serial.println("SD not found.");
        return;    // init failed
      }
    }
    else if (IncomingData.substring(0, 10) == "WRITE_LCD:")
    {
      String LCD_TEXT = IncomingData.substring(10, IncomingData.length());
      Serial.println("Accepted text for LCD = " + LCD_TEXT);
      tft.print(LCD_TEXT);
    }
    else
    {
      Serial.println("Unknown command:'" + IncomingData + "'" );
      Serial.print("0x: "); 
      for (int i = 0; i < IncomingData.length(); i++)
      {
        Serial.print(IncomingData.charAt(i), HEX); 
        if (i < IncomingData.length() - 1)
        {
          Serial.print("-");
        }
      }
      if (IncomingData.length() > 0)
      {
        Serial.println();
      }
    }
  }
}
The result is SD working normally, but the LCD screen is white.

- Then I tried removing the SD card and rebooting. The LCD is working!!!
- I put back the SD card without rebooting, SD and SdFat working, lcd black but is not printing anything new.
- Removing the SD again, the LCD is working.

But because 1 picture is 0x3E7 words:
Image

So the question is: Is it possible to have the (SPI)LCD and SD working simultaneously?

(I have read that some ppl are suggesting removing R167. Is that recommended? That 0Ω resistor is connecting the CD pin of the SD to the D/C pin of the LCD and then this line is pulled up with a 10k. What are the drawbacks of having the CD pin floating? If R167 is removed and then CD is pulled up to 3V3 from another root would that work or does SD need IO21?)

ilioss
Posts: 17
Joined: Tue Sep 05, 2017 1:43 pm

Re: WROVER Dev Kit 4.1 LCD and SD Not Working

Postby ilioss » Fri May 01, 2020 1:27 pm

Hello ESP_Me_no_dev,

After two day,s of wrestling with my TFT display and various pinout sugestions and all I was able to find on the internet I must admit no succes.
At the moment I have a working set-up so realy the motivation to solve the problem is not there howe

Code: Select all

// ***************  AsyncWebserver *******************
#include <AsyncEventSource.h>
#include <ESPAsyncWebServer.h>
#include <AsyncTCP.h>
 
//****************  WIFI *****************************
#include <WiFi.h>
#include <WiFiUdp.h>                    // nodig voor de tijd NTP
AsyncWebServer server(80);

//**************** TIME ******************************
#include <time.h>
long timezone = 1; 
byte daysavetime = 1;

//**************** SPIFFS ****************************
#include <SPIFFS.h>                     // SPIFFS file flashen

//**************** ESPmDNS  **************************
#include <ESPmDNS.h>

//**************** FS  *******************************
#include <FS.h>
#include <FSImpl.h>
#include <vfs_api.h>
File fsUploadFile;                      // a File variable to temporarily store the received file

//****************  OTA ******************************
#include <ArduinoOTA.h>                 // Over the air programming

const char* ssid     = "mmm";    // Replace with your network credentials
const char* password = "nnnn";

//************** Display ****************************
#include <Adafruit_GFX.h>               // Core graphics library
#include <Adafruit_ST7735.h>            // Hardware-specific library for ST7735
#define TFT_CS         15               // Chip Select
#define TFT_RST        12               // Or set to -1 and connect to Arduino RESET pin
#define TFT_DC          4               // D/C 
#define TFT_BACKLIGHT  25               // Backlight
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

// *************** SD   ******************************
#include <SD.h>
#include <SPI.h>
#define CS_PIN 2                        // chipselect pin gedefinieerd SD card

//**************** BME280 ****************************
#include <Wire.h>
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme;                    // I2C  SDA=21 en SCL=22

// ***************  DALLAS temp. *********************
#include <OneWire.h>
#include <DallasTemperature.h>
#define TEMP_SENSOR_PIN 5
OneWire oneWire(TEMP_SENSOR_PIN);       // Set up a OneWire instance to communicate with OneWire devices
DallasTemperature sensors(&oneWire);    // Create an instance of the temperature sensor class

const int ledPin = 13;                  // Set LED GPIO13  
String ledState;                        // Stores LED state

String yy;
String mm;
String dd;
String hr;
String mi;
String se;

String dataMessage;                     // met gegevens om te loggen
String headerMessage;                   // file header met colom gegevens datum, tijd, tempbi,hum,press,tempbu
String tempbi;                          // van BME
String humidity;                        // van BME
String pressure;                        // van BME
String tempbu;    
String temperature;

long previousMillis = 0;   // tbv display wissel
long interval = 120000;     //  tbv display wissel
 


// *************** BME-280 ***************************
String getTemperature() {               // Variable to store the HTTP request String header;
  float temperature = bme.readTemperature(); 
  Serial.println(temperature);
  return String(temperature);
}
  
String getHumidity() {
  float humidity = bme.readHumidity();
  Serial.println(humidity);
  return String(humidity);
}

String getPressure() {
  float pressure = bme.readPressure()/ 100.0F;
  Serial.println(pressure);
  return String(pressure);
}

//**************** DS18B20 ***************************
String readDSTemperatureC() {           // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
  sensors.requestTemperatures(); 
  delay(20);
 float  tempbu = sensors.getTempCByIndex(0); 
 delay(20);
  Serial.println(tempbu);
  return String(tempbu);
}

//**************** LED  etc.**************************
String processor(const String& var){   // Replaces placeholder with LED state value
  Serial.println(var);
  if(var == "STATE"){                  // var in index.html page (id)
    if(digitalRead(ledPin)){
      ledState = "ON";
    }
    else{
      ledState = "OFF";
    }
    Serial.print(ledState);
    return ledState;
  }
  else if (var == "TEMPERATURE"){       // var in index.html page (id)
    return getTemperature();            // BME-280 temperature binnen
  }
  else if (var == "HUMIDITY"){          // var in index.html page (id)
    return getHumidity();
  }
  else if (var == "PRESSURE"){          // var in index.html page (id)
    return getPressure();
  } 
  else if (var == "TEMPBU"){            // var in index.html page (id)
    return readDSTemperatureC();        // DS18B20 buiten
  }
}

//**************** SET-UP ****************************
 void setup(){
 Serial.begin(115200);
 pinMode(TFT_BACKLIGHT, OUTPUT);
 digitalWrite(TFT_BACKLIGHT, HIGH);     // Backlight on
 pinMode(ledPin, OUTPUT);               //  bool status;
 pinMode(2, OUTPUT);
 SPI.begin();
 sensors.begin();                       // Start up the DS18B20 library
 bme.begin();  
   if (!bme.begin(0x76)) {
      Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }
 initSD();
 startWIFI();
 initTFT();
 startOTA();

  if(!SPIFFS.begin()){                                                    // Initialize SPIFFS
    Serial.println("An Error has occurred while mounting SPIFFS");
    return;
  }

  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){            // Route for root / web page
    request->send(SPIFFS, "/index.html", String(), false, processor);
  });
  
  server.on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest *request){ //  was    /favicon.ico
    request->send(SPIFFS, "/favicon.png", "image/png");
  }); 
  
  server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request){   // Route to load style.css file
    request->send(SPIFFS, "/style.css", "text/css");
  });
 
  server.on("/on", HTTP_GET, [](AsyncWebServerRequest *request){          // Route to set GPIO to HIGH
    digitalWrite(ledPin, HIGH);    
    request->send(SPIFFS, "/index.html", String(), false, processor);
  });
 
  server.on("/off", HTTP_GET, [](AsyncWebServerRequest *request){          // Route to set GPIO to LOW
    digitalWrite(ledPin, LOW);    
    request->send(SPIFFS, "/index.html", String(), false, processor);
  });

  server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){  // Route to the BME Temperature
    request->send_P(200, "text/plain", getTemperature().c_str());
  });
  
  server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){     // Route to the BME Humidity
    request->send_P(200, "text/plain", getHumidity().c_str());
  });
  
  server.on("/pressure", HTTP_GET, [](AsyncWebServerRequest *request){     // Route to the BME Pressure
    request->send_P(200, "text/plain", getPressure().c_str());
  });
 
  server.on("/tempbu", HTTP_GET, [](AsyncWebServerRequest *request){       // Route to the DS18B20 Temperature
    request->send_P(200, "text/plain", readDSTemperatureC().c_str());
   });
  server.begin();                                                          // Start server
  }
 

//****************  LOOP  ****************************
void loop(){
 ArduinoOTA.handle();
  unsigned long currentMillis = millis();

   Serial.println("Contacting Time Server");
   configTime(3600*timezone, daysavetime*3600, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org");
   struct tm tmstruct ;
   delay(200);
    
   tmstruct.tm_year = 0;
   getLocalTime(&tmstruct, 5000);
   Serial.printf("\nNow is : %d-%02d-%02d %02d:%02d:%02d\n",(tmstruct.tm_year)+1900,( tmstruct.tm_mon)+1, tmstruct.tm_mday,tmstruct.tm_hour , tmstruct.tm_min, tmstruct.tm_sec);
   Serial.println("");
      yy = (tmstruct.tm_year)+1900;
      mm = ( tmstruct.tm_mon)+1;
      dd = tmstruct.tm_mday;
      hr = (tmstruct.tm_hour);
      mi = (tmstruct.tm_min);
      se = (tmstruct.tm_sec); 
     
   getReadings();
   delay(20);
   getBME();
   delay(20);
   displayText();
   
      
    String path = "/" + mm + "-" + dd + ".csv";                                   // format maand dag 
    headerMessage = "Tijd, temperature,humidity,pressure,tempbu \n";              // tijd,temperature, humidity, pressure, tempbu
    dataMessage = String(hr) + ":" + String(mi) + ":" + String(se) + "," + String(temperature) + "," + String(humidity) + "," + String(pressure) + "," + String(tempbu)+ "\r\n";  // uur:minuut:sec,temperature, humidity, pressure, tempbu
    File file = SD.open(path.c_str());
     if(!file) {
     Serial.println("File doens't exist");
     Serial.println("Creating file...");
     writeFile(SD, path.c_str(), headerMessage.c_str());
    }
    else {
    Serial.println("File already exists");  
    }
    file.close();
      if (dd != dd) {                   // nieuwe dag
     writeFile(SD, path.c_str(), headerMessage.c_str());
    }
      if (currentMillis - previousMillis > interval) {
       appendFile(SD, path.c_str(), dataMessage.c_str());// SD
       previousMillis = currentMillis;
      }
 
 
  }

//**************** VOIDS *****************************
 
 void startOTA(){
     ArduinoOTA
    .onStart([]() {
      String type;
      if (ArduinoOTA.getCommand() == U_FLASH)
        type = "sketch";
      else                                         // U_SPIFFS
        type = "filesystem";
        Serial.println("Start updating " + type);  // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
    })
    .onEnd([]() {
      Serial.println("\nEnd");
    })
    .onProgress([](unsigned int progress, unsigned int total) {
      Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
    })
    .onError([](ota_error_t error) {
      Serial.printf("Error[%u]: ", error);
      if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
      else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
      else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
      else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
      else if (error == OTA_END_ERROR) Serial.println("End Failed");
    });
    ArduinoOTA.begin();
    Serial.println("Ready");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
 }

 void initTFT(){
     tft.initR(INITR_BLACKTAB);           // initialize a ST7735S chip, black tab
     tft.setTextWrap(false);              // Allow text to run off right edge
     tft.fillScreen(ST77XX_BLACK);
}

void displayText() {
    int x;
    x=random(0,100);
    tft.setRotation(-45);
    tft.fillScreen(ST77XX_BLACK);
    tft.setCursor(0, x);
    tft.setTextColor(ST77XX_RED);
    tft.setTextSize(2);
    tft.print("Temp:");
    tft.setTextColor(ST77XX_YELLOW);
    tft.setTextSize(2);
    tft.println(temperature);
    delay(1500);
    tft.fillScreen(ST77XX_BLACK);
    
    x=random(0,100); 
    tft.setCursor(0,x);
    tft.setTextColor(ST77XX_GREEN);
    tft.setTextSize(2);
    tft.print("Hum :");
    tft.setTextColor(ST77XX_GREEN);
    tft.setTextSize(2);
    tft.println(humidity);
    delay(1500);
    tft.fillScreen(ST77XX_BLACK);
    
    x=random(0,100);
    tft.setCursor(0,x);
    tft.setTextColor(ST77XX_BLUE);
    tft.setTextSize(2);
    tft.print("Pres:");
    tft.setTextColor(ST77XX_BLUE);
    tft.println(pressure);
    delay(1500);
    tft.fillScreen(ST77XX_BLACK); 
    
    x=random(0,100);
    tft.setCursor(0,x);
    tft.setTextColor(ST77XX_RED);
    tft.setTextSize(2);
    tft.print("Tempbu:");
    tft.setTextColor(ST77XX_YELLOW);
    tft.setTextSize(2);
    tft.println(tempbu);
    delay(2500);
    tft.fillScreen(ST77XX_GREEN);
    
    x=random(0,70);
    tft.setCursor(20, x);
    tft.setTextSize(2);
    tft.setTextColor(ST77XX_BLACK);
    tft.println("Datum:");
    tft.println("");
    tft.print(yy);
    tft.print(":");
    tft.print(mm);
    tft.print(":");
    tft.println(dd);
    delay(2500);
    tft.fillScreen(ST77XX_GREEN);

    x=random(0,70);
    tft.setCursor(30, x);
    tft.println("Time:");
    tft.println("");
    tft.print(hr);
    tft.print("-");
    tft.print(mi);
    tft.print("-");
    tft.println(se);
    delay(2500);
    
}

void initSD() {
    SD.begin(2);
    Serial.print("Initializing SD card...");
    if (!SD.begin(2))
     {      
     Serial.println("Card failed, or not present");    // see if the card is present and can be initialized:
     while (1) ;                                       // don't do anything more:  nu mag door ook als er geen kaart is
     }
    Serial.println("card initialized.");
    delay(10);
    Serial.println("\r\n");
  }

void startWIFI() {                                     // Connect to Wi-Fi
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);  {
        while (WiFi.waitForConnectResult() != WL_CONNECTED) {  // while (WiFi.status() != WL_CONNECTED)
        delay(1000);  
        Serial.println("Connecting to WiFi..");
        Serial.println(WiFi.localIP());              // Print ESP32 Local IP Address
        Serial.println("Ready");
        Serial.print("IP address: ");
        Serial.println(WiFi.localIP());
   }
 }
}

void getReadings(){                                    // Function to get DS18B20 temperature
    sensors.requestTemperatures(); 
    delay(30);
    tempbu = sensors.getTempCByIndex(0);               // Temperature in Celsius
    delay(30);
  }
 
void getBME() {                                        // BME-280 readings
    temperature = bme.readTemperature(); 
    delay(20);
    humidity = bme.readHumidity();
    delay(20);
    pressure = bme.readPressure()/ 100.0F;
    delay(20);
  }

void startmDNS() {
    if (!MDNS.begin("esp32")) {
    Serial.println("Error setting up MDNS responder!");
    while(1) {
    delay(100);
    }
 }
    Serial.println("mDNS responder started");
    server.begin();                                  // Start TCP (HTTP) server
    Serial.println("TCP server started");
    MDNS.addService("http", "tcp", 80);              // Add service to MDNS-SD
}

void appendFile(fs::FS &fs, const char * path, const char * message) {  // Append data to the SD card (DON'T MODIFY THIS FUNCTION)
    Serial.println("");
    Serial.printf("Appending to file: %s\n", path);
    File file = fs.open(path, FILE_APPEND);
    if(!file) {
    Serial.println("Failed to open file for appending");
    return;
  }
    if(file.print(message)) {
    Serial.println("Message");
    Serial.print(dataMessage.c_str());
    Serial.println("Appended");
    } else {
    Serial.println("Append failed");
    }
    file.close();
  }

void writeFile(fs::FS &fs, const char * path, const char * message) {  // Write to the SD card (DON'T MODIFY THIS FUNCTION)
    Serial.printf("Writing file: %s\n", path);
    File file = fs.open(path, FILE_WRITE);
    if(!file) {
    Serial.println("Failed to open file for writing");
    return;
    }
    if(file.print(message)) {
    Serial.println("File written");
    } else {
    Serial.println("Write failed");
    }
    file.close();
  }
ever it still bodders me and sorry for your effort.

So my final moment to throw the towel is;

Confusing pin-out.
SD as you told HSPI CS 15, CLK 14, MISO 12, MOSI 13 ok no problem

The TFT: VSPI RST 19, CS 5, D/C 22 (conflict with my sensor on 21 and 22 SCL/SDA) , DIN 23, clk 18

as far as I understand no pins should be used by both.

For now I,am happy.
Thanks .
Regards ilioSS

User avatar
Segmentation Fault
Posts: 22
Joined: Sat Apr 04, 2020 1:49 am

Re: WROVER Dev Kit 4.1 LCD and SD Not Working

Postby Segmentation Fault » Thu May 07, 2020 3:43 pm

Segmentation Fault wrote:
Tue Apr 28, 2020 11:17 pm
Hi ESP_Me-no-dev, thank you for looking into this.

Your advice on both SD and LCD on SPI absolutely makes sense, there should be different names for different SPI buses, duh!!

Doing that helps, but there is still an issue.

My modified code:

Code: Select all

#include <WiFiClient.h>
#include <WiFi.h>
#include <esp_wifi.h>
#include <ESP32Ping.h>
#include <HTTPClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#define FS_NO_GLOBALS
#include <SdFat.h>
#include <sdios.h>
#include <WROVER_KIT_LCD.h>
#include <FreeStack.h>
#include <My_library.h>
#include <SPI.h>
#include <SD.h>


int SERIAL_BAUD_RATE = 1500000;
#define SD_CS 13
#define RGB_LED_RED   0
#define RGB_LED_GREEN 2
#define RGB_LED_BLUE  4


SPIClass SD_SPI(HSPI);
WROVER_KIT_LCD tft; //object responsible for display control
#define USE_SDIO 0
SdFat sd((SPIClass*)&SD_SPI);


// global for card size
uint32_t cardSize;
// global for card erase size
uint32_t eraseSize;
// store error strings in flash
#define sdErrorMsg(msg) sd.errorPrint(F(msg));



void setup()
{
  // SET LEDs
  pinMode(RGB_LED_BLUE, OUTPUT);
  digitalWrite(RGB_LED_BLUE, LOW);
  pinMode(RGB_LED_RED, OUTPUT);
  digitalWrite(RGB_LED_RED, LOW);

  // SET Serial
  Serial.begin(SERIAL_BAUD_RATE);

  // Set SD
  SD_SPI.begin(14, 2, 15/*, SD_CS*/); // The bultin SD card SPI for WROVER
  
  // Initialize SD
  Serial.print("Initializing the SD card... ");
  if (SD.begin(SD_CS, SD_SPI))
  {
    Serial.println("OK!");
    // check for index.htm file
    Serial.print("Checking for index.htm... ");
    if (SD.exists("/index.htm"))
    {
    Serial.println("OK!");
    }
    else
    {
    Serial.println("Failed!");
    }
  }
  else
  {
    Serial.println("Failed!");
  }
  // CHeck sd fat
  Serial.println("Initialising sd FAT:");
  uint32_t t = millis();
  #if USE_SDIO
    if (!sd.cardBegin(SD_CS, SD_SCK_MHZ(10)))
    {
      Serial.print("cardBegin failed in #if USE_SDIO");
      sdErrorMsg("\ncardBegin failed");
    }
  #else  // USE_SDIO
    if (!sd.cardBegin(SD_CS, SD_SCK_MHZ(10)))
    {
      Serial.print("cardBegin failed in #else (of #if USE_SDIO)");
      sdErrorMsg("cardBegin failed");
    }
    else
    {
      if (!sd.fsBegin())
      {
        sdErrorMsg("\nFile System initialization failed.\n");
      }
    }
  #endif  // USE_SDIO 
  t = millis() - t;
  Serial.print("init time: ");
  Serial.print(t); Serial.println("ms");


  // Set LCD
  tft.begin();   
  tft.setRotation(1); // rotate to landscape
  // Write on LCD
  tft.fillScreen(WROVER_BLACK); // paints the entire canvas
  tft.setCursor(0, 0); // position the cursor at the origin
  tft.setTextColor(WROVER_WHITE);
  tft.setTextSize(1); // font size - 1
  tft.println("Chip: ESP32");
  tft.println("Board: ESP-WROVER-KIT V4.1");
  uint64_t chipid = ESP.getEfuseMac();
  tft.printf("Chip ID = %04X", (uint16_t)(chipid>>32));//print High 2 bytes
  tft.printf("%08X",(uint32_t)chipid);//print Low 4bytes.
  tft.println();  
  tft.print("Chip Size: "); tft.println(ESP.getFlashChipSize());
  tft.print("Chip Speed: "); tft.println(ESP.getFlashChipSpeed());
  tft.print("Chip Mode: "); tft.println(ESP.getFlashChipMode());
  tft.print("Running setup and loop on core: "); tft.println(xPortGetCoreID());  
}

void loop ()
{
  delay(1000);
  tft.println(".");
  Check_Serial_income();
}


void Check_Serial_income()
{
  if (Serial.available() > 0)
  {
    String IncomingData = Recieve_serial('\n');
    if (IncomingData == "CHECK_SD_FAT" )
    {  
      Serial.println("Initialising sd FAT:");
      uint32_t t = millis();
      if (!sd.cardBegin(SD_CS, SD_SCK_MHZ(10)))
      {
        Serial.print("cardBegin failed in #else (of #if USE_SDIO)");
        sdErrorMsg("cardBegin failed");
      }
      else
      {
        if (!sd.fsBegin())
        {
          sdErrorMsg("\nFile System initialization failed.\n");
        }
      }
      t = millis() - t;
      Serial.print("init time: ");
      Serial.print(t); Serial.println("ms");
    }
    else if  (IncomingData.substring(0, 8) == "LIST_SD:" )
    {
      String arg_ = IncomingData.substring(8, IncomingData.length());

      if (SD.begin(SD_CS, SD_SPI))
      {
        fs::File dir = SD.open(arg_);
        // return the command received
        Serial.println("LIST_SD:" + arg_);
        if (!dir.isDirectory())
        {
          dir.close();
          Serial.println("NOT DIR");
          Serial.println("---END---");
          return;
        }
        dir.rewindDirectory();

        // return the requested path
        if (arg_ != "/" && arg_.charAt(0) != '/')
        {
          Serial.print("/");
        }

        for (int cnt = 0; true; ++cnt)
        {
          fs::File entry = dir.openNextFile();
          if (!entry)
          {
            break;
          }
          String _name = entry.name();
          if (_name.charAt(0) == '/')
          {
            _name = _name.substring(1, _name.length());
          }
          Serial.print(_name);
          if (cnt > 0 && entry.isDirectory())
          {
            Serial.println("/");
          }
          else
          {
            Serial.println();
          }
          entry.close();
        }
        dir.close();
        Serial.println("---END---");
      }
      else
      {
        Serial.println("SD not found.");
        return;    // init failed
      }
    }
    else if (IncomingData.substring(0, 10) == "WRITE_LCD:")
    {
      String LCD_TEXT = IncomingData.substring(10, IncomingData.length());
      Serial.println("Accepted text for LCD = " + LCD_TEXT);
      tft.print(LCD_TEXT);
    }
    else
    {
      Serial.println("Unknown command:'" + IncomingData + "'" );
      Serial.print("0x: "); 
      for (int i = 0; i < IncomingData.length(); i++)
      {
        Serial.print(IncomingData.charAt(i), HEX); 
        if (i < IncomingData.length() - 1)
        {
          Serial.print("-");
        }
      }
      if (IncomingData.length() > 0)
      {
        Serial.println();
      }
    }
  }
}
The result is SD working normally, but the LCD screen is white.

- Then I tried removing the SD card and rebooting. The LCD is working!!!
- I put back the SD card without rebooting, SD and SdFat working, lcd black but is not printing anything new.
- Removing the SD again, the LCD is working.

But because 1 picture is 0x3E7 words:
Image

So the question is: Is it possible to have the (SPI)LCD and SD working simultaneously?

(I have read that some ppl are suggesting removing R167. Is that recommended? That 0Ω resistor is connecting the CD pin of the SD to the D/C pin of the LCD and then this line is pulled up with a 10k. What are the drawbacks of having the CD pin floating? If R167 is removed and then CD is pulled up to 3V3 from another root would that work or does SD need IO21?)

Bump!

Any news on the matter?

Who is online

Users browsing this forum: No registered users and 28 guests