0
\$\begingroup\$

I’m currently working on a project using an Arduino Mega, where I have two devices connected via SPI: a BB-ADS1220 (for reading 2 strain gauges) and an LSM6DSO (accelerometer/gyroscope). I was able to connect both sensors separately and read data out of each of them with no issue. Yay! :slight_smile:

However, I’m experiencing some interference issues when trying to read them together (on the same SPI bus).

Although I can read both, when I touch the accelerometer, it seems to introduce noise + fluctuations in the readings from the strain gauge circuit (which should not read anything as it is far from the accelerometer).

Has anyone encountered similar issues when using multiple devices on the same SPI bus? Any suggestions on how to mitigate this interference? I should mentioned that I'm switching between two SPI modes in my code (SPI mode 0 for the LSM6DSO and SPI mode 1 for the ADS1220). I fear this might be the issue?

Here’s a quick overview of my setup:

  • Microcontroller: Arduino Mega
  • Sensors: BB-ADS1220 (strain gauge) and LSM6DSO (accelerometer)
  • Level shifter: PiHut TXB0104
  • Connections: Both devices are connected via SPI with appropriate wiring and grounding (see attached schematic)

Any advice or insights would be greatly appreciated!

#include <SPI.h>
#include "Protocentral_ADS1220.h"
//TODO: bug. If I move the accelerometer, the load cell signal is affected. How come?
// LSM6DSO Configuration
#define LSM6DSO_CS_PIN 10
#define WHO_AM_I_REG 0x0F
#define CTRL1_XL 0x10
#define CTRL2_G 0x11
#define OUTX_L_A 0x28
#define OUTX_H_A 0x29
#define OUTY_L_A 0x2A
#define OUTY_H_A 0x2B
#define OUTZ_L_A 0x2C
#define OUTZ_H_A 0x2D
#define OUTX_L_G 0x22
#define OUTX_H_G 0x23
#define OUTY_L_G 0x24
#define OUTY_H_G 0x25
#define OUTZ_L_G 0x26
#define OUTZ_H_G 0x27
// ADS1220 Configuration
#define PGA 4 // Programmable Gain = 1
#define VREF 2.048 // Internal reference of 2.048V
#define VFSR (VREF / PGA)
#define FULL_SCALE (((long int)1<<23) - 1)
#define ADS1220_CS_PIN 9
#define ADS1220_DRDY_PIN 8
Protocentral_ADS1220 pc_ads1220;
int32_t adc_data;
void setup() {
 Serial.begin(115200);
 
 // Initialize SPI
 SPI.begin();
 
 // Initialize LSM6DSO
 pinMode(LSM6DSO_CS_PIN, OUTPUT);
 digitalWrite(LSM6DSO_CS_PIN, HIGH); // Deselect LSM6DSO
 configureLSM6DSO();
 
 // Initialize ADS1220
 pinMode(ADS1220_CS_PIN, OUTPUT);
 digitalWrite(ADS1220_CS_PIN, HIGH); // Deselect ADS1220
 configureADS1220();
}
void loop() {
 // Read data from LSM6DSO
 readLSM6DSO();
 // Read data from ADS1220
 readADS1220();
 
}
// Function to configure LSM6DSO
void configureLSM6DSO() {
 Serial.println("Configuring LSM6DSO...");
 
 digitalWrite(LSM6DSO_CS_PIN, LOW); // Select LSM6DSO
 SPI.setDataMode(SPI_MODE0); // Set SPI mode to 0
 // Send initialization commands
 writeRegister(CTRL1_XL, 0x60); // Enable accelerometer
 writeRegister(CTRL2_G, 0x60); // Enable gyroscope
 digitalWrite(LSM6DSO_CS_PIN, HIGH); // Deselect LSM6DSO
}
// Function to read data from LSM6DSO
void readLSM6DSO() {
 digitalWrite(LSM6DSO_CS_PIN, LOW); // Select LSM6DSO
 SPI.setDataMode(SPI_MODE0); // Ensure SPI mode is set to 0
 int16_t accelX = read16bitRegister(OUTX_L_A, OUTX_H_A);
 int16_t accelY = read16bitRegister(OUTY_L_A, OUTY_H_A);
 int16_t accelZ = read16bitRegister(OUTZ_L_A, OUTZ_H_A);
 
 
 Serial.print(accelX); Serial.print(" ");
 Serial.print(accelY); Serial.print(" "); 
 Serial.print(accelZ); Serial.print(" "); 
 
 digitalWrite(LSM6DSO_CS_PIN, HIGH); // Deselect LSM6DSO
}
// Function to configure ADS1220
void configureADS1220() {
 Serial.println("Configuring ADS1220...");
 
 digitalWrite(ADS1220_CS_PIN, LOW); // Select ADS1220
 SPI.setDataMode(SPI_MODE1); // Set SPI mode to 1
 // Send initialization commands
 // ... (Initialize ADS1220 settings)
 // Initialize ADS1220 with Chip Select and Data Ready pins
 pc_ads1220.begin(ADS1220_CS_PIN, ADS1220_DRDY_PIN);
 // Configure ADS1220 settings
 pc_ads1220.set_data_rate(DR_330SPS); // Data rate of 330 samples per second
 pc_ads1220.set_pga_gain(PGA_GAIN_1); // PGA gain set to 1
 pc_ads1220.set_conv_mode_single_shot(); // Set to single-shot conversion mode
 digitalWrite(ADS1220_CS_PIN, HIGH); // Deselect ADS1220
}
// Function to read data from ADS1220
void readADS1220() {
 digitalWrite(ADS1220_CS_PIN, LOW); // Select ADS1220
 SPI.setDataMode(SPI_MODE1); // Ensure SPI mode is set to 1
 // Read data from ADS1220
 // ... (Implement ADS1220 read logic)
 // Read from channel 0
 adc_data = pc_ads1220.Read_SingleShot_SingleEnded_WaitForData(MUX_SE_CH0);
 float ch0 = convertToMilliV(adc_data);
 // Read from channel 1
 adc_data = pc_ads1220.Read_SingleShot_SingleEnded_WaitForData(MUX_SE_CH1);
 float ch1 = convertToMilliV(adc_data);
 // Calculate the differential voltage (half-bridge value)
 float differentialVoltage = 40000*(ch1 - ch0);
 // Print the differential voltage for the Serial Plotter
 Serial.println(differentialVoltage);
 digitalWrite(ADS1220_CS_PIN, HIGH); // Deselect ADS1220
}
// Function to write to a register
void writeRegister(byte regAddress, byte data) {
 digitalWrite(LSM6DSO_CS_PIN, LOW); // Select device
 SPI.transfer(regAddress & 0x7F); // Send register address (write mode)
 SPI.transfer(data); // Send the data to write
 digitalWrite(LSM6DSO_CS_PIN, HIGH); // Deselect device
}
// Function to read a 16-bit register
int16_t read16bitRegister(byte regL, byte regH) {
 byte lowByte = readRegister(regL);
 byte highByte = readRegister(regH);
 return (int16_t)((highByte << 8) | lowByte);
}
// Function to read a single register
byte readRegister(byte regAddress) {
 digitalWrite(LSM6DSO_CS_PIN, LOW); // Select device
 SPI.transfer(regAddress | 0x80); // Send register address with read bit (0x80)
 byte regValue = SPI.transfer(0x00); // Send dummy byte and read response
 digitalWrite(LSM6DSO_CS_PIN, HIGH); // Deselect device
 return regValue; // Return the register value
}
// Function to convert raw ADC data to millivolts
float convertToMilliV(int32_t i32data) {
 return (float)((i32data * VFSR * 1000) / FULL_SCALE);
}

schematic

toolic
10.8k11 gold badges31 silver badges35 bronze badges
asked Oct 19, 2024 at 20:31
\$\endgroup\$
2
  • \$\begingroup\$ Have you considered changing the MEGA to 3.3V supply and eliminating the level shifter altogether? || You may find it interesting to look up typical "quirks" of the TXBxxxx family: they are NOT suitable for general purpose applications like open-drain signals or long-wire buses. \$\endgroup\$ Commented Oct 20, 2024 at 18:19
  • \$\begingroup\$ For reference, this question was also posted at: eevblog.com/forum/microcontrollers/… \$\endgroup\$ Commented Oct 20, 2024 at 18:28

1 Answer 1

1
\$\begingroup\$

As I understand the datasheet, if CS of the LSM6DSO is high (= SPI deselected) it will expose an active I2C interface on the same lines. This probably cannot coexist with another SPI device.

If you can disable the level shifter during communicatons to the ADS1220 you have a good chance.

answered Oct 20, 2024 at 18:06
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.