Issue accessing 2 SPI devices on separate busses on ESP32

I am using LilyGo LoRa module (LoRa32 V2.1_1.6 – LILYGO®) with LoRa, OLED & micro SD slot. As per the documentation, it uses 2 separate SPI busses for both LoRa & SD card (OLED is on I2C).
I am having issue while using both the LoRa & SD card at the same time. If I split my program in 2 separate programs - one just for SD card & the other just for LoRa - it works exactly as expected. However if I combine the code then the LoRa works but SD card doesn't.

Combined code that doesn't work:

#include "SPI.h"
#include "LoRa.h"
#include "FS.h"
#include "SD.h"

#define LORASCK 5  
#define LORAMISO 19
#define LORAMOSI 27
#define LORASS 18 
#define LORARST 23
#define LORADI0 26
#define LoRaSyncWord 0xAE
#define SDCardCS 13
#define SDCardMOSI 15
#define SDCardMISO 2
#define SDCardSCK 14
#define BAND 915E6
SPIClass hspi(HSPI);
SPIClass myvspi(VSPI);
String lorastring = "";
bool packetreceived = false;
bool sdcardavailable = false;
int x = 0;
bool firstboot=true;

void setup() 
{
  Serial.begin(115200);
  LoRa.setPins(LORASS, LORARST, LORADI0);
  hspi.begin(LORASCK, LORAMISO, LORAMOSI, LORASS);
  myvspi.begin(SDCardSCK, SDCardMISO, SDCardMOSI, SDCardCS);
  if (SD.begin(SDCardCS, myvspi, 80000000)) 
  {
     Serial.println("SPI bus initiated");
     sdcardavailable = true;
     uint8_t cardType = SD.cardType();

     if (cardType == CARD_NONE) 
     {
        sdcardavailable = false;
        Serial.printf("No SD card inserted.\n Data will not be stored on the card.\n");
     }

     if (sdcardavailable == true) 
     {
         Serial.print("Card type detected: ");
         if (cardType == CARD_MMC) 
         {
            Serial.println("MMC");
         } 
         else if (cardType == CARD_SD) 
         {
            Serial.println("SDSC");
         } 
         else if (cardType == CARD_SDHC) 
         {
            Serial.println("SDHC");
         }
         uint64_t cardSize = SD.cardSize() / (1024 * 1024);
         Serial.printf("SD Card Size: %lluMB\n", cardSize);
     }
 } 
 else 
 {
   Serial.println("Unable to open SPI bus...");
 }

   if (!LoRa.begin(BAND)) 
  {
    Serial.println("LoRa not initialised...");
    while (true)
      ;
  }
  LoRa.setSyncWord(LoRaSyncWord);
  Serial.println("LoRa Initializing OK!");
}

void loop() 
{
  parslorapacket();
  if (sdcardavailable == true) 
  {
    writeData(SD, "/logfile1.txt", "Header line");
    readFile(SD, "/logfile1.txt");
  }
}

void parslorapacket()
{
  int packetSize = LoRa.parsePacket();
  if (packetSize)
  {
    lorastring = "";
    while (LoRa.available()) 
    {
      Serial.print("LoRa packet received is: ");
      lorastring = LoRa.readString();
    }
    Serial.print(lorastring);
  }
}
void writeData(fs::FS &fs, const char * path, const char * message) 
{
  if (firstboot == true)
  {
    if (fs.remove("/logfile1.txt")) 
    {
      Serial.printf("File /logfile1.txt deleted\n");
    }

    File file = fs.open(path, FILE_APPEND);
    if(file.println(message)) 
    {
      Serial.println("logfile1.txt created.");
    } 
    else 
    {
      Serial.println("Couldn't create logfile1.txt file.");
    }
   firstboot=false;
  }

  File file = fs.open(path, FILE_APPEND);
  x++;
  if(file.println(x)) 
    {
      Serial.println("/logfile1.txt appended.");
      delay(1000);
    } 
    else 
    {
      Serial.println("Couldn't append /logfile1.txt file.");
    }
  file.close();
}

void readFile(fs::FS &fs, const char * path) 
{
  Serial.printf("Reading file: /logfile1.txt\n");

  File file = fs.open(path);
  if (!file) {
    Serial.println("Failed to open file for reading");
    return;
  }

  Serial.print("Read from file: ");
  while (file.available()) {
    Serial.write(file.read());
  }
  file.close();
}

Log of the above code:

