Hi there,
SO, My first guess would be shared SPI bus handling.
A few reasons:
- the IMU works over I2C, so the sensor is probably fine
- the Adafruit library works in SPI, so the hardware path is at least basically correct
- the failures only show up with the other SPI libraries while sharing the bus with the ADS1220
That points more toward chip-select handling, SPI mode/transaction conflicts, or library assumptions than what I first suspected to missing pull-ups.
The LSM6DS3 supports both I2C and SPI, with CS selecting SPI mode, and the SparkFun-style constructor for SPI is the expected pattern.
What I would try first:
- Set both CS pins as outputs at startup and drive them HIGH before calling either library:
pinMode(IMU_CS, OUTPUT);
pinMode(ADS_CS, OUTPUT);
digitalWrite(IMU_CS, HIGH);
digitalWrite(ADS_CS, HIGH);
-
- Test the IMU alone with the SparkFun/Seeed library, with the ADS1220 code completely removed.
-
- Then test the ADS1220 alone.
-
- When sharing the bus, make sure the other device’s CS is HIGH before every transaction.
-
- Compare the Adafruit library behavior, since that one already works. It may simply be managing SPI transactions or chip select more carefully.
Here’s a cleaned-up test version that does the main things I would want on a shared SPI bus:
- sets both CS pins HIGH before any device init
- initializes SPI first
- forces the other device deselected before talking to one device
- adds a little structure so the bus is not left in a bad state
- reads the IMU only once per loop pass
This does not fix a broken library internally, but it gives YOU a much better shot at making the shared bus behave.
/*
XIAO nRF52840 / XIAO BLE
Shared SPI test: ADS1220 + LSM6DS3TR-C
Purpose:
- Force proper chip-select handling on a shared SPI bus
- Help diagnose why LSM6DS3 SPI init fails with some libraries
Notes:
- Both CS pins are driven HIGH before init
- Only one device is selected at a time
- IMU is tested with SparkFun/Seeed style LSM6DS3 library constructor
*/
#include <SPI.h>
#include <ADS1220_WE.h>
#include <LSM6DS3.h>
#define SAMPLE_RATE 90
#define IMU_CS D6
#define ADS_CS D7
#define ADS_DRDY D3
bool adcok = false;
bool imuok = false;
LSM6DS3 MyImu(SPI_MODE, IMU_CS);
ADS1220_WE ads(ADS_CS, ADS_DRDY);
// -----------------------------
// Helper functions
// -----------------------------
void deselectAllSPI() {
digitalWrite(IMU_CS, HIGH);
digitalWrite(ADS_CS, HIGH);
}
void selectIMU() {
digitalWrite(ADS_CS, HIGH);
digitalWrite(IMU_CS, LOW);
}
void deselectIMU() {
digitalWrite(IMU_CS, HIGH);
}
void selectADS() {
digitalWrite(IMU_CS, HIGH);
digitalWrite(ADS_CS, LOW);
}
void deselectADS() {
digitalWrite(ADS_CS, HIGH);
}
// -----------------------------
// Setup
// -----------------------------
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println();
Serial.println("=================================");
Serial.println("Shared SPI Test: ADS1220 + LSM6DS3");
Serial.println("=================================");
// IMPORTANT: set CS lines first
pinMode(IMU_CS, OUTPUT);
pinMode(ADS_CS, OUTPUT);
deselectAllSPI();
delay(10);
// Start SPI bus
SPI.begin();
delay(10);
Serial.println("Init Sensors...");
// -----------------------------
// Init ADS1220
// -----------------------------
deselectAllSPI();
delay(5);
ads.setSPIClockSpeed(1000000);
// Make extra sure IMU is not selected during ADS init
digitalWrite(IMU_CS, HIGH);
if (!ads.init()) {
Serial.println("ADS1220 is not connected!");
adcok = false;
} else {
Serial.println("ADS1220 found");
adcok = true;
ads.setGain(ADS1220_GAIN_128);
ads.setOperatingMode(ADS1220_DUTY_CYCLE_MODE);
ads.setDataRate(ADS1220_DR_LVL_4); // 82.5 SPS duty cycle mode
ads.setConversionMode(ADS1220_CONTINUOUS);
ads.setCompareChannels(ADS1220_MUX_1_2);
ads.setVRefSource(ADS1220_VREF_REFP1_REFN1);
ads.setLowSidePowerSwitch(ADS1220_SWITCH);
}
delay(200);
// -----------------------------
// Init LSM6DS3
// -----------------------------
deselectAllSPI();
delay(5);
// Make extra sure ADS is not selected during IMU init
digitalWrite(ADS_CS, HIGH);
int imuStatus = MyImu.begin();
if (imuStatus != 0) {
Serial.print("IMU not found! begin() returned: ");
Serial.println(imuStatus);
imuok = false;
} else {
Serial.println("IMU found");
imuok = true;
}
deselectAllSPI();
delay(100);
Serial.println("Setup complete.");
Serial.println();
}
// -----------------------------
// Main loop
// -----------------------------
void loop() {
int cnt = SAMPLE_RATE;
int32_t reading = 0;
float gyroZ = 0.0f;
while (cnt > 0) {
// ----- Read ADS1220 -----
if (adcok) {
// Make sure IMU is deselected first
deselectAllSPI();
delayMicroseconds(5);
reading = ads.getRawData();
deselectADS();
} else {
delay(15);
}
// ----- Read IMU -----
if (imuok) {
// Make sure ADS is deselected first
deselectAllSPI();
delayMicroseconds(5);
gyroZ = MyImu.readFloatGyroZ();
deselectIMU();
}
cnt--;
}
Serial.print("Bridge Reading: ");
Serial.println(reading);
Serial.print("Gyroscope Z = ");
Serial.println(gyroZ, 4);
Serial.println("-----------------------------");
delay(500);
}
First, test IMU only:
- comment out all ADS1220 code
- see whether
MyImu.begin() works reliably
Then test ADS only.
If both work alone but fail together, that is strong proof of a shared-bus conflict, not a dead sensor.
If the IMU still fails with this version, the next things I would look at are:
- SPI mode mismatch between the IMU library and ADS library
- breakout board wiring for the LSM6DS3 SPI pins
- whether the IMU breakout is really set up for 4-wire SPI
- whether the library is doing odd things internally during
begin()
Try that and report back , please.
HTH
GL
PJ 