I realized that after I posted my code. Therefor I wrote a second post that your code should work.
In the 3D world, 0x0000 is next to 0xFFFF, so 0 is next to 65535. The 0xFFFF is also -1 when it would be a signed value.
The range to both sides is also the same. The angle with 16383 is the same (but opposite) angle as 49152. That seems to be the range to deal with.
The code of the Bosch API has lots of structs and code for offsets, but most of the code does not really do much. The basic example shows the raw values.
However, I think those raw values in the example are signed 16 bits values. It uses this struct with signed value for the acceleration.
The datasheet is too long for me to completely understand.
Do you have any progress?
I am starting my project exactly as you did (not all the components arrived so I haven't started yet), the discussion in this post is really helpful.
I have solved my previous problem, by setting the address to 0x69. For those who connect to VIN, Ground, SCL and SDA, the address is 0x69 not 0x68.
However, my project aimed to collect IMU data with a high sample rate (maybe the max of BMI323: 6400Hz). I use serial connection to my PC but it only achieves 800+Hz now (I have changed the sample rate setting).
From my previous experience, it is possible to access audio data at > 16000Hz, which means the remained problem should be software issue (I guess). Do you have any expertise in it?
I guess there are the following solutions:
change to SPI?
callback is used in PDM library, is it the bottleneck?
Since my question is not so correlated to the original post, I may create a new post later.
Since BMI323 supports -2g/2g range for accelerometer, it is hard to believe that the data type is "uint16_t", I try with short instead, and the results are the following:
However, although the X and Y looks reasonable, the Z always keeps 0. Are you interested in using "short" instead of "uint16_t"?
I have attached my code below:
#include <Wire.h>
#define INC_ADDRESS 0x69
#define ACC_CONF 0x20 //Page 91
#define GYR_CONF 0x21 //Page 93
#define CMD 0x7E //Page 65
short x, y, z;
void setup(void) {
Serial.begin(115200);
//Accelerometer
Wire.begin();
Wire.setClock(400000); // I2C Fast Mode (400kHz)
softReset();
/*
* Acc_Conf P.91
* mode: 0x7000 -> High
* average: 0x0000 -> No
* filtering: 0x0080 -> ODR/4
* range: 0x0000 -> 2G
* ODR: 0x000B -> 800Hz
* Total: 0x708B
*/
writeRegister16(ACC_CONF,0x708C);//Setting accelerometer
/*
* Gyr_Conf P.93
* mode: 0x7000 -> High
* average: 0x0000 -> No
* filtering: 0x0080 -> ODR/4
* range: 0x0000 -> 125kdps
* ODR: 0x000B -> 800Hz
* Total: 0x708B
*/
writeRegister16(GYR_CONF,0x708B);//Setting gyroscope
}
void softReset(){
writeRegister16(CMD, 0xDEAF);
delay(50);
}
void loop() {
if(readRegister16(0x02) == 0x00) {
//Read ChipID
readAllAccel(); // read all accelerometer/gyroscope/temperature data
Serial.print(" \tx:");
Serial.print(x);
Serial.print(" \ty:");
Serial.print(y);
Serial.print(" \tz:");
Serial.println(z);
}
}
//Write data in 16 bits
void writeRegister16(uint16_t reg, uint16_t value) {
Wire.beginTransmission(INC_ADDRESS);
Wire.write(reg);
//Low
Wire.write((uint16_t)value & 0xff);
//High
Wire.write((uint16_t)value >> 8);
Wire.endTransmission();
}
//Read data in 16 bits
uint16_t readRegister16(uint8_t reg) {
Wire.beginTransmission(INC_ADDRESS);
Wire.write(reg);
Wire.endTransmission(false);
int n = Wire.requestFrom(INC_ADDRESS, 4);
uint16_t data[4];
int i =0;
while(Wire.available()){
data[i] = Wire.read();
i++;
}
return (data[3] | data[2] << 8);
}
//Read all axis
void readAllAccel() {
Wire.beginTransmission(INC_ADDRESS);
Wire.write(0x03);
Wire.endTransmission();
Wire.requestFrom(INC_ADDRESS, 6);
short data[6];
int i =0;
while(Wire.available()){
data[i] = Wire.read();
i++;
}
//Offset = 2 because the 2 first bytes are dummy (useless)
int offset = 2;
x = (data[offset + 0] | (short)data[offset + 1] << 8); //0x03
y = (data[offset + 2] | (short)data[offset + 3] << 8); //0x04
z = (data[offset + 4] | (short)data[offset + 5] << 8); //0x05
}
Hi, I've tested your code and I had the same, Z frozen, but it's because you're not reading enough bytes, the 2 firsts are dummies, so you have to read 8 instead of 6 as follow
Wire.requestFrom(INC_ADDRESS, 8);
short data[8];
int i =0;
while(Wire.available()){
data[i] = Wire.read();
i++;
}
//Offset = 2 because the 2 first bytes are dummy (useless)
int offset = 2;
And I don't see the problem to use short instead of int16_t, because it seems the same:
"int16_t is always, by definition an 16-bit signed value (−32,768 to +32,767),"
"A short is a 16-bit data-type. On all Arduinos (ATMega and ARM based) a short stores a 16-bit (2-byte) value. This yields a range of -32,768 to 32,767"