I have used the ideas here to improve the speed of logging data to SD cards. I wrote functions to print a numerical field to an SD card that are as much as five times faster than the standard Arduino print.
I am now able to log data from four analog pins on an Uno to an SD at 2000 Hz. This is 8000 ADC values per second. This is near the limit since each conversion takes about 110 microseconds.
I am using a small RTOS, Nil RTOS, written by Giovanni Di Sirio. I ported this RTOS to avr arduinos Google Code Archive - Long-term storage for Google Code Project Hosting..
I wrote a version of analogRead() that sleeps while the ADC conversion occurs. This saves about 90 microseconds of CPU time per conversion.
I have also modified SdFat so it no longer busy waits for flash programming in the SD to complete.
Here are test results for 16-bit unsigned fields and 32-bit float fields.
This test compares the standard print function
with printField. Each test prints 20,000 values.
Test of println(uint16_t)
Time 6.51 sec
File size 128.89 KB
Write 19.80 KB/sec
Test of printField(uint16_t, char)
Time 1.27 sec
File size 128.89 KB
Write 101.33 KB/sec
Test of println(double)
Time 17.17 sec
File size 160.00 KB
Write 9.32 KB/sec
Test of printField(double, char)
Time 3.56 sec
File size 160.00 KB
Write 44.94 KB/sec
Here are the test loops for the writes:
switch(test) {
case 0:
for (uint16_t i = 0; i < N_PRINT; i++) {
file.println(i);
}
break;
case 1:
for (uint16_t i = 0; i < N_PRINT; i++) {
file.printField(i, '\n');
}
break;
case 2:
for (uint16_t i = 0; i < N_PRINT; i++) {
file.println((double)0.0001*i, 4);
}
break;
case 3:
for (uint16_t i = 0; i < N_PRINT; i++) {
file.printField((double)0.0001*i, '\n', 4);
}
}
I have attached the implementation of printField().
PrintField.cpp (8.85 KB)