Adafruit multiple SPI devices interfering with eachother

I am using an Adafruit H3LIS331 high-range accelerometer and LSM9DS1 mid-range IMU over SPI. I was hoping to save myself some work by using the Adafuit Arduino libraries but they seem to be interfering with one another. They work individually but misbehave when connected. Here is my code:

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_H3LIS331.h>
#include <Adafruit_LSM9DS1.h>
#include <Adafruit_Sensor.h>

// Used for software SPI
#define SCK 76
#define MISO 74
#define MOSI 75
// Used for hardware & software SPI
#define H3LIS331_CS 52
#define LSM9DS1_AGCS 4
#define LSM9DS1_MCS 10

Adafruit_H3LIS331 HighA = Adafruit_H3LIS331();
Adafruit_LSM9DS1 MidIMU = Adafruit_LSM9DS1(LSM9DS1_AGCS, LSM9DS1_MCS);

void getHighA(void);
void getMidIMU(void);

void setup() {
  // put your setup code here, to run once:
  
  Serial.begin(115200);
  Serial.println("Test!");

  //MidIMU setup
  if (!MidIMU.begin()){
    Serial.println("Couldnt start MidIMU");
    while (1) yield();
  }
  Serial.println("Found LSM9DS1 9DOF");
  MidIMU.setupAccel(MidIMU.LSM9DS1_ACCELRANGE_2G);
  MidIMU.setupMag(MidIMU.LSM9DS1_MAGGAIN_4GAUSS);
  MidIMU.setupGyro(MidIMU.LSM9DS1_GYROSCALE_245DPS);
  //MidIMU.endTransaction()
  
  //HighA setup
  if(!HighA.begin_SPI(H3LIS331_CS,SCK,MISO,MOSI)){
    Serial.println("Couldnt start HighA");
    while (1) yield();
  }
  Serial.println("H3LIS331 found!");
  HighA.setRange(H3LIS331_RANGE_100_G);
  HighA.setDataRate(LIS331_DATARATE_1000_HZ);
}

void loop() {
  // put your main code here, to run repeatedly:
  
  getHighA();
  getMidIMU();
  delay(1000);

}

void getHighA(void){
  sensors_event_t high_a_event;
  HighA.getEvent(&high_a_event);

  Serial.print("High Accel X: "); Serial.print(high_a_event.acceleration.x); Serial.print(" m/s^2");
  Serial.print("\tY: "); Serial.print(high_a_event.acceleration.y);     Serial.print(" m/s^2 ");
  Serial.print("\tZ: "); Serial.print(high_a_event.acceleration.z);     Serial.println(" m/s^2 ");
}

void getMidIMU(void){
  MidIMU.read();
  sensors_event_t a, m, g, temp;
  MidIMU.getEvent(&a, &m, &g, &temp); 
  Serial.print("Mid Accel X: "); Serial.print(a.acceleration.x); Serial.print(" m/s^2");
  Serial.print("\tY: "); Serial.print(a.acceleration.y);     Serial.print(" m/s^2 ");
  Serial.print("\tZ: "); Serial.print(a.acceleration.z);     Serial.println(" m/s^2 ");

  Serial.print("Mag X: "); Serial.print(m.magnetic.x);   Serial.print(" uT");
  Serial.print("\tY: "); Serial.print(m.magnetic.y);     Serial.print(" uT");
  Serial.print("\tZ: "); Serial.print(m.magnetic.z);     Serial.println(" uT");

  Serial.print("Gyro X: "); Serial.print(g.gyro.x);   Serial.print(" rad/s");
  Serial.print("\tY: "); Serial.print(g.gyro.y);      Serial.print(" rad/s");
  Serial.print("\tZ: "); Serial.print(g.gyro.z);      Serial.println(" rad/s");

  Serial.println();
}

The output of this yields correct data for the H3LIS331 high range accelerometer but the data out of LSM9DS1 is non-changing and incorrect. If the order of MidIMU and HighA are swapped in setup(), then the opposite occurs where the LSM9DS1 data is correct when H3LIS331 is fake.

After some research, it appears that SD card modules normally cause this issue. I will be adding an SD card to this project later but it is not even working in its current state. The only path forward that I see is to not use the premade libraries and to start coding my own SPI functions. Any help or insight with this issue would be greatly appreciated.

Which controller are you using?

Before you try to write your own SPI communication, I suggest you follow the description on Arduino:
https://www.arduino.cc/en/reference/SPI

to be precise this paragraph:

Note about Slave Select (SS) pin on AVR based boards

All AVR based boards have an SS pin that is useful when they act as a slave controlled by an external master. Since this library supports only master mode, this pin should be set always as OUTPUT otherwise the SPI interface could be put automatically into slave mode by hardware, rendering the library inoperative.

It is, however, possible to use any pin as the Slave Select (SS) for the devices. For example, the Arduino Ethernet shield uses pin 4 to control the SPI connection to the on-board SD card, and pin 10 to control the connection to the Ethernet controller.

I don't see any measures in your sketch to ensure the SS is high.

Should've included that. I am using an Arduino Due. I don't think it is the cause of the issue but I can check if this issue is replicated on an Uno of mine later. Also, I may have found a lead on this issue. It looks like both libraries are overwriting spi_dev variable. I am not too familiar with how Arduino SPI works on the low-level side but this may be relevant.

Both Adafruit boards are designed with an I2C usage in mind. You can use them on SPI but only as single devices. This is caused by the handling of the MISO line which doesn't tri-state when CS is pulled HIGH but is pulled high or low (depending on the board).

You may desolder the relevant resistors or cut traces to fix that.

I would suggest to change the bus to I2C as the board design is definitely optimized for that.

Thanks for your suggestion. Do you have any sources on that by chance? I couldn't find documentation regarding that on the Adafruit website.

Adafruit provides schematics for all it's products. Just have a look at them and how they pulled the signals to set the correct configuration of the chip. I don't know if Adafruit explicitly documents this. For me schematics are better than a written text that might forget important details.

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