How to increase the writing speed on the SDCard

Hi,

I'm making some experiments using Arduino BLE 33 sense and the microphone. I developed this sample script that aims to store audio data in the SDCard.

#include <Arduino.h>
#include <PDM.h>
#include <SD.h>

// default number of output channels
static const char channels = 1;

// default PCM output frequency
static const int frequency = 16000;

// Buffer to read samples into, each sample is 16-bits
short sampleBuffer[512];

// Number of audio samples read
volatile int samplesRead;

void onPDMdata() {
	// Query the number of available bytes
	int bytesAvailable = PDM.available();

	// Read into the sample buffer
	PDM.read(sampleBuffer, bytesAvailable);

	// 16-bit, 2 bytes per sample
	samplesRead = bytesAvailable / 2;
}

File myFile;

void setup() {
	Serial.begin(9600);
	while (!Serial);

	Serial.print("Initializing SD card...");

	// see if the card is present and can be initialized:
	if (!SD.begin(4)) {
		Serial.println("Card failed, or not present");
		// don't do anything more:
		while (1);
	}
	Serial.println("card initialized.");
	// open the file. note that only one file can be open at a time,
	// so you have to close this one before opening another.
	myFile = SD.open("test.txt", FILE_WRITE);

	// Configure the data receive callback
	PDM.onReceive(onPDMdata);

	// Optionally set the gain
	// Defaults to 20 on the BLE Sense and 24 on the Portenta Vision Shield
	PDM.setGain(15);

	// Initialize PDM with:
	// - one channel (mono mode)
	// - a 16 kHz sample rate for the Arduino Nano 33 BLE Sense
	// - a 32 kHz or 64 kHz sample rate for the Arduino Portenta Vision Shield
	if (!PDM.begin(channels, frequency)) {
		Serial.println("Failed to start PDM!");
		while (1);
	}
}

bool finished = false;
void loop() {
//	// Wait for samples to be read
	if (samplesRead) {
		// Clear the read count
		samplesRead = 0;
		myFile.write((uint8_t*)sampleBuffer, sizeof(sampleBuffer));
	}

	unsigned long now = millis();
	if (now / 1000 > 20 && !finished) {
		Serial.println(now);
		finished = true;
		PDM.end();
		myFile.close();
	}
}

The SDCard is connected to a breadboard using external pull-ups of 47kOhm.

With this script, I noticed I've not enough writing speed in the SDCard to process all the MIC samples. So I would like to hear your suggestions on how can I increase the writing speed in order to don't lose any samples.

Regards

I've no experience of the BLE 33 board, but you should check to see what the current SPI clock frequency is and then if you can increased it. This should reduce the time taken to transfer the data to the SD card.

Note that you will likely have to buffer your audio data as the SD card will usually stop accepting data/commands briefly whilst it writes to its internal flash.

Try this way:

SD.begin(SPI_FULL_SPEED, 4);

Which MCU is being used?

What is the measurement period? Continuous? Audio, correct? Audio, you want around 44Khz sample rate, correct? Arduino Uno is limited to about 9.6Khz A BLE sample rate is limited to 35Khz sample rate. I'd not be blaming the SD card not being able to keep up, yet.

Hi Fernando,

I just did that. However, the SDCard is not detected. I'm wondering if I should reduce the resistors on the data lines. Currently, I'm using 47k, which can contribute to increasing the impedance on the line. What do you think?

Why not store every byte as it becomes available?

You could try to only test for byte availability in the ISR, not spending ISR time reading the number of bytes in the ISR.

What is the time taken to read the sample buffer?
Serial.println( micros());
PDM.read(sdfsdfas,adfdf);
Serial.println( micros());

I can't give you any information about resistors but you can try:

SD.begin(SPI_HALF_SPEED, 4);

I can't use a Serial.print() inside a ISR function. However, I extracted it to the main loop and it takes less than 1ms. Here's the output:

Example 1:

66245
66245

Example 2:

66246
66247

In HALF_SPEED it works. In FULL_SPEED not

I don't know what's the default speed in library but if it's QUARTER_SPEED now you has the double.

Make tests.

Now do a measurement of the speed of the SD write.

As, I'm not looking over your shoulder at your computer screen always post your latest code in a new post.

I just tested the SD Write speed.
Code:

void loop() {
	// Query the number of available bytes
	int bytesAvailable = PDM.available();

	if (bytesAvailable > 0) {
		Serial.println("__");
		Serial.println("Bytes:");
		Serial.println(bytesAvailable);
		Serial.println(micros());
		// Read into the sample buffer
		PDM.read(sampleBuffer, bytesAvailable);
		Serial.println(micros());
		Serial.println("Sd:");
		Serial.println(micros());
		myFile.write((uint8_t*)sampleBuffer, samplesRead * 2);
		Serial.println(micros());
	}
}

Output:

Initializing SD card...card initialized.
__
Bytes:
512
4521232
4521627
Sd:
4522231
4522413

This is very strange because the SDCard seems to be away faster.

So now the hunt is on for where the slowness is coming from. I'd also reduce serial prints to minimum and comment out the ones not being used as they slow down the code a slight bit.

Also I'd open the SD card for append instead of write.

And post the whole code. Snippets suck.