I'm using ESP8266 at speed of 160 MHz to record ADC results into SD card, I need to do this at rate of 8 KHz. Means that i should save it on the SD Card or i'll run out of memory before 4 Sec passes. I used timer1 to trigger sampling, but my problem is that surprisingly ESP8266 can not do this fast enough and the maximum sampling rate i get is about 7 KHz. I also tried to write data in ESP8266 Flash using littleFS in hope of acceleration but there was no luck. Here is my code:
#include <SPI.h>
#include <SD.h>
File dataFile;
int flag = 0;
int count = 0, level = 0, se_count = 0;
void inline analogReader() // Sampling and Recording processed which is done sequentially :(
{
uint16_t dataByte = (uint16_t) analogRead(A0);
dataFile.write((uint8_t*) &adcBuf, 2);
}
void ICACHE_RAM_ATTR onTimerISR() { // Timer sets the flag every 0.125 MS
flag = 1;
}
void setup() {
pinMode(A0, INPUT);
pinMode(D0, OUTPUT);
Serial.begin(115200);
if (!SD.begin(D0)) {
Serial.println("Card failed, or not present");
// don't do anything more:
return;
}
Serial.println("card initialized.");
File root = SD.open("/");
if (SD.exists("real_test.bin"))
{
SD.remove("real_test.bin");
}
dataFile = SD.open("real_test.bin", FILE_WRITE);
if (dataFile) {
Serial.println("File created!");
}
else
{
Serial.println("Failed to create file!");
return;
}
// Setting the timer so that timer interrupt fires every 0.125 MS
timer1_attachInterrupt(onTimerISR);
timer1_enable(TIM_DIV1/*from 80 Mhz*/, TIM_EDGE/*TIM_LEVEL*/, TIM_LOOP/*TIM_SINGLE*/);
timer1_write(10000); /* ( 80 / 1 ) * 125 */
}
void loop() {
if (flag) // To check whether its time to sampling or not, because of the low speed of the process
{ // The flag is set again before one iteration ends.
flag = 0;
if (se_count < 10)
analogReader();
count++;
if (count == 8000) // When 8000 sample & write process done notify using serial monitor. (it is
always more that 1 Sec. for example 1.3 Sec.)
{
count = 0;
level = !level;
Serial.println(level);
se_count++;
if (se_count == 10) // When we done 8000 * 10 sample & write we close the file. it supposed to
// be done in almost 10 sec. but it takes more time in practice. for
// example 13 Sec.
{
dataFile.close();
Serial.println("Write ended");
}
}
}
}
I even used a faster method system_adc_read_fast(buf, num, clk_div) that is available in ESP-SDK, So i'm desperately seeking for one or two of approaches bellow if possible:
- To use a non-blocking approach: If there is any possibility to hand SD writing to DMA so that i only fill the ADC buffer for DMA, or an interrupt for ADC complete so that i write to SD and when interrupt fired put the result in the buffer and return back to SD writing.
- Yet faster approach for both ADC sampling and writing: Can i increase the SD write speed of SD library? for example by configuring SPI for maximum speed rate.
I also tried SDFat library but it does not recognize my SD Card. The whole process is odd to me that even by using a 160 MHz CPU and hardware i can not record ADC data at rate of 8000 Sample/S. I have TIME limitation so please help me.
Any suggestion is appreciated. Thanks in advance.