Hi community!
I'm trying to log analog data on my motorbike with the 6 ADC inputs of my Arduino MKR Zero. It already works using the SD.h library. The problem is that even using all the tips and tricks on the internet, I cannot write fast enough to the sd. I would need about 400 SPS on every ADC channel. The ADC seems to be fast enough, but the writing to the SD takes about 6-8 ms for all channels. When I flush/close to write the data it even takes about 20 ms. That's not yet good enough.
Now I thought of switching to the SDFat library. Does anyone have enough experience to tell if that's going to solve my problem, or have a good idea on how to solve it?
Ideally, I wouldn't want to switch to binary data, as I'd like to be able to read the log file.
Further, my code does not write a file with the SDFat library. What am I missing?
//General Libraries-------------
#include <Arduino.h>
#include <SPI.h>
#include <math.h>
#include <stdlib.h>
//MKRZero specific libraries----
#include "SdFat.h"
#include "sdios.h"
#include <RTCZero.h>
RTCZero rtc;
int rtccounter = 0;
byte seconds;
byte minutes;
byte hours;
byte day;
byte month;
byte year;
//set up variables using the SD utility library functions---------------------------
/*
Set DISABLE_CS_PIN to disable a second SPI device.
For example, with the Ethernet shield, set DISABLE_CS_PIN
to 10 to disable the Ethernet controller.
*/
const int8_t DISABLE_CS_PIN = -1;
// SDCARD_SS_PIN is defined for the built-in SD on some boards.
const uint8_t SD_CS_PIN = 28;
// Try to select the best SD card configuration.
#if HAS_SDIO_CLASS
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#elif ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(4))
#else // HAS_SDIO_CLASS
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SD_SCK_MHZ(4))
#endif // HAS_SDIO_CLASS
// SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h,
// 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT.
#define SD_FAT_TYPE 3
#if SD_FAT_TYPE == 0
SdFat sd;
File myFile;
#elif SD_FAT_TYPE == 1
SdFat32 sd;
File32 myFile;
#elif SD_FAT_TYPE == 2
SdExFat sd;
ExFile myFile;
#elif SD_FAT_TYPE == 3
SdFs sd;
FsFile myFile;
#else // SD_FAT_TYPE
#error Invalid SD_FAT_TYPE
#endif // SD_FAT_TYPE
String dataString = "";
String Header = "";
//AnalogPins
int sP0 = A0;
int sP1 = A1;
int sP2 = A2;
int sP3 = A3;
int sP4 = A4;
int sP5 = A5;
int sP6 = A6;
//DigitalPins
int sP7 = 0;
int sP8 = 1;
//Variables
uint16_t s0 = 0; // variable to store the value coming from the sensor
uint16_t s1 = 0;
uint16_t s2 = 0;
uint16_t s3 = 0;
uint16_t s4 = 0;
uint16_t s5 = 0;
uint16_t s6 = 0;
//uint16_t s7 = 0;
//uint16_t s8 = 0;
//Timer
int timer0 = 0;
unsigned int time0 = 0;
//Samplerate
int s_rate0 = 3000;
int s_rate1 = 100;
//Counter
int filen = 0;
int fileCountOnSD = 0; // for counting files
//Funktionen
void printDirectory(File dir, int numTabs) {
while (true) {
File entry = dir.openNextFile();
if (! entry) {
// no more files
break;
}
for (uint8_t i = 0; i < numTabs; i++) {
Serial.print('\t');
}
Serial.print(entry.name());
// for each file count it
fileCountOnSD++;
if (entry.isDirectory()) {
Serial.println("/");
printDirectory(entry, numTabs + 1);
} else {
// files have sizes, directories do not
Serial.print("\t\t");
Serial.println(entry.size(), DEC);
}
entry.close();
}
}
// int smooth(int x){ //Pin übergeben
// int i;
// uint16_t value = 0;
// int numReadings = 12;
// for (i = 0; i < numReadings; i++){
// // Read light sensor data.
// value = value + analogRead(x);
// }
// // Take an average of all the readings.
// value = value / numReadings;
// return value;
// }
void setup() {
//Serial.begin(115200);
analogReadResolution(12); //10 bit showed no imrovement in terms of sps
//pinMode(sP7, INPUT);
//pinMode(sP8, INPUT);
//Initialisieren SD Karte------------------------------------
sd.cardBegin(SD_CONFIG);
//Count files on sd
//myFile = SD.open("/");
myFile.open("/");
printDirectory(myFile, 0);
filen = fileCountOnSD;
if (sd.exists(String(filen) + "DATA.txt")) {
return;
} else {
myFile = sd.open(String(filen) + "DATA.txt", FILE_WRITE);
myFile.close();
}
Header = ("Time_rel.,A0,A1,A2,A3,A4,A5,A6");
myFile = sd.open(String(filen)+ "DATA.txt", FILE_WRITE);
if (myFile) {
myFile.println(Header);
myFile.close();
}
timer0 = millis();
time0 = millis();
rtc.begin(); // initialize RTC
/* Change these values to set the current initial time */
seconds = 0;
minutes = 0;
hours = 0;
/* Change these values to set the current initial date */
day = 1;
month = 1;
year = 2021;
rtc.setTime(hours, minutes, seconds);
rtc.setDate(day, month, year);
}
void loop() {
/*
If you replace FILE_WRITE with O_WRITE | O_CREAT and control when flush is called you can increase the speed by a large factor.
*/
myFile = sd.open(String(filen) + "DATA.txt", O_WRITE| O_APPEND | O_CREAT);
for (uint8_t i = 0; i < 100; i++) {
//if ((millis() - timer0) > 2) {
s0 = analogRead(sP0);
s1 = analogRead(sP1);
s2 = analogRead(sP2);
s3 = analogRead(sP3);
s4 = analogRead(sP4);
s5 = analogRead(sP5);
s6 = analogRead(sP6);
time0 = millis();
//s7 = digitalRead(sP7);
//s8 = digitalRead(sP8);
//Save the values on SD
dataString = String(time0) + ',' + String(s0) + "," + String(s1) + "," + String(s2) + "," +
String(s3) + "," + String(s4) + "," + String(s5) + ","
+ String(s6);
myFile.println(dataString);
//}
timer0 = millis();
}
//myFile.flush();
myFile.close();
}