Lolin Wemos D1 R1 + PCF8574 + TFT 2.4 (SPI) + SD module

Good afternoon. Help me figure out how the SD card works. There is a Lolin Wemos D1 R1 + PCF8574 + TFT 2.4 (SPI) + SD module. (I tried using the built-in TFT SD module. The result is the same).

#include <SPI.h>
#include <SD.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <PCF8574.h>
#include <Wire.h>

#define BLACK       0x0000      //   0,   0,   0 
#define NAVY        0x000F      //   0,   0, 128 
#define DARKGREEN   0x03E0      //   0, 128,   0 
#define DARKCYAN    0x03EF      //   0, 128, 128 
#define MAROON      0x7800      // 128,   0,   0 
#define PURPLE      0x780F      // 128,   0, 128 
#define OLIVE       0x7BE0      // 128, 128,   0 
#define LIGHTGREY   0xC618      // 192, 192, 192 
#define DARKGREY    0x2945      // 128, 128, 128 
#define BLUE        0x001F      //   0,   0, 255 
#define GREEN       0x07E0      //   0, 255,   0 
#define DEEPGREEN   0x0C81      //   0, 255,   0 
#define CYAN        0x07FF      //   0, 255, 255 
#define RED         0xF800      // 255,   0,   0 
#define MAGENTA     0xF81F      // 255,   0, 255 
#define YELLOW      0xFFE0      // 255, 255,   0 
#define WHITE       0xFFFF      // 255, 255, 255 
#define ORANGE      0xFD20      // 255, 165,   0 
#define GREENYELLOW 0xAFE5      // 173, 255,  47 
#define PINK        0xF81F
#define DEEPBLUE    0x0007
#define GREY        0x4A89

PCF8574 pcf8574(0x25);

#define TFT_CS 10
#define TFT_DC D8 
#define TFT_RST D9 

extern  unsigned char  OnOff[];
extern  unsigned char  WiFiLogo[];
extern  unsigned char  ClockLogo[];

#define SD_CS_PIN  8;
File myFile;

Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

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

  tft.init(240, 320, SPI_MODE2); 
  tft.setRotation(1); 
  tft.invertDisplay(false);
  tft.fillScreen(ST77XX_BLACK);
  tft.setCursor(0, 0); tft.setTextSize(2); tft.setTextColor(CYAN); 

  
  
  if ( !pcf8574.begin() ) 
    { 
       tft.setCursor(50, 60); tft.setTextColor(CYAN); 
       tft.setTextSize(2); tft.print ("PCF module - OK"); 
       for (int i = 0; i<=7; i++) pcf8574.pinMode(i, OUTPUT);     
       pcf8574.digitalWrite(P0, HIGH);
       pcf8574.digitalWrite(P1, HIGH);
       pcf8574.digitalWrite(P2, LOW); 
       pcf8574.digitalWrite(P3, LOW); 
       pcf8574.digitalWrite(P4, HIGH);
       pcf8574.digitalWrite(P5, HIGH);
       pcf8574.digitalWrite(P6, HIGH);
       pcf8574.digitalWrite(P7, HIGH);
    }
  else   
    { tft.setCursor(50, 60); tft.setTextColor(RED); tft.setTextSize(2); tft.print("PCF module - Fail"); }         
  
 
  if ( !SD.begin(2) ) 
    {
       tft.setCursor(50, 85); tft.setTextColor(RED); tft.setTextSize(2); tft.print("SD-card    - Fail"); 
    }
  else 
    {
       tft.setCursor(50, 85); tft.setTextColor(CYAN); tft.setTextSize(2); tft.print("SD-card    - OK"); 
    }       
}

void loop ()
{
}

Free pins on D1R1 from 0 to 6, D11 and D12. In SD.begin (?) instead of ? I've tried them all.
Always a white screen. As soon as I turn off the initialization of the SD module, everything is displayed on the TFT. Please explain why this is happening.

