ESP32 and using SPI to communicate with BMA456

Hi,

I'm trying to communicate with a BOSCH BMA456, via SPI, and an ESP32 (DevKitC).
I do get some response, and actually ONE correct value, the answer to CHIP_ID which is dec 22.

But:

  1. datasheet says BMA456 responds with 16 bit protocol, and the first byte is always dummy, so I would expect something like: (nonsens byte), 22, (nonsens byte), 22, etc.
    but here it seems the one correct byte I do get (22) comes already as the first byte?

  2. why does this, almost, work but only for the second time sending out the command?

Can anyone help with this one please?
(I have no oscilloskop to check for what actually happens)

Response from serial monitor:

255
0
22
35
0
16
0
0

link to BMA456: Downloads | Bosch Sensortec

https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMA456-DS000-01.pdf

digitalWrite(slaveSelectPin, LOW); // make sure BMA456 knows its SPI
  digitalWrite(slaveSelectPin, HIGH);
    
  SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE3)); //set parameters
  SPI.begin();  // init SPI
  
  digitalWrite(slaveSelectPin, LOW); // select slave

  delay(100);
  
  data= SPI.transfer(0x80); // send 1 byte to slave (command read CHIP_ID), and receive first byte (dummy)
  Serial.println(data);
  delay(100);

  data= SPI.transfer(0x00); // send dummy, and receive second byte with chip_id 
  Serial.println(data);
  delay(100);

  data= SPI.transfer(0x80); // repeat the above
  Serial.println(data);
  delay(100);

  data= SPI.transfer(0x00);
  Serial.println(data);
  delay(100);

  data= SPI.transfer(0x80); // repeat the above
  Serial.println(data);
  delay(100);

  data= SPI.transfer(0x00);
  Serial.println(data);
  delay(100);
  
  data= SPI.transfer(0x80); // repeat the above
  Serial.println(data);
  delay(100);

  data= SPI.transfer(0x00);
  Serial.println(data);
  delay(100);
   
  digitalWrite(slaveSelectPin, HIGH);
  
  SPI.endTransaction();

another working engineer who can't figure it out?

https://forum.arduino.cc/index.php?topic=531898.0

.

Please post complete code, the error might be in the part you're hiding from us.

The datasheet explains on page 108 that you first have to write the command byte on the SPI bus and then read the dummy byte. After that you can read the value you requested. You're reading the dummy byte while sending the command byte.

Thanks pylon,

that helped regarding the byte order.

I thought that one had to/must do the write and read in the same commandline.

the serial monitor now response with (0, 22 being OK)

0
22
0
16
0
0
0
0

Im still wondering why I cant do more correct CHIP_ID reads though?
And yes I do know im still missing all the init of the chip, but this should not be nescessary for now.

Thanks ieee for letting me know that I'm now an working engineer, not just someone new to Arduino and SPI, and not having trying to read the datasheet and googling for days just to get here..

Here is the complete code for now:

/*
 * Test BMA456 SPI
 * 
 */

// libraries 
#include <SPI.h>

// declare variables **********************************************
#define LEDpin 15

bool LEDstate= 0;
int slaveSelectPin= 5;
byte command;
byte data;
unsigned int data16;

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

  pinMode(LEDpin, OUTPUT);

  pinMode(slaveSelectPin, OUTPUT);
  
  digitalWrite(slaveSelectPin, LOW); // make sure BMA456 knows its SPI
  digitalWrite(slaveSelectPin, HIGH);
    
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3)); //set parameters
  SPI.begin();  // init SPI
  
  digitalWrite(slaveSelectPin, LOW); // select slave

  delay(100);
  
  SPI.transfer(0x80); // send 1 byte to slave (command read CHIP_ID), DO NOT receive first byte at this moment
  delay(100);
  
  data= SPI.transfer(0x00); // send dummy, and receive first byte (dummy)
  Serial.println(data);
  delay(100);

  data= SPI.transfer(0x00); // send dummy, and receive second byte with chip_id 
  Serial.println(data);
  delay(1000);


  SPI.transfer(0x80); // send 1 byte to slave (command read CHIP_ID), DO NOT receive first byte at this moment
  delay(100);
  
  data= SPI.transfer(0x00); // send dummy, and receive first byte (dummy)
  Serial.println(data);
  delay(100);

  data= SPI.transfer(0x00); // send dummy, and receive second byte with chip_id 
  Serial.println(data);
  delay(1000);


  SPI.transfer(0x80); // send 1 byte to slave (command read CHIP_ID), DO NOT receive first byte at this moment
  delay(100);
  
  data= SPI.transfer(0x00); // send dummy, and receive first byte (dummy)
  Serial.println(data);
  delay(100);

  data= SPI.transfer(0x00); // send dummy, and receive second byte with chip_id 
  Serial.println(data);
  delay(1000);
  

  SPI.transfer(0x80); // send 1 byte to slave (command read CHIP_ID), DO NOT receive first byte at this moment
  delay(100);
  
  data= SPI.transfer(0x00); // send dummy, and receive first byte (dummy)
  Serial.println(data);
  delay(100);

  data= SPI.transfer(0x00); // send dummy, and receive second byte with chip_id 
  Serial.println(data);
  delay(1000);

  
  digitalWrite(slaveSelectPin, HIGH);
  
  SPI.endTransaction();
    
}

void loop() {
  // put your main code here, to run repeatedly:
  LEDstate= !LEDstate;
  digitalWrite(LEDpin, LEDstate);
  
  delay(1000);
}

Im still wondering why I cant do more correct CHIP_ID reads though?

You have to pull CS HIGH for a short time between consecutive commands. That way the chip knows when the next commands start. Otherwise is just reads on, so you don't get the CHIP ID anymore but the next register.