Explorable with two devices on same SPI

Hi,

Does anyone know if the Explorable Apollo3 can share the default SPI bus with two devices (using each a different Chip Select)?

I’m trying but without success, also selecting and delselecting each device before the other:

...
 digitalWrite(CS_1, HIGH);       //Dev1 SPI OFF
 digitalWrite(CS_2, LOW);       //Dev2 SPI ON
...
 digitalWrite(CS_2, HIGH);       //Dev2 SPI OFF
 digitalWrite(CS_1, LOW);       //Dev1 SPI ON
...

anyway yet isn’t working, only when using one device at time… (phisically disconnected one set of wires of the other device).

I would try to define a second SPI bus but not clear which one IOs can use.

Any suggestion?

Hi,

The short answer is “yes”. But you usually pass the CS pin to whichever library is communicating with each device and let the library toggle the pin for you.

Please tell us more about these two devices:

What are they?

Are they the same?

Which library / libraries are you using to communicate with them?

Can you share the start of your code, where you “begin” SPI and the two devices?

Where does it fail?

Paul

hi,

tnx for the quick reply. I also thought that these commands were implicit and omitted in the normal code…

My setting is the following:

An Explorable stacked on a Dual Log Shield and the two connected to a SparkFun GPS-RTK Dead Reckoning Breakout - ZED-F9R. Also a SparkFun Qwiic OLED Display (128x32) via Qwiic I2C.

Here a skimmed Part of the code (with included libraries) and the setup with the SPI devices.

#include <SparkFun_Qwiic_OLED.h>  //http://librarymanager/All#SparkFun_Qwiic_Graphic_OLED
QwiicNarrowOLED myOLED;
#include <Wire.h>      //Needed for I2C 
#define myWire Wire
#define myWire1 Wire1  // Define which Wire port to use. Change this to Wire1 if you are using the Artemis Thing Plus or the expLoRaBLE
#include <SPI.h>
#define spiPort SPI
//#include <SD.h>     //not compiling on Apollo3
#include <SdFat.h>
#include <SparkFun_Dual-Port_Logging_Shield.h>  //Click here to get the library: http://librarymanager/All#SparkFun_Dual-Port_Logging
sfeDualPortLoggingShield myShield;
#include <SparkFun_u-blox_GNSS_v3.h>  //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS_v3
SFE_UBLOX_GNSS_SPI myGNSS;
#include <RadioLib.h>
#define CONFIG SERIAL_8N1  // a config value from HardwareSerial.h (defaults to SERIAL_8N1)
#define CS_GPS 4
#define CS_SD 24  //A5  // ** On the Artemis Thing Plus: A5 is D24
#define sdWriteSize 2048      // Write data to the SD card in blocks of n*512 bytes
#define fileBufferSize 65530  // Allocate just under 64KBytes of RAM for UBX message storage

SdFat SD;
File myFile;  //File that all GNSS data is written to

void setup() {

  Serial.begin(115200);  // set the baud rate with the begin() method
  pinMode(CS_GPS, OUTPUT);
  pinMode(CS_SD, OUTPUT);
  digitalWrite(CS_GPS, HIGH);  // set the CS of SD Card SPI to high (to force it in case of a reset)
  digitalWrite(CS_SD, HIGH);   //

  // Initialize SPI
  //SPI.begin();  
  spiPort.begin();
  // Do a fake transaction to initialize the SPI pins
  spiPort.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
  spiPort.transfer(0);
  spiPort.endTransaction();

  myWire.begin();   // Start I2C
  myWire1.begin();  // Start I2C

  // Initalize the OLED device and related graphics system
  if (myOLED.begin() == false) {
    Serial.println("OLED Device begin failed. Freezing...");
    while (true)
      ;
  }

//GPS Init
  myGNSS.setFileBufferSize(fileBufferSize);  // setFileBufferSize must be called _before_ .begin

  // Connect to the u-blox module using SPI port, csPin and speed setting
  bool begun = false;
  do {
    begun = myGNSS.begin(spiPort, CS_GPS, 4000000);
    if (!begun) {
      Serial.println("u-blox GNSS not detected on SPI bus.");
    }
  } while (!begun);
  // GPS Initialized
  //more GPS settings command omitted..

//SD Init
  bool success = myShield.begin(0x51, myWire1);  // Use a custom I2C address and/or port

  if (!success) {
    Serial.println(F("An error has occurred! Could not communicate with the SD Shield!"));
    //Serial.println(F("Please try powering the board off and on again..."));
    while (1)
      ;  // Do nothing more
  }
  // Wake the shield and put it into Thing Plus / Arduino (SPI) mode
  Serial.println("Putting the SD shield into SPI (Thing Plus / Arduino) mode");
  bool result = myShield.spiMode();
  if (!result) {
    //Serial.println("An error has occurred! Could not communicate with the Shield! Freezing...");
    while (1)
      ;
  }
  delay(1000);  // Let the shield start up - it takes a full second

  //Serial.println("Initializing SD card...");
  //if (!SD.begin(spiPort, CS_SD, 1000000)){
  if (!SD.begin(CS_SD)) {
    Serial.println("microSD card initialization failed! Freezing...");
    while (1)
      ;
  }
    // SD Initialized
}

The code compiles, is just that at the part of the second SPI device doesn’t communicate properly. It fails at the SD initialization, if I use a code without the GPS it still fails, until I disconnect the SPI wires of the GPS…

Hi Dan,

Just FYI, SPI devices use one of four modes for data transfer. The mode sets the clock polarity and edges. u-blox GNSS use MODE0, MSBFIRST. You’re OK because the v3 GNSS library automatically (re)sets the mode for each transfer. Not all libraries do that. It’s just something to watch out for when using multiple SPI devices - which may use different modes.

You need to tell SdFat that it doesn’t have exclusive access to the SPI bus. Please try:

if (!SD.begin(SdSpiConfig(CS_SD, SHARED_SPI, SD_SCK_MHZ(8))))

If you want to use larger SD cards (FAT16, FAT32, exFAT), tell SdFat to use:

SdFs SD;

FsFile myFile;

I hope this helps,

Paul

Hi Paul,

with this new SD begin command the setup works!

Still have to check other parameters in the generated file but at least now I have something.

Thank you

Dan