Search code examples
c++cpointersbuffermemory-address

passing buffer pointers to read accelerometer data results in 2 out of 3 correct readings


I am working with accelerometers and reading FIFO data. Writing code in C/C++, Platformio Arduino framework for esp32. I created some functions to access FIFO data of all 3 axis:

void Get_FIFO_data_16(SPIClass *dev, uint8_t *header, int16_t *payload, uint16_t *timestamp) {
    const uint8_t packet_length = 16; //bytes
    uint8_t packet[packet_length] = {0};
      
    ReadRegBytes(dev, FIFO_DATA, packet, packet_length);
      
    *header = packet[0]; //header
    *payload = packet[1]<<8 | packet[2]; //acc X data
    
    //Serial.println(*payload);

    *(payload + 1) = packet[3]<<8 | packet[4]; //acc Y data
    
    //Serial.println(*(payload + 1));

    *(payload + 2) = packet[5]<<8 | packet[6]; //acc Z data
    *timestamp = packet[14]<<8 | packet[15];
  }


void Read_FIFO16_packet(int16_t* X_data, int16_t* Y_data, int16_t* Z_data, uint16_t *timestamp) {
  uint8_t header = 0;
  int16_t data[3] = {0};
  uint16_t TimeStamp = 0;

  iim_acc_obj.Get_FIFO_data_16(spi_device, &header, data, &TimeStamp);
    /*Header*/

    /********/
  *X_data = data[0]; //X_data is still correct
  *Y_data = data[1];
  *Z_data = data[2];

  *timestamp = TimeStamp;
}


void Read_FIFO_packet_16_IIM (int16_t *X_buffer, int16_t *Y_buffer, int16_t *Z_buffer, uint16_t *timestamp, uint16_t elements_to_read) {
  if (iim_acc_obj.Check_Who_am_I(spi_device) == true) {

    for (int i = 0; i < elements_to_read; i++) {
      Read_FIFO16_packet(X_buffer + i, Y_buffer + i, Z_buffer + i, timestamp + i);

      //Serial.println(*(X_buffer + i)/ 4095.00); //reading like this prints correct value
    }

  } else Serial.print("SPI Coms failed !");    
}


void Print_FIFO_Content_IIM(int16_t *X_data_buff, int16_t *Y_data_buff, int16_t *Z_data_buff, uint16_t *timestamp, uint32_t FIFO_len) {

  Serial.println("Timestamp    X data   Y data  Z data");
  int i = 0;

  for (uint32_t i = 0; i < FIFO_len; i++) {
    Serial.print(*(X_data_buff + i) / 4095.00);  //wrong data
    Serial.print("       ");
    Serial.print(*(Y_data_buff + i) / 4095.00); //correct data
    Serial.print("       ");
    Serial.print(*(Z_data_buff + i) / 4095.00); //correct data
    Serial.print("\n\r");
  }
  memset(X_data_buff, 0, sizeof(X_data_buff));  //reset buffer
  memset(Y_data_buff, 0, sizeof(Y_data_buff));  //reset buffer
  memset(Z_data_buff, 0, sizeof(Z_data_buff));  //reset buffer
}


///main.c///
 int16_t x_data[128] = {0};
 int16_t y_data[128] = {0};
 int16_t z_data[128] = {0};
...
...
Read_FIFO_packet_16_IIM(x_data, y_data, z_data, &timestamp, 128);
Print_FIFO_Content_IIM(x_data, y_data, z_data, &timestamp, 128);

Everything seem to work correctly until Read_FIFO_packet_16_IIM func, X axis data gets corrupted or lost and I get random fixed value every time I call this funcion (It should be around 0), but Y and Z axis return correct data (Y around 0 and Z around 1). My guess is that something gets mixed up with addresses, but why doing same thing works for 2 axis ?

Update: It seems that the last X buffer value (128 element) is returned correctly and prints out around -0.02 (which seems correct value).


Solution

  • Okay, so the problem was with timestamp, I was accidently sending uint16_t variable instead of array and this caused timestamp data to be written on X axis data, because their addresses are near each other (I declare them one after the other), I managed to catch this by writing constants instead of data[]:

    *X_data = 1 //data[0]; 
    *Y_data = 2 //data[1];
    *Z_data = 3 //data[2];
    

    And I got incrementing data in X_data and there is only one incrementing variable in this system, so when I found out who changed the values it was quite easy to find why it changes the values.