Skip to main content
Associate
Nov 2, 2026 9:55 AM UTC
Question

ASM330LHHXTR SPI Interface Issue

Hi everyone,
I am currently using an ESP32-S3 development board to read ST's 6-axis IMU sensors via SPI, but I am encountering abnormal values when trying to read the Device ID (WHO_AM_I, 0x0F). After doing some cross-testing, I noticed a very strange hardware phenomenon. I would appreciate any debugging advice or insights.
 

[Hardware Setup]

  • MCU: ESP32-S3 Devkit

  • Sensors:

    1. ASM330LHHXTR

    2. STEVAL MKI215V1 (LSM6DSO evaluation board)

    3. SparkFun LSM6DSO Breakout

  • Power Supply: 3.3V

  • Interface: SPI (I have already tried switching between 3-wire and 4-wire modes)

[Issue Description & Troubleshooting Steps] The expected Device ID is 0x6B, but it fails to read correctly. My debugging process is as follows:

  1. ASM330LHHXTR Test: Using the code provided below, the Device ID returns 0x40 or 0x48.

  2. STEVAL MKI215V1 Test: Switched to this evaluation board, and the Device ID returns 0x50.

    • The Anomaly: If I disconnect the sensor's GND wire and press Reset on the ESP32, the Device ID reads correctly as 0x6B. This doesn't make sense logically.

  3. SparkFun LSM6DSO Test:

    • First, I tested it using I2C with the official GitHub library, and it worked perfectly.

    • Then, I changed the hardware wiring and code to use SPI, and the exact same issue from Step 2 occurred.

  4. Reproducing the GND Anomaly: On the SparkFun module, the same phenomenon happens—disconnecting the GND wire and pressing Reset makes the Device ID read correctly.

[My Questions]

  1. Why does the Device ID read normally when the GND wire is unplugged, but return garbage data when connected? Does this imply a blind spot in my hardware wiring (e.g., leakage current, parasitic powering, or an I2C/SPI pin state conflict)?

  2. Am I missing something in my ESP32-S3 SPI initialization setup?

Any advice or suggestions for further testing would be greatly appreciated. Thank you!

 

[Test Code]

#include <SPI.h>

// ESP32-S3 Pin Define
const int PIN_MOSI = 11;
const int PIN_SCK = 12;
const int PIN_MISO = 13;
const int CSPin = 14;

// ==========================================
// Function Prototypes
// ==========================================
void SPI_write(uint8_t WriteAddr, uint8_t WriteData);
uint8_t SPI_read(uint8_t ReadAddr);
void SPI_multi_read(uint8_t ReadAddr, uint8_t *ReadBuf, unsigned int Bytes);
bool ASM330LHH_Initial();

// ==========================================
// Main
// ==========================================
void setup() {
  Serial.begin(115200);
  delay(500); 

  pinMode(CSPin, OUTPUT);
  digitalWrite(CSPin, HIGH);
  delay(10);

  // SPI.begin();
  // SPI.begin(PIN_SCK, PIN_MISO, PIN_MOSI, -1);
  SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));

  if (!ASM330LHH_Initial()) {
    Serial.println("[ERROR] Initial ASM330LHH FAILED.");
    while (1) {
      delay(100);
    }
  }
}

void loop() {
  uint8_t Device_ID = SPI_read(0x0F);
  Serial.print("Device ID 0x");
  if (Device_ID < 0x10) Serial.print("0");
  Serial.println(Device_ID, HEX);

  uint8_t CTRL3_C = SPI_read(0x12);
  Serial.print("CTRL3_C 0x");
  Serial.println(CTRL3_C, HEX);

  uint8_t OUTX_L_A = SPI_read(0x28);
  Serial.print("OUTX_L_A 0x");
  Serial.println(OUTX_L_A, HEX);

  uint8_t OUTX_H_A = SPI_read(0x29);
  Serial.print("OUTX_H_A 0x");
  Serial.println(OUTX_H_A, HEX);

  delay(1000);
}

// ====================================================================================
// Basic SPI R/W Function
// ====================================================================================
uint8_t SPI_read(uint8_t ReadAddr) {
  uint8_t val;
  digitalWrite(CSPin, LOW);   

  SPI.transfer(ReadAddr | 0x80);  
  val = SPI.transfer(0x00);
  
  digitalWrite(CSPin, HIGH);  
  
  return val;
}

void SPI_write(uint8_t WriteAddr, uint8_t WriteData) {
  digitalWrite(CSPin, LOW);   
  
  // Send Address and ensure the write flag (MSb = 0)
  SPI.transfer(WriteAddr & 0x7F);
  SPI.transfer(WriteData);
  
  digitalWrite(CSPin, HIGH);  
}