ets Jun 8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x1b (SPI_FAST_FLASH_BOOT)
configsip: 188777542, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1184
load:0x40078000,len:13260
load:0x40080400,len:3028
entry 0x400805e4
SPI bus initiated
Card type detected: SDSC
SD Card Size: 486MB
LoRa Initializing OK!
Couldn't create logfile1.txt file.
Couldn't append /logfile1.txt file.
Reading file: /logfile1.txt
Failed to open file for reading
Couldn't append /logfile1.txt file.

Just the LoRa code:

#include "SPI.h"
#include "LoRa.h"

#define LORASCK 5  
#define LORAMISO 19
#define LORAMOSI 27
#define LORASS 18 
#define LORARST 23
#define LORADI0 26
#define LoRaSyncWord 0xAE
#define BAND 915E6
SPIClass hspi(HSPI);
String lorastring = "";
bool packetreceived = false;

void setup() 
{
  Serial.begin(115200);
  LoRa.setPins(LORASS, LORARST, LORADI0);
  hspi.begin(LORASCK, LORAMISO, LORAMOSI, LORASS);

   if (!LoRa.begin(BAND)) 
  {
    Serial.println("LoRa not initialised...");
    while (true)
      ;
  }
  LoRa.setSyncWord(LoRaSyncWord);
  Serial.println("LoRa Initializing OK!");
}

void loop() 
{
  parslorapacket();
}

void parslorapacket()
{
  int packetSize = LoRa.parsePacket();
  if (packetSize)
  {
    lorastring = "";
    while (LoRa.available()) 
    {
      Serial.print("LoRa packet received is: ");
      lorastring = LoRa.readString();
    }
    Serial.print(lorastring);
  }
}

Log of the LoRa code:

ets Jun 8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 188777542, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1184
load:0x40078000,len:13260
load:0x40080400,len:3028
entry 0x400805e4
LoRa Initializing OK!
LoRa packet received is: 0,0.0000000,0.0000000,0.00,15:9:28,0.00
LoRa packet received is: 0,0.0000000,0.0000000,0.00,15:9:29,0.00
LoRa packet received is: 0,0.0000000,0.0000000,0.00,15:9:30,0.00
LoRa packet received is: 0,0.0000000,0.0000000,0.00,15:9:31,0.00
LoRa packet received is: 0,0.0000000,0.0000000,0.00,15:9:33,0.00
LoRa packet received is: 0,0.0000000,0.0000000,0.00,15:9:34,0.00
LoRa packet received is: 0,0.0000000,0.0000000,0.00,15:9:35,0.00
LoRa packet received is: 0,0.0000000,0.0000000,0.00,15:9:36,0.00

Just the SD card code:

#include "SPI.h"
#include "FS.h"
#include "SD.h"

#define SDCardCS 13
#define SDCardMOSI 15
#define SDCardMISO 2
#define SDCardSCK 14
SPIClass myvspi(VSPI);
bool sdcardavailable = false;
int x = 0;
bool firstboot=true;

void setup() 
{
  Serial.begin(115200);
  myvspi.begin(SDCardSCK, SDCardMISO, SDCardMOSI, SDCardCS);
  if (SD.begin(SDCardCS, myvspi, 80000000)) 
  {
     Serial.println("SPI bus initiated");
     sdcardavailable = true;
     uint8_t cardType = SD.cardType();

     if (cardType == CARD_NONE) 
     {
        sdcardavailable = false;
        Serial.printf("No SD card inserted.\n Data will not be stored on the card.\n");
     }

     if (sdcardavailable == true) 
     {
         Serial.print("Card type detected: ");
         if (cardType == CARD_MMC) 
         {
            Serial.println("MMC");
         } 
         else if (cardType == CARD_SD) 
         {
            Serial.println("SDSC");
         } 
         else if (cardType == CARD_SDHC) 
         {
            Serial.println("SDHC");
         }
         uint64_t cardSize = SD.cardSize() / (1024 * 1024);
         Serial.printf("SD Card Size: %lluMB\n", cardSize);
     }
 } 
 else 
 {
   Serial.println("Unable to open SPI bus...");
 }
}

void loop() 
{
  if (sdcardavailable == true) 
  {
    writeData(SD, "/logfile1.txt", "Header line");
    readFile(SD, "/logfile1.txt");
  }
}