Or, for example, I connect the CS SD module to D6, the TFT is working and the card is not initialized and WEMOS is restarted at intervals of 5-7 seconds. By myself.

P.S. I don't know technical English well, so I use a translator. Who could translate something wrong.

Always start with known-good examples for your hardware:

D1_mini_Examples/ReadWrite.ino at master · wemos/D1_mini_Examples · GitHub

I probably explained it wrong. The SD module works separately. Separately, TFT + PCF8574 works, but together SD + TFT + PCF8574 do not work. When changing the CS pin, SD.begin(CS) TFT then shows nothing (white screen) then shows, but SD.begin (CS) returns an error.

I guess the TFT is also an SPI device, you may need to manually switch the EN pin of both the tft & SD.
basically, before you do anything with the SD card (intialize/ read / write) start out with

digitalWrite(TFT_CS, HIGH);
SD.begin(SD_CS);

and when finished with the writing or reading manually switch the SD_CS & turn the tft back on

digitalWrite(SD_CS, HIGH);
digitalWrite(TFT_CS, LOW);

These 2 together can serve as the init function

bool StartSD() {
  digitalWrite(TFT_CS, HIGH);  // disable the tft
  bool init = SD.begin(SD_CS);  // enable the SD (in any other function you would use digitalWrite(SD_CS, LOW);
  digitalWrite(SD_CS, HIGH);  // disable the SD
  digitalWrite(TFT_CS, LOW); // enable the tft
  return init;
}

so you can call it like this

if ( !StartSD() ) 

Just understand that both devices use the same SPI pins, so you need to make sure that only 1 of them is switched on at a time, and that you are not executing functions on a device that is disabled.

One would say that an SPI library should take care of it for you, and i really think it should just switch the CS pin on and off again (for an SD library that is always just waiting for commands this seems logical) But alas this is not the case, so you have to do it manually.

The problem is probably the SD module - if it's a microSD. The standard microSD module does not release the MISO line when it is NOT selected by CS. So it interferes with the other SPI device. It works fine if it's the only SPI device, but does not play well with others.

If your module has a 3.3V regulator and a voltage translator chip, then that's probably the explanation. The translator output for MISO is always active, and doesn't go tristate when CS is released. The answer is to bypass the translator gate for that line, so the SD card speaks directly to the D1. The card itself will behave properly.

And if your module isn't like that, well, nevermind.

So, it doesn't work.
Let me tell you everything in detail.
Maybe I'm confused about something?
Photo TFT with built-in SD module,
a third-party SD module
and the Wemos D1 R1 itself are in the photo.

How to connect:
TFT_CS -> D10
MOSI_TFT -> MOSI_SD -> D11
MISO_TFT -> MISO_SD -> D12
SCK_TFT -> SCK_SD -> D13
DC_TFT -> D8
RES_TFT ->D9
SD_CS -> D2

In the quality of SD_CS I tried all pins from D0 to D7
The result is Fail.

The sketch with your corrections is given below.

#include <SPI.h>
#include <SD.h>

#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

#include <PCF8574.h>

#include <Wire.h>

#define BLACK       0x0000      //   0,   0,   0 
#define NAVY        0x000F      //   0,   0, 128 
#define DARKGREEN   0x03E0      //   0, 128,   0 
#define DARKCYAN    0x03EF      //   0, 128, 128 
#define MAROON      0x7800      // 128,   0,   0 
#define PURPLE      0x780F      // 128,   0, 128 
#define OLIVE       0x7BE0      // 128, 128,   0 
#define LIGHTGREY   0xC618      // 192, 192, 192 
#define DARKGREY    0x2945      // 128, 128, 128 
#define BLUE        0x001F      //   0,   0, 255 
#define GREEN       0x07E0      //   0, 255,   0 
#define DEEPGREEN   0x0C81      //   0, 255,   0 
#define CYAN        0x07FF      //   0, 255, 255 
#define RED         0xF800      // 255,   0,   0 
#define MAGENTA     0xF81F      // 255,   0, 255 
#define YELLOW      0xFFE0      // 255, 255,   0 
#define WHITE       0xFFFF      // 255, 255, 255 
#define ORANGE      0xFD20      // 255, 165,   0 
#define GREENYELLOW 0xAFE5      // 173, 255,  47 
#define PINK        0xF81F
#define DEEPBLUE    0x0007
#define GREY        0x4A89

String header;

PCF8574 pcf8574(0x25);

#define TFT_CS D10
#define TFT_DC D8 
#define TFT_RST D9 
#define SD_CS  D2


extern  unsigned char  OnOff[];
extern  unsigned char  WiFiLogo[];
extern  unsigned char  ClockLogo[];

int Num = 1; 
int CirclePosition = 0;

unsigned long currentTime = millis();
unsigned long previousTime = 0; 
const long timeoutTime = 2000;
int thisByte = 33;

File myFile;

Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

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


  tft.init(240, 320, SPI_MODE2); // Init ST7789 240x240
  tft.setRotation(1); tft.invertDisplay(false);
  tft.fillScreen(ST77XX_BLACK);
  tft.setCursor(0, 0); tft.setTextSize(2); tft.setTextColor(CYAN); 

  tft.setCursor(75, 31); tft.setTextColor(BLUE); tft.setTextSize(2); tft.print("HELLO");
  
  if ( !pcf8574.begin() ) 
    { 
       tft.setCursor(50, 60); tft.setTextColor(CYAN); 
       tft.setTextSize(2); tft.print ("PCF module - OK"); 
       for (int i = 0; i<=7; i++) pcf8574.pinMode(i, OUTPUT);     
       pcf8574.digitalWrite(P0, HIGH);   
       pcf8574.digitalWrite(P1, LOW); 
       pcf8574.digitalWrite(P2, LOW);  
       pcf8574.digitalWrite(P3, LOW);   
       pcf8574.digitalWrite(P4, LOW); 
       pcf8574.digitalWrite(P5, LOW);  
       pcf8574.digitalWrite(P6, LOW);   
       pcf8574.digitalWrite(P7, HIGH);   
    }
  else   
    { tft.setCursor(50, 60); tft.setTextColor(RED); tft.setTextSize(2); tft.print("PCF module - Fail"); }         
  

  digitalWrite (10, HIGH);  // disable the tft
  digitalWrite (SD_CS, LOW); 
 
 bool init = true;
  init = SD.begin(SD_CS); 

  digitalWrite(SD_CS, HIGH);  // disable the SD
  digitalWrite(10, LOW); // enable the tft

  if ( init == false ) 
    {  tft.setCursor(50, 85); tft.setTextColor(RED); tft.setTextSize(2); tft.print("SD-card    - Fail");   }
  else 
    {  tft.setCursor(50, 85); tft.setTextColor(CYAN); tft.setTextSize(2); tft.print("SD-card    - OK");    }


  tft.setCursor(50, 110); tft.setTextColor(CYAN); tft.setTextSize(2); tft.print(init); 
  
 
  myFile = SD.open("config.txt", FILE_WRITE);
  myFile.close();
}

You can not do this unless you disable the tft & enable the SD.
That is why i said you should make functions for all operations relating to the SD card, i gave the example for the initialization, can you confirm that that works (maybe by adding a delay after the prints to the tft ? )

Yes, it is clear that for any operations it is necessary to do LOW and HIGH for TFT_CS pin. I still didn't understand why it didn't work, I pulled the TFT out of the breadboard, it lay on my desk, then put it back into the breadboard, set delay (1000) after SD.begin and everything worked. Thank you all for your help.

1 Like

and the SD_CS pin ! (SD.begin() does that once for you, but after that you have to do it manually)

Yes, and that's for sure

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