STK8231 accelerometer, getting two axis (x & y data) but not z, raw in 0-255

Here is the datasheet I followed: STK8321 SENSORTEK | C966924 - LCSC Electronics

We are trying the following code:


#include <Wire.h>

int ADXLAddress = 0x0F; // Device address in which is also included the 8th bit for selecting the mode, read in this case.

#define X_Axis_Register_DATAX0 0x03 // Hexadecima address for the DATAX0 internal register.
#define X_Axis_Register_DATAX1 0x02 // Hexadecima address for the DATAX1 internal register.

#define Y_Axis_Register_DATAX0 0x05 // Hexadecima address for the DATAX0 internal register.
#define Y_Axis_Register_DATAX1 0x04 // Hexadecima address for the DATAX0 internal register.

#define Z_Axis_Register_DATAX0 0x07 // Hexadecima address for the DATAX0 internal register.
#define Z_Axis_Register_DATAX1 0x06 // Hexadecima address for the DATAX0 internal register.

int X0, X1, X_out;
int Y0, Y1, Y_out;
int Z0, Z1, Z_out;

void setup() {
  Wire.begin(); // Initiate the Wire library
  Serial.begin(115200);
  Wire.beginTransmission(ADXLAddress);
  Wire.endTransmission();
}

void loop() {
  Wire.beginTransmission(ADXLAddress); // Begin transmission to the Sensor
  //Ask the particular registers for data
  Wire.write(X_Axis_Register_DATAX0);
  Wire.write(X_Axis_Register_DATAX1);
  Wire.endTransmission(); // Ends the transmission and transmits the data from the two registers

  Wire.requestFrom(ADXLAddress, 2); // Request the transmitted two bytes from the two registers
  if (Wire.available() <= 2) { //
    X0 = Wire.read(); // Reads the data from the register
    X1 = Wire.read();
  }

  Serial.print("\n   X0= "); Serial.print(X0); Serial.print("         X1= "); Serial.print(X1);

  delay(100);

  Wire.beginTransmission(ADXLAddress); // Begin transmission to the Sensor
  Wire.write(Y_Axis_Register_DATAX0);
  Wire.write(Y_Axis_Register_DATAX1);
  Wire.endTransmission(); // Ends the transmission and transmits the data from the two registers

  Wire.requestFrom(ADXLAddress, 2); // Request the transmitted two bytes from the two registers
  if (Wire.available() <= 2) { //
    Y0 = Wire.read(); // Reads the data from the register
    Y1 = Wire.read();
  }

  Serial.print("   Y0= "); Serial.print(Y0);  Serial.print("       Y1= "); Serial.print(Y1);

  delay(100);

  Wire.beginTransmission(ADXLAddress); // Begin transmission to the Sensor
  Wire.write(Z_Axis_Register_DATAX0);
  Wire.write(Z_Axis_Register_DATAX1);
  Wire.endTransmission(); // Ends the transmission and transmits the data from the two registers

  Wire.requestFrom(ADXLAddress, 6); // Request the transmitted two bytes from the two registers
  if (Wire.available() <= 6) { //
    Z0 = Wire.read(); // Reads the data from the register
    Z1 = Wire.read();
  }

  Serial.print("    Z0= "); Serial.print(Z0); Serial.print("         Z1= ");  Serial.print(Z1);

  delay(200);
}

Please help us to get the final X, Y, and Z.

Raw values of X and Y are somewhat correct, but Z always shows - 0.

Also, we are not able to calculate correctly X, Y, and Z to get the final G-force value.

Main point of datasheet :

The acceleration data of STK8321 is 12 bits and is given in two's complement format. The MSB in each axis will be stored in register XOUT2/YOUT2/ZOUT2 (0x03, 0x05, 0x07) individually, and the LSB will be stored in register XOUT1/YOUT1/ZOUT1 (0x02, 0x04, 0x06) individually. The NEW_X/NEW_Y/NEW_Z bit in register XOUT1/YOUT1/ZOUT1 (0x02, 0x04, 0x06) is used for new data flag, and it will be set to 1 if the data is updated, and reset if either the corresponding MSB or LSB is read. Reading the acceleration data registers shall always start with the LSB part due to the data protection function. When data protection function is enabled, the content of an MSB register will be updated by reading the corresponding LSB register.