void writeData(fs::FS &fs, const char * path, const char * message) 
{
  if (firstboot == true)
  {
    if (fs.remove("/logfile1.txt")) 
    {
      Serial.printf("File /logfile1.txt deleted\n");
    }

    File file = fs.open(path, FILE_APPEND);
    if(file.println(message)) 
    {
      Serial.println("logfile1.txt created.");
    } 
    else 
    {
      Serial.println("Couldn't create logfile1.txt file.");
    }
   firstboot=false;
  }

  File file = fs.open(path, FILE_APPEND);
  x++;
  if(file.println(x)) 
    {
      Serial.println("/logfile1.txt appended.");
      delay(1000);
    } 
    else 
    {
      Serial.println("Couldn't append /logfile1.txt file.");
    }
  file.close();
}

void readFile(fs::FS &fs, const char * path) 
{
  Serial.printf("Reading file: /logfile1.txt\n");

  File file = fs.open(path);
  if (!file) {
    Serial.println("Failed to open file for reading");
    return;
  }

  Serial.print("Read from file: ");
  while (file.available()) {
    Serial.write(file.read());
  }
  file.close();
}

Log of the SD card code:

ets Jun 8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 188777542, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1184
load:0x40078000,len:13260
load:0x40080400,len:3028
entry 0x400805e4
SPI bus initiated
Card type detected: SDSC
SD Card Size: 486MB
File /logfile1.txt deleted
logfile1.txt created.
/logfile1.txt appended.
Reading file: /logfile1.txt
Read from file: Header line
1
/logfile1.txt appended.
Reading file: /logfile1.txt
Read from file: Header line
1
2
/logfile1.txt appended.
Reading file: /logfile1.txt
Read from file: Header line
1
2
3
/logfile1.txt appended.
Reading file: /logfile1.txt
Read from file: Header line
1
2
3
4

As you can see, when run separately, the code works as expected. However when run together, it is giving error while writing the file to SD card.
Can some expert out there help understand what the problem is?

there are problems with common SD card readers using SPI bus with other devices - have a look at ESP32 reference sdspi_share

connect the SD card to the VSPI interface (pins 23 MOSI 19 MISO 18 CLK and 5 CS) and LoRa to the HSPI interface
have a look at post connecting-sd-card-and-bmp280-via-spi-interface

Just use;

SPI.begin(LORASCK, LORAMISO, LORAMOSI, LORASS);
hspi.begin(SDCardSCK, SDCardMISO, SDCardMOSI, SDCardCS);
if (SD.begin(SDCardCS, hspi, 80000000))

And comment out the VSPI definition;

//SPIClass myvspi(VSPI);


The above changes tested and working, with the sam pin definitions, on a LilyGo T3 V1.6.1 ESP32 SX1278.

`#define LoRaSyncWord 0xAE`

Dont change the syncword, best to stick to the standard ones. 

Syncwords other than the standard 0x12 and 0x34 ones may not work, can be leaky, or can result in reduced sensitivity when receiving packets.
1 Like
  1. the SPI object is defined as SPIClass SPI(VSPI);
  2. default VSPI pins are 18, 19, 23, 5
  3. default HSPI pins are 12, 13, 14, 15

you use the pin sets swapped between VSPI and HSPI. it should work, but why?

@horace OP doesn't have the SD card on a same SPI and uses VSPI for the SD card even on different pins. your post is confusing.

Or for a simpler change just do this;

  LoRa.setSPI(hspi);

   if (!LoRa.begin(BAND)) 
  {

If you dont use LoRa.setSPI() the LoRa library will use the default SPI interface, which will be vspi.

Hi @horace
Thanks for your response. Unfortunately the LoRa & SD card is hard wired on the module & are not external that I can re-pin to any other pins.
Thanks

Hi @srnet
Thanks for your reply, & yes, the changes you have suggested have worked.
Thanks for helping out.
Are you able to help me understand what the problem was?
Also regarding the sync word - can you share some links with details around it?
Thanks again.

Hi @Juraj
Thanks for your reply. I am not sure about the default HSPI & VSPI pins, but defined based on the pin diagram based on the product page & also as per the product page the SDCardMISO is on pin 2.
Thanks.

See post #5

Never seen a full explanation of what is OK and what is not from Semtech, although they have been asked often enough. One thing is for sure, they (syncwords) dont work in the simple way you might expect from the datasheet.

@srnet
Thanks.

so if LORA is on default pins for the SPI library, you don't need to set anything regarding SPI for LORA. it will use the SPI library on the pins where you have the LORA module.

use HSPI for the SD card. the SD holder is on default HSPI pins so you don't have to configure the pins.

hspi.begin();
if (SD.begin(SDCardCS, hspi, 80000000)) 
1 Like