cancel
Showing results for 
Search instead for 
Did you mean: 

LSM6DSV16BX Bone conduction feature

Ayse
Associate

I used LSM6DSV16BX for bone conduction detection. Based on the sample code and driver provided on github, everything related to the I2C works fine. But when it comes to the TDM part, I can not get any valid data from the tdm port.

my platform is esp32 s3 with esp idf framework, which support the tdm reading generally. And i use the code just like reading the data from multiple microphones with TDM in this project. It does not work ( or look like a sound wave). The tdm port gives the steady wave-like data but have nothing to do with the sound)

Is there any sample code about how to read/decode the tdm data from this module? and what is the correct data looks like?

1 ACCEPTED SOLUTION

Accepted Solutions

Hi @Ayse ,

The TDM interface seems correctly set. To be sure, you can read the registers with address:

  • 6C
  • 6D
  • 6E

And check with the datasheet if they are set as you like.

To read the data, it's possible to use the SAI interface. ST’s boards have the possibility to use the HAL, so function that abstract the hardware layer to simplify the development. You can connect the SAI interface in use to a DMA , so a memory space, and when the data is ready the HAL that manages the SAI interface call a function. When the function is called, you have the possibility to use memcpy to save the data into an array previously defined. The peripheral initialization connects the interface to the DMA so when the DMA is ready triggers a function defined as in the following example.

(Define and variable section)

#define FIFO_SIZE 1000

typedef union{

 struct{

   int16_t x;

   int16_t y;

   int16_t z;

 };

 uint8_t b8[6];

}out;

static out bs[FIFO_SIZE] = {0};

static int16_t bb_tdm[3];

static uint32_t i_w_tdm = 0;

(Outside main)

void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)

{

  memcpy(&bs[i_w_tdm].x,&bb_tdm[0],3);

   i_w_tdm = (i_w_tdm + 1);

}

 

(Inside main):

HAL_SAI_Receive_DMA(&hsai_BlockA1,(uint8_t*)bb_tdm,6);

 

The function called into the main starts the SAI interface and tells the peripheral to store the 6 blocks of data into the DMA at the address of bb_tdm.

Blocks are 6 instead of 3 because the address is incremented as uint8_t so an int16_t value need two increments to be copied.

When all data is transmitted correctly, the DMA calls the function defined outside the main. This function stores the data into the struct in position i_w_tdm using the memcpy instruction.

In this way the three channels of TDM data are stored and available for reading.

If this helps you, please mark my answer as "Best Answer" by clicking on the "Accept as Solution" button, this can be helpful for Community users to find this solution faster.

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.

View solution in original post

3 REPLIES 3
SimoneAsnaghi
ST Employee

Hi,

I don’t know in detail your hardware of choice but to solve your issue I’d suggest checking if the driver file you linked is configured correctly for your board of choice.

If it is correctly set what you should read from the TDM port is a stream of acceleration data, that you can save in a variable defined as a struct containing three elements:

 int16_t tdm_x, int16_t tdm_y and int16_t tdm_z.

At the end what you obtain is just an acceleration log on three axes, sampled at 8Khz or 16Khz. You can’t listen to the audio output if the board hasn’t an onboard audio codec linked to a headphone jack or to a digital audio output. If you want to visualize the soundwave you have to choose one of the three axes, based on your acquisition setup, and plot it.

If you want to listen to your TDM acquisition and your board has no audio codec, you can stream or save your data to your pc and transform the acceleration log into an audio file, using, for example, a small Python script.

Hope this can help.

Have a good day!

Simone

Hi Simone, thanks for your reply, I know with not codec i can only get the data wave. The driver and configuration is based on the code presented in the public repo : https://github.com/Passoll/LSM6DSV16BX_ESPIDFdriver, and the configuration is the example file  tdm_conf https://github.com/STMicroelectronics/STMems_Standard_C_drivers/blob/master/lsm6dsv16bx_STdC/examples/lsm6dsv16bx_tdm_conf.c  which I assume are officially viable solution. However, in this file, it did not mention how to read the tdm data, and only provide the code of reading the I2C.
And my code is as follows, I have difficulties reading the correct tdm data, which is shown as steady wave instead of some sound-like wave. I have followed the datasheet to seperate the valid data slots, with WCLK_8kHZ_BCLK_2048kHz, However, No matter how hard I move the sensor, it still do not have any reaction to my voice.
https://github.com/Passoll/LSM6DSV16BX_ESPIDFdriver/blob/main/main/bone_conduct_main.cpp 

By the way, is there any sample code that related to reading this tdm data? It will be greatly appreciated even that is not from esp32.

Hi @Ayse ,

The TDM interface seems correctly set. To be sure, you can read the registers with address:

  • 6C
  • 6D
  • 6E

And check with the datasheet if they are set as you like.

To read the data, it's possible to use the SAI interface. ST’s boards have the possibility to use the HAL, so function that abstract the hardware layer to simplify the development. You can connect the SAI interface in use to a DMA , so a memory space, and when the data is ready the HAL that manages the SAI interface call a function. When the function is called, you have the possibility to use memcpy to save the data into an array previously defined. The peripheral initialization connects the interface to the DMA so when the DMA is ready triggers a function defined as in the following example.

(Define and variable section)

#define FIFO_SIZE 1000

typedef union{

 struct{

   int16_t x;

   int16_t y;

   int16_t z;

 };

 uint8_t b8[6];

}out;

static out bs[FIFO_SIZE] = {0};

static int16_t bb_tdm[3];

static uint32_t i_w_tdm = 0;

(Outside main)

void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)

{

  memcpy(&bs[i_w_tdm].x,&bb_tdm[0],3);

   i_w_tdm = (i_w_tdm + 1);

}

 

(Inside main):

HAL_SAI_Receive_DMA(&hsai_BlockA1,(uint8_t*)bb_tdm,6);

 

The function called into the main starts the SAI interface and tells the peripheral to store the 6 blocks of data into the DMA at the address of bb_tdm.

Blocks are 6 instead of 3 because the address is incremented as uint8_t so an int16_t value need two increments to be copied.

When all data is transmitted correctly, the DMA calls the function defined outside the main. This function stores the data into the struct in position i_w_tdm using the memcpy instruction.

In this way the three channels of TDM data are stored and available for reading.

If this helps you, please mark my answer as "Best Answer" by clicking on the "Accept as Solution" button, this can be helpful for Community users to find this solution faster.

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.