why are you requesting 6 bytes? (you are only requesting 2 bytes for X and Y)

1 Like

sorry, but i tried more bytes too, it shows similar result, i'm just sure, that 2 byte should be for x & next 2 byte for y axis, i tried same for Z axis, but z always showing - 0

also, sorry I did my mistake 2 in codes as I was doing hit & trials, for Y-axis, it's 4, for Z, i tried 6
,
I tried , 2 bytes only for all 3 axes individually but z still - 0

also I'm not able to get final x, y, z from these raw , values coming between 0-255

have you tried requesting the 6 bytes in one go just to see if the chip auto-increases the requested register address?

#include <Wire.h>
const uint8_t STK8321 = 0x0F;
const uint8_t startRegister = 0x02;

void printAcceleration() {
  byte acceleration[6];
  Wire.beginTransmission(STK8321);
  Wire.write(startRegister);
  Wire.endTransmission();

  Wire.requestFrom(STK8321, 6);
  if (Wire.available() == 6) {
    Wire.readBytes(acceleration, 6);
    for (byte index = 0; index < 6; index ++) {
      Serial.print("0x");
      if (acceleration[index] < 0x10) Serial.write('0');
      Serial.print(acceleration[index], HEX);
      Serial.write(' ');
    }
    Serial.println();
  } else {
    Serial.println("I did not get 6 bytes back");
  }

}

void setup() {
  Serial.begin(115200); Serial.println();
}

void loop() {
  printAcceleration();
  delay(10);
}

there might be a bit of setup to do as well to configure the STK8321

After adding wire.begin()

here is output :

0x38 0xF8 0x1D 0xFD 0x01 0xBC
19:27:27.253 -> 0x50 0xF8 0x5E 0xFD 0xC0 0xBC
19:27:27.287 -> 0x78 0xF9 0xCF 0xFD 0xC8 0xBC
19:27:27.287 -> 0x28 0xF9 0x7B 0xFD 0x22 0xBC
19:27:27.287 -> 0x90 0xF9 0xA0 0xFD 0xD2 0xBD
19:27:27.323 -> 0x48 0xFB 0x58 0xFC 0x38 0xBF
19:27:27.323 -> 0x90 0xF9 0x39 0xFD 0xCA 0xBD
19:27:27.323 -> 0x60 0xF9 0xC8 0xFC 0x87 0xBD
19:27:27.323 -> 0xE0 0xF8 0x68 0xFD 0x0B 0xBD
19:27:27.358 -> 0x48 0xF8 0x2F 0xFD 0xE1 0xBC
19:27:27.358 -> 0x68 0xF8 0xA0 0xFD 0x7D 0xBC
19:27:27.358 -> 0xF0 0xF8 0xAC 0xFC 0x32 0xBC
19:27:27.393 -> 0xD0 0xF8 0x1A 0xFE 0xB6 0xBB
19:27:27.393 -> 0x48 0xF9 0x84 0xFD 0xE9 0xBC
19:27:27.429 -> 0xB8 0xF9 0x8D 0xFD 0x02 0xBD
19:27:27.429 -> 0xC0 0xF8 0x01 0xFD 0x98 0xBD
19:27:27.429 -> 0xE0 0xF7 0x81 0xFE 0x8E 0xBC
19:27:27.467 -> 0x40 0xFA 0xD2 0xFC 0xAF 0xBC
19:27:27.467 -> 0xF8 0xF7 0xA9 0xFD 0x85 0xBC
19:27:27.467 -> 0x58 0xF9 0x68 0xFD 0x0B 0xBD
19:27:27.467 -> 0x78 0xF9 0xD8 0xFD 0x6D 0xBC
19:27:27.467 -> 0xE0 0xF8 0xB8 0xFB 0x2C 0xBD
19:27:27.502 -> 0x58 0xF9 0xB0 0xFE 0xD1 0xBC
19:27:27.502 -> 0xE8 0xF9 0x77 0xFE 0x19 0xBC
19:27:27.538 -> 0xD0 0xF8 0x13 0xFD 0x3B 0xBC
19:27:27.538 -> 0x30 0xF9 0xA0 0xFD 0x2A 0xBC
19:27:27.538 -> 0xB0 0xF8 0x4C 0xFD 0x0B 0xBD
19:27:27.573 -> 0x08 0xFA 0xCB 0xFB 0x34 0xBD
19:27:27.573 -> 0x88 0xF8 0x81 0xFE 0xDF 0xBB
19:27:27.573 -> 0xF0 0xF8 0xF7 0xFC 0xA7 0xBC
19:27:27.573 -> 0x70 0xF8 0x58 0xFC 0xA7 0xBC
19:27:27.609 -> 0x70 0xF9 0x3C 0xFC 0x1B 0xBD
19:27:27.609 -> 0x30 0xF9 0xEE 0xFC 0x1B 0xBD
19:27:27.609 -> 0xC8 0xF8 0xAC 0xFC 0x54 0xBC
19:27:27.647 -> 0xB0 0xF8 0xBC 0xFD 0xAF 0xBC
19:27:27.647 -> 0x38 0xF8 0x97 0xFD 0x64 0xBC
19:27:27.647 -> 0xA0 0xF8 0x94 0xFE 0xD0 0xBC
19:27:27.683 -> 0xB0 0xF8 0x1D 0xFD 0x4C 0xBC
19:27:27.683 -> 0x88 0xF9 0x01 0xFD 0x64 0xBC
19:27:27.683 -> 0xA8 0xF8 0xB6 0xFC 0xB8 0xBC

