This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

SD Write Problem

Hi Everyone,

I am trying to record data from ADC to a SD card every 500ms using nrf52832. I am following the fatfs example. Before I had a problem whereby every approximately 10s I would lose a few samples from the ADC as shown by the figure below. I thought the problem was due to the SD card write latency as every 10s I observed an increase in current that usually lasted for around a few hundred milliseconds. After reading around I found that instead of opening and closing the file everytime I wanted to record data onto the SD card I should use f_sync() and this somehow fixed the problem.

But then I still observe this regular increase in write duration, so I was wondering if this is caused by the SD card write latency or is it due to software bugs. And how does the fatfs module handle this (ie when calling f_write) if it's due to SD write latency.

Thanks for the help. Bryan

White lines showing loss of ADC samples x-axis = sample number y-axis = voltage in uV

image description

Significant increase in write duration for the fifth peak

image description

White lines showing loss of ADC samples x-axis = sample number y-axis = voltage in uV


Update: I tested with another SD card and the problem with the missing samples came back. So f_sync did not solve the problem.


Update: 13/11/17

Code For writing to the SD card added.

In Main

while(1)
		{
			if( sampling_done == true)
			{
				sdWrite(data);
			}
			power_manage();
		}

In SAADC callback

void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
		
		if(p_event->type == NRF_DRV_SAADC_EVT_DONE)
		{			
				
					ret_code_t err_code;
					
					err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, NUM_OF_CHANNELS);
					APP_ERROR_CHECK(err_code);
					
					int16_t temp[4]={0};
					int8_t notification[8]={0};
					temp[0] = ADC_result_conversion(p_event->data.done.p_buffer[0]);
					temp[1] = ADC_result_conversion(p_event->data.done.p_buffer[1]);
					temp[2] = ADC_result_conversion(p_event->data.done.p_buffer[2]);
					temp[3] = ADC_result_conversion(p_event->data.done.p_buffer[3]);

			
					NRF_LOG_INFO("ADC event number: %d\r\n", (int)event_cnt);
					NRF_LOG_INFO("CH1: %d.%02d \r\n",	NRF_LOG_FLOAT(temp[0]));
					NRF_LOG_INFO("CH2: %d.%02d \r\n",	NRF_LOG_FLOAT(temp[1]));
					NRF_LOG_INFO("CH3: %d.%02d \r\n", NRF_LOG_FLOAT(temp[2]));
					NRF_LOG_INFO("CH4: %d.%02d \r\n", NRF_LOG_FLOAT(temp[3]));
									
					NRF_LOG_INFO("\n");
					NRF_LOG_FLUSH();
					memcpy( &data[0]+NUM_OF_CHANNELS*event_cnt, &temp[0], NUM_OF_CHANNELS*2);
					memcpy( &notification[0], &temp[0] , NUM_OF_CHANNELS*2);
					event_cnt++;
					
					if( event_cnt >= MAX_NUM_SAMPLES)
					{
						//sdWrite(data);
						sampling_done = true;
						event_cnt = 0;
					}
				
					ble_cus_custom_value_update(&m_cus, notification);
					sample_cnt++;		                                                            
    }
}

In sdWrite function

static void sdWrite(int16_t data[])
{
		
		FRESULT ff_result;
	  uint32_t bytes_written;
		char buffer[3000] = {0};
		int n=0;
		int counter=0;
	
   
		while(counter < MAX_NUM_SAMPLES)
		{
			n += sprintf(&buffer[n], "%d %d %d %d\r\n", data[NUM_OF_CHANNELS*counter], data[NUM_OF_CHANNELS*counter+1], data[NUM_OF_CHANNELS*counter+2], data[NUM_OF_CHANNELS*counter+3]); //format the data to ASCII
			counter++;
		}
			ff_result = f_write(&file, buffer , n , (UINT *) &bytes_written);
			if (ff_result != FR_OK)
			{
					NRF_LOG_INFO("Write failed\r\n.");
			}
			else
			{
				    //NRF_LOG_INFO("%d bytes written.\r\n", bytes_written);
			}
		 NRF_LOG_FLUSH();
		 f_sync(&file);
		
}
  • Writing to SD cards is often more difficult than people expect. Although I haven't used fatfs for a while (I've moved to Keil's FlashFS), the general principle is "write" your samples into a large as possible ring buffer stored in RAM. I presume your ADC samples are done in an ISR? Meanwhile in your main loop, continuously check this ring buffer. If there is a complete block (usually 512 bytes) to write out, call f_write to write the data out to the SD card.

  • What do you mean when you say you lose samples? Are they not written to SD card, or not sampled? Are you seeing any errors when writing to the card?

  • I think there are not being written to the SD card as if you look at the first graph, there is a gap(white line) at every 200 samples (10 seconds). And looking at the power consumption with a DC power analyzer(figure 2), I found that these gaps correspond to the sudden increase in write current of the SD card from normal spikes of around 20ms to a prolonged one of around 200ms.

  • Could you post the code showing how you write to SD card? Is the increased current only for nRF chip, or for whole circuit? Have you tried to debug to see if the chip is stuck on some blocking function when the current is increased, preventing sleep and blocking processing of events?

  • Hi Jorgen sorry for the late response but I have added the relevant code. I mainly debug in RTT viewer, I haven't tried debugging in Keil for this project yet. To measure the current, I am using a DC power analyzer attached to the input of the DC boost converter, so the current is increased for the whole circuit.

Related