// ====================================================================================
// ASM330LHH Initial
// ====================================================================================
bool ASM330LHH_Initial() {
  uint8_t id = SPI_read(0x0F);

  Serial.print("Initial WHO_AM_I = 0x");
  Serial.println(id, HEX);

  return true;
}

 

[ASM330LHHXTR  Schematic]

Note: R4 NC

 

3 replies

Andrew Neil
Super User
Nov 2, 2026 10:52 AM UTC

Welcome to the forum

Please see How to write your question to maximize your chances to find a solution for best results.

In particular, how, exactly, is the ESP32 connected to the IMU - PCB? dev boards? breadboard? other?

a full schematic could be helpful; plus some good, clear photos of your setup.

 

Have you looked at the lines using an oscilloscope to verify that signals are clean, at correct levels, etc?

On the SparkFun module, the same phenomenon happens—disconnecting the GND wire and pressing Reset makes the Device ID read correctly.

In particular, look at what’s going on here

 

Can your ESP32 successfully communicate with any other SPI slaves?

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
Associate
Nov 3, 2026 5:30 AM UTC

Thanks for the reply and the suggestions! I will make sure to follow the posting guidelines for my future questions.

To answer your points:

  1. I am using an ESP32-S3 development board to connect with the IMU.

  2. I haven't checked with the oscilloscope yet, but I will definitely look into it later today.

  3. My ESP32-S3 is able to communicate normally with other SPI devices (e.g., Bosch sensors), so the SPI bus itself should be functioning correctly.

[Full Schematic]

[Full Setup]
 

#include <SPI.h>

// ESP32-S3 Pin Define
const int PIN_MOSI = 11;
const int PIN_SCK = 12;
const int PIN_MISO = 13;
const int CSPin = 14;
// ==========================================
// function
// ==========================================
void SPI_write(uint8_t WriteAddr, uint8_t WriteData);
uint8_t SPI_read(uint8_t ReadAddr);
void SPI_multi_read(uint8_t ReadAddr, uint8_t *ReadBuf, unsigned int Bytes);
bool ASM330LHH_Initial();

// ==========================================
// Main
// ==========================================
void setup() {
Serial.begin(115200);
delay(500);

pinMode(CSPin, OUTPUT);
digitalWrite(CSPin, HIGH);
delay(10);

SPI.begin(PIN_SCK, PIN_MISO, PIN_MOSI, -1);

SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3));

if (!ASM330LHH_Initial()) {
Serial.println("[ERROR] Initial ASM330LHH FAILED.");
while (1) {
delay(100);
}
}
}

void loop() {
uint8_t Device_ID = SPI_read(0x0F);
Serial.print("Device ID 0x");
if (Device_ID < 0x10) Serial.print("0");
Serial.println(Device_ID, HEX);

uint8_t CTRL3_C = SPI_read(0x12);
Serial.print("CTRL3_C 0x");
Serial.println(CTRL3_C, HEX);

uint8_t OUTX_L_A = SPI_read(0x28);
Serial.print("OUTX_L_A 0x");
Serial.println(OUTX_L_A, HEX);

uint8_t OUTX_H_A = SPI_read(0x29);
Serial.print("OUTX_H_A 0x");
Serial.println(OUTX_H_A, HEX);

delay(1000);
}

// ====================================================================================
// Basic SPI R/W Function
// ====================================================================================
uint8_t SPI_read(uint8_t ReadAddr) {
uint8_t val;
digitalWrite(CSPin, LOW);

SPI.transfer(ReadAddr | 0x80);
val = SPI.transfer(0x00);

digitalWrite(CSPin, HIGH);
return val;
}

void SPI_write(uint8_t WriteAddr, uint8_t WriteData) {
digitalWrite(CSPin, LOW);

SPI.transfer(WriteAddr & 0x7F);
SPI.transfer(WriteData);

digitalWrite(CSPin, HIGH);
}

// ====================================================================================
// ASM330LHH Initial
// ====================================================================================
bool ASM330LHH_Initial() {

// uint8_t test0 = SPI_read(0x18);
// Serial.print("test0 = 0x");
// Serial.println(test0, HEX);

// SPI_write(0x12, 0X04); // CTRL3
// delay(1);
// uint8_t test1 = SPI_read(0x18);

// Serial.print("test1 = 0x");
// Serial.println(test1, HEX);

uint8_t id = SPI_read(0x0F);
// uint8_t id = SPI_read(0x18);
// uint8_t id = SPI_read(0x13);

Serial.print("Initial WHO_AM_I = 0x");
Serial.println(id, HEX);

// if (id != 0x6B) { // 0x6B
// return false;
// }
return true;
}

 

 

Andrew Neil
Super User
Nov 3, 2026 9:28 AM UTC

Those so-called “dupont” connectors (most are not genuine DuPont) can be unreliable - you definitely need to check at the device pins that you are getting clean signals.

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.