when I convert these hex to integers, it gives between 0=255 ,
& Now I see, this way, Z is coming fine.

Now can you help me in converting the raw value to calculate G force?
my final aim is to calculate, impact detection or sudden movement.

Thanks for so much help.

You will need to study the STK8321 data sheet very carefully.

To collect and convert the X and Y data, something like this MIGHT work.

Make sure that signs are correct! You may have to check the sign bits of XH and YH, and fix the result.

actually only 4 bit shifting needed for both

good catch (I typed the code here, so ...)

seems you are getting some data.

a reading has 12 bits and the spec says that the data is organised this way


so for X you need to take the 4 upper bits of the first element you receive and they will be the low 4 bits of the result and concatenate them to the second element. that's what @jremington code is (almost) doing

  uint16_t XL = Wire.read();
  uint16_t XH = Wire.read();
  int16_t X  = (XH<<4) | (XL>>4);

you shift XH by 4 bits to the right to make room for the low 4 bits which you get by shifting XL to the left 4 by 4 bits

by storing the data directly into a 16 bit variable, the bit shifting and oring makes everything aligned

Thank you, guys!
I got everything working fine, now working on G-force to calculate, finally, I've to calculate car accident impact, hope this sensor could do. as they mentioned 10000 G,.
Also, I'm wondering about the Unit of this sensor output, I read, that I need to divide values by its sensitivity (default +/- 2 = total by 4 ) to get a unit mg/LSB.

as I'm using 3.3V esp32 so reading is 0-4096, so I think, I should convert volt to the corresponding value and then divide by sensitivity & multiply by g= 9.8 to get the G value,
can someone confirm if I'm correct as per: Converting values from an Accelerometer to G - ozzmaker.com

I understand I should read much in the datasheet, that I'm trying. I'll keep reading again n again.

Thank you so much for your help.

When held still, the sensor will report +/- 1 g, along any axis that is vertical.

Do that for both orientations, up and down, for each axis, and use the values you get to calibrate the accelerometer. Usually only offsets need to be subtracted, but they will be different for each axis.

Yes getting a bit, Thanks,

Hi,
I got an excel sheet for whole calculations from m manufacturer STK & now just wanna make sure, about getting the correct g-force. & also for others' reference

The above excel cells has the all required formulas.
Also attached screenshot of excel, in case the above link doesn't work.

uint16_t XL = Wire.read();
uint16_t XH = Wire.read();
int16_t X  = (XH<<4) | (XL>>4);

Same did for each axis then output :
3889 4062 3016
3890 4070 3025
3911 4081 3016
3896 4082 3030
3900 4076 3033

So the formula after using the above code shared by @J-M-L @jremington,

Should be ( as per excel ) :
int16_t final-X-G-force= x * 0.0009765625*9.087 m/s^2

just making sure, if nothing is wrong in the final g-force.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.