Write 20 Bit Sensor Data on SD Card

Hello together,

this is my first project using a microcontroller so this might be a question that is obvious for some of you.

I want to connect two three-axis accelerometer to an Arduino Nano and write the Data on a micro SD-Card.

The Sensor Data Sheet is attached to this post but here are some informations: The sensor Data has a size of 20 bit (for each axis) and an output Data Rate of 4 kHz and I want to connect it to the Arduino via SPI (together, this makes 6 axis * 20 bit *4,000 Hz = 480 kb/s). Because the Arduino Nano only has 8 bit, i was wondering if it is able to process the Sensor Data fast enough so I don't loose any Data. Or should I use the Arduino Nano 33 IOT, which has 32 bit or even an Arduino Uno?

Thank you for helping me :slight_smile:

ADXL356-357.pdf (1.32 MB)

Nano and Uno have the same 8-bit chip, so no advantage to Uno. Arduino based on 32-bit chips must still deal with SPI data 8 bits at a time, but they have faster clock speeds and some even have DMA which can greatly speed up transfer of data over SPI. Some have 2 SPI ports, so that the sensor and sd card do not have to share the same data bandwidth.

Theoretically, a 16MHz Nano can transfer SPI data at up to 8Mb/s. In practice, it is far slower because the CPU cannot supply data to or store data from the SPI port quickly enough.

I would recommend beginning with the Nano to see if it is fast enough. If it is not, post your code here and we may be able to find ways to speed it up.

If you look into SPI you will see that SPI only transfers 8 bits at a time and the arriving bits are assembled.

An Uno is an 8 bit machine.

Here is a ESP32 API function to write 8 bits with DMA and background data transfer enabled.

int fWriteSPIdata8bits( spi_device_handle_t &h, int _address, int _sendData )
{
  uint8_t address =  _address;
  uint8_t sendData = _sendData;
  esp_err_t intError;
  spi_transaction_t trans_desc;
  trans_desc = { };
  trans_desc.addr =  0;
  trans_desc.cmd = 0;
  trans_desc.flags = 0;
  trans_desc.length = (8 * 2); // total data bits
  trans_desc.tx_buffer = txData;
  trans_desc.rxlength = 0 ; // Number of bits NOT number of bytes
  trans_desc.rx_buffer = NULL;
  txData[0] = address  & 0x7F;
  txData[1] = sendData;
  intError = spi_device_transmit( h, &trans_desc);
  return intError;
} // void fWriteSPIdata8bits(  spi_device_handle_t &h, uint8_t address, uint8_t sendData )

And here is a ESP32 SPI API function to read 16 bits with DMA and background data transfer enabled.

void fReadSPIdata16bits( spi_device_handle_t &h, int _address )
{
  uint8_t address = _address;
  esp_err_t intError;
  spi_transaction_t trans_desc;
  trans_desc = { };
  trans_desc.addr =  0;
  trans_desc.cmd = 0;
  trans_desc.flags = 0;
  trans_desc.length = (8 * 3); // total data bits
  trans_desc.tx_buffer = txData;
  trans_desc.rxlength = 8 * 2 ; // Number of bits NOT number of bytes
  trans_desc.rx_buffer = rxData;
  txData[0] = address | 0x80;
  intError = spi_device_transmit( h, &trans_desc);
  low = rxData[0]; high = rxData[1];
} // void fSendSPI( uint8_t count, uint8_t address, uint8_t DataToSend)

You can see an 8 bit transaction needs two buckets of 8 bit data one bucket for the device register to be read and one bucket for the 8 bit reply. You can see the 16 bit reply needs 3 8 bit buckets, 1 bucket to hold the address register and 2 buckets to hold the reply.

Your 8 bit and 16 bit and so forth and so on bit buckets should be taken care of through the library used or, if you do it yourself, the programmer.

And thrown in for extra measure. This is wrote for a NLX90393 a 20 bit device and the code SPI API code to send 20 bits with DMA and background data transfer enabled.

int fWriteSPIdata32bits( spi_device_handle_t &h, int _sendData0, int _sendData1, int _sendData2, int _sendData3 )
{
  // uint8_t address =  _address;
  // uint8_t sendData = _sendData;
  esp_err_t intError;
  spi_transaction_t trans_desc;
  trans_desc = { };
  trans_desc.addr =  0;
  trans_desc.cmd = 0;
  trans_desc.flags = 0;
  trans_desc.length = (8 * 4); // total data bits
  trans_desc.tx_buffer = txData;
  trans_desc.rxlength = 0 ; // Number of bits NOT number of bytes
  trans_desc.rx_buffer = NULL;
  txData[0] = (uint8_t)_sendData0; // command bits
  txData[1] = (uint8_t)_sendData1; // lower bits
  txData[2] = (uint8_t)_sendData2; // higher bits
  txData[3] = (uint8_t)_sendData3; // address
  intError = spi_device_transmit( h, &trans_desc);
  return intError;
} // void fWriteSPIdata8bits(  spi_device_handle_t &h, uint8_t address, uint8_t sendData )

And you can load up a device library and look at the code to see how the code author does the thing.

Thank you for your answers so far. I think i got a better understanding of how the SPI Data transfer works now.
I will try the setup with the Arduino Nano and if that's not fast enough I will post my code.