Go Down

Topic: Reading BMA280 data via SPI with Due (Read 84 times) previous topic - next topic


Oct 13, 2017, 10:12 am Last Edit: Oct 14, 2017, 01:12 pm by gecodet
Hi everyone, I'm trying to use the Arduino Due to read sensor data from the BMA280. This is a 3-axis accelerometer (datasheet: https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMA280-DS000-11_published.pdf). Protocol that I use is SPI.

Acceleration data for each axis has a width of 14-bit. Problem is, for each axis I always get 65532, which is (1111111111111100)2. I don't understand why it keeps returning this value. I bit-masked the last two bits because these are useless data as specified in the datasheet. The codes are as shown:

Code: [Select]
#include <SPI.h>
// https://www.arduino.cc/en/Tutorial/BarometricPressureSensorhttps://www.sparkfun.com/tutorials/240
// http://forum.arduino.cc/index.php/topic,159313.0.html

const int CS = 52;

byte PMU_Range = 0x0F;
byte PMU_BW = 0x10;
byte PMU_SELF_TEST = 0x32;

byte DATAX0 = 0x02;   // x-axis LSB
byte DATAX1 = 0x03;   // x-axis MSB

void setup(){

SPI.setDataMode(CS, 0);   // set SPI mode to '00'
SPI.setClockDivider(CS, 84);


pinMode(CS, OUTPUT);
digitalWrite(CS, HIGH);

writeRegister(PMU_Range, 0x03);   // set ge-range to +/- 2G
writeRegister(PMU_BW, 0x0E);   // set bandwidth to 500Hz
writeRegister(PMU_SELF_TEST, 0x00);   // disable self-test


void loop(){
// read 2 bytes of data (LSB and MSB of x-axis) starting at register DATAX0
unsigned int xData = readRegister(DATAX0, 2);



void writeRegister(byte registerAddress, byte value){
// Set Chip Select pin low to signal the beginning of an SPI packet.
digitalWrite(CS, LOW);
// Transfer the register address over SPI.
// Transfer the desired register value over SPI.
// Set the Chip Select pin high to signal the end of an SPI packet.
digitalWrite(CS, HIGH);

unsigned int readRegister(byte thisRegister, int bytesToRead) {
byte lsb = 0;           // least significant byte
unsigned int msb = 0;   // most significant byte

// read process requires setting the first bit to 1
thisRegister = 0x80 | thisRegister;

digitalWrite(CS, LOW);


// read least significant byte returned
lsb = SPI.transfer(0x00);
// decrement the number of bytes left to read:

if (bytesToRead > 0) {
 // read most significant byte returned
 msb = SPI.transfer(0x00);
 // shift most significant byte left
 msb = msb << 8;
 // combine the byte you just got with the previous one:
 msb = msb | (lsb & 0xFC);
 // decrement the number of bytes left to read:
// take the chip select high to de-select:
digitalWrite(CS, HIGH);
// return the result:
return (msb);

I'm using the BMA280 shuttle board (schematic in attachment) which is easy to wire, so I suppose the problem lies in the software. I'd be grateful for any advice. Thanks! :)


Some thoughts:

After a fast reading of the datasheet, it appears that this sensor can be read in SPI 4 wires by default or 3 wires.

If you are using the default SPI mode 4 wires (Pin 11 to Gnd, page 106), I guess connections should be:
SDI to MOSI, SDO to MISO, CSM to CSS,  SCK to SCK,  Gnd to Gnd. Is that your wiring ?

I noticed (datasheet page 18) that :
Accel_Data = (uint16_t) (MSB << 6)                      // Bits 13 to 6
                      | (uint16_t)(LSB & 0b00111111);  // Bits  6 to 0, remove flag bits
which is not what I can see in your code.


Hi ard_newbie, thanks for your reply!

1) Yes I'm using the SPI 4 wire mode, and the wiring is as you've stated.

2) I tried using the code you suggested, but it still doesn't work, it keeps returning 16383. I suppose the SPI is not initiated properly in the first place. But I have no clue how I can modify the code.


Now it works and returns reasonable values. :)

I was using the ICSP interface and I changed to the SPI interface on the Due. Apart from that I added the command SPI.setBitOrder(CS, LSBFIRST) to the code.

Go Up