Two SPI devices not working together

Hi guys, I am currently making a project which I need to storage data from a sensor in a SD card and also print it on a TFT. When I inicializate the SD module, the TFT library loses the SPI communication. I’ve tried using the function SPI.endtrasaction() but I did not work. This is the code:


#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <SPI.h>
#include <Wire.h>
#include <SD.h>
#include <Adafruit_ILI9341.h>

//Pins SPI
#define SCK 13
#define MISO 12
#define MOSI 11

//TFT
#define TFT_DC 9
const int TFT_SS = 10;
#define TFT_RST 8


Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_SS, TFT_DC, MOSI, SCK, TFT_RST ,MISO);

#define BLUE ILI9341_BLUE
#define RED ILI9341_RED
#define BLACK ILI9341_BLACK
#define WHITE ILI9341_WHITE
#define YELLOW ILI9341_YELLOW
#define CYAN ILI9341_CYAN

//Tarjeta SD
const int SD_SS = 7;
File archivo;

void setup() {
  Serial.begin(9600);
  tft.begin();
  tft.fillScreen(BLACK  );
  pinMode(SD_SS, OUTPUT);
  pinMode(TFT_SS, OUTPUT);
  tft.setRotation(1);
  
  digitalWrite(TFT_SS, HIGH);
  digitalWrite(SD_SS, LOW);
  
  if (!SD.begin(SD_SS)){
    Serial.println("Fallo de conexion");
  }
  else{
    archivo = SD.open("Datos.txt", FILE_WRITE);
    Serial.println("Inicializacion correcta!");
  }
  
  digitalWrite(TFT_SS, LOW);
  digitalWrite(SD_SS, HIGH);
  SPI.endTransaction();
  
  tft.fillScreen(RED);
  tft.fillScreen(BLACK);
}


void loop() { 

tft.fillScreen(CYAN);

}

Any advice?

Show the forum a schematic and say which Arduino you are using.

There are SD modules that don’t tristate correctly.

Like here Arduino - hacking a micro SD card reader data logger to connect with another SPI device nRF24L01 - YouTube

@gianfender, your topic was moved to a more appropriate section of the forum.

Can you edit your post, select all code and click the < / > button in the toolbar above the text box.

+1 for @Whandall suggestion. SD card adapter modules are almost always the culprit when used with another SPI device and the comms don’t work. Unless you know what to look for, it’s frustrating when each device works correctly on its own but not together.

Often the problem with the SD module is that they use a level shifter chip because the SD Card runs on 3.3V and the Arduino runs on 5V. If the level shifter isn’t done right, it will be driving the MISO (Master In / Slave Out) pin even when the Slave Select line is HIGH. It might work if you disconnect the MISO pin from the level shifter and connect it directly to the Data Out pin of the SD socket. The 3.3V output from the SD card is high enough to read properly on a 5V input.

@gianfender needs to be aware that the ILI9341 display is a 3.3V device, so solutions to problems will likely depend on the Arduino in use.

I am using Arduino UNO, and for my TFT display I’ve used a logic converter from 5V to 3.3V. But as I know the SD card works with 5V. I would try what @Whandall says. And @johnwasser I did not use a level shifter for the SD module, What do you mean?

Does the SD module have any chips on it? If so, that is probably used as a level shifter.

I have a similar project and had to completely shut down the SPI connection the SD card and then open one to the TFT and visa versa.

Okey guys, I have already tried to connect the MISO pin directly as it shows in the video, but It does not work? What could it be?

What did you do to shut it down @drmpf ?

I was using an ESP32, and for the TFT I used the code below (similar code for the SD)
(but on UNO, end() in the SPI class does nothing :frowning: )

Other things I did were, added 10k pullups to the SD SPI lines, add 47uF - 100uF low ESR cap directly across the SD board Vcc-GND.
Also as noted above make sure you handle the 5V to 3v3 transition.

// only runs once
void initTFT() {
  if (TFT_initialized) {
    return;
  }
  TFT_initialized = true;
  tftScreen.begin();
  tftScreen.setTextWrap(false); // set no wrap
  tftScreen.setRotation(3);
  TFT_started = true;
}

void stopTFT() {
  if (TFT_started) {
    tftScreen.stop(); // checks running
  }
}

void restartTFT() {
  if (TFT_started) {
    tftScreen.restart(); // checks running
  }
}

Then added the code like

bool Adafruit_SPITFT::isRunning() {
  return spiRunning;
}

void Adafruit_SPITFT::stop() {
	if (spiRunning) {
	  spiRunning = false;
      digitalWrite(_cs, HIGH); // Deselect
	  hwspi._spi->end();
	}
}
void Adafruit_SPITFT::restart() {
	if (!spiRunning) {
	  spiRunning = true;
      digitalWrite(_cs, HIGH); // Deselect
	  hwspi._spi->begin(_sck, _miso, _mosi, _cs);
	}
}

The Adafruit micro SD module has a level shifter, but the MISO line bypasses the level shifter so should work on the bus. See the schematic. I made my own module following that schematic and it works well alongside a rf24 radio module.

I have struggled with the same problem, namely connecting a SD-card reader and a NRF24L01 to an ESP32 through SPI, simultaneously. I have done a thorough web research. Here are my insights and my amazingly simple solution to the problem:

root course:

The SD card reader is using a 3.3V to 5 V level shifter. However, there is a flaw in the circuit, unfortunately: the level shifter does NOT enter tri-state, when the circuit is disabled through the CS (chip select) line. This leads to the situation, that the NRF24L01 cannot send data over the MISO line, as this line is either HIGH or LOW, depending of what the SD-card reader is sending.

The reference for this insight is this: SOLVED. Nrf24 (Mirf lib) + Micro SD-card works OK together

solution

The hardware bug of the SD-card reader board can be fixed directly. Please refer to the above link. But I found this fix very delicate and decided to look for an alternative approach.

I came across two approaches:

  1. the proper way of fixing this would be to put a tri-state driver in the MISO line leaving the SD-card-reader. The chip would be 74HC125. The enable pin of the driver would be connected with the chip select line of the SD-card reader (connect both the enable pin of the SD-card reader and the enable pin of the driver with the chip select line from your Arduino). I have not tried this out, but I am very sure it would work.

  2. as I did not have a 74HC125 on hand, I used this simple approach instead:

  • connect the MISO-output of the NRF24L01 directly with the MISO input of the Arduino.
  • connect the MISO-output of the SD-card reader through a 4.7k resistor with the Arduino.

The effect is the following:

  • if the nrF24L01 is enabled, the nrf24L01 MISO signal is leading, regardless of the output of the SD-card MISO. The worst that can happen is a few hundred µA current through the resistor. However, the potential at the Arduino input is not distorted very much.

  • if the nrf24L01 is disabled, it's MISO-output if tri-state, which means, it has a high resistance. Therefore, the MISO-signal of the SD-card reader reaches the Arduino through the resistor, without much loss of voltage.

I hope this fix helps.

Best regards

Ludwig

Very interesting. Thanks for that info.
In my case I was using a 'bare' SD card holder without any level shifters, since it was talking to the ESP32 at 3V3.
This Adafruit SD Card break out board comes without level shifters but with pullups and a small power cap.

Thats what I do as well, there are micro SD boards available that have no electronics, so there is nothing to fix, or just use the bare holders.

For 3.3V Arduinos its much easier to use the appropriate SD breakout board than 'fix' the ones that are not intended for 3.3V operation.

As for the pullups, then from what I have researched your supposed to fit them on the normally unused DAT1 and DAT2 pins.

In my experience the microSD cards work just fine without the pull ups, maybe some microSD cards have them internally ?

Hi, I did this, but the sd card cannot connect to the arduino, it can't initialize

Okey guys, I have tried everything, beggining with bypassing the miso lines directly to arduino from the sd card reader, and also I tried using a 4k7 resistor between SD miso line and arduino, and I cannot make it work. Any ideas?

gianfender, I am not sure I understand your setup. Can you send a drawing? What kind of SD card reader are you using? What type of display?

You need to narrow down the problem. Do you have a software problem or do you have a hardware problem? A way to find out might be this;

If you disconnect the SD card-reader, does the display work? If you disconnect the display, does the SD-card reader work?