Teensy 4.1 SD Printing Issues

Dave18

New member
Hello, I am new to using teensy and am trying to use it as a data logger for a 20kHz signal. Due to the high frequency, to sample fast enough, I found I need to store the data in a data buffer, then write it to the SD card. However that is where I run into my issue. Each time the program goes to add the full data buffer to the SD card, it writes over the data that was there from before. I have tried seeking to the end and opening the file is APEND mode, but neither are successful at having it start at the end of the SD card. Is there any other way to have the new data printed at the end of the SD card rather than over the existing data?

Code:
#include <SD.h>
#include <ADC.h>

#define chipSelect BUILTIN_SDCARD // Should highlight if you have Teensy 3.5/3.6/4.0 selected
int sdLED = 25;                  // LED pin to indicate SD status
int signalPin = A0;               // Assuming your input pin is A0

File datalog;
char filename[] = "SDCARD00.csv";
bool sdActive = false;

ADC *adc = new ADC();

const unsigned long samplingDuration = 1000000; // 1 second in microseconds
unsigned long lastSampleTime = 0;
String dataBuffer = "";

///////// Functions ////////////
// void sdSetup()
// logData(String Data)

void setup()
{
  Serial.begin(9600);
  Serial.print("Starting SD setup... ");
  sdSetup();
  Serial.println("SD setup complete");
}

void loop()
{
  while (true)
  {
    unsigned long currentTime = micros();

    int numSamples = 2024;
    for (int i = 0; i < numSamples; i++)
    {
      unsigned long currentTime = micros();
      int sensorValue = adc->adc0->analogRead(signalPin);
      dataBuffer += String(currentTime) + "," + String(sensorValue) + "\n";
    }

    // Check if the sampling duration has passed
    if (currentTime - lastSampleTime >= samplingDuration)
    {
      logData(dataBuffer);
      lastSampleTime = currentTime;
    }
  }
}

void sdSetup()
{
  pinMode(chipSelect, OUTPUT);
  if (!SD.begin(chipSelect))
  {
    Serial.println("Card failed, or not present");
    for (int i = 1; i < 20; i++)
    {
      digitalWrite(13, HIGH);
      digitalWrite(sdLED, LOW);
      delay(100);
      digitalWrite(13, LOW);
      digitalWrite(sdLED, HIGH);
      delay(100);
    }
  }
  else
  {
    Serial.println("Card initialized.\nCreating File...");
    for (byte i = 0; i < 100; i++)
    {
      filename[6] = '0' + i / 10;
      filename[7] = '0' + i % 10;
      if (!SD.exists(filename))
      {
        datalog = SD.open(filename, FILE_WRITE);
        sdActive = true;
        Serial.println("Logging to: " + String(filename));
        delay(1000);
        break;
      }
    }
    if (!sdActive)
    {
      Serial.println("No available file names; clear SD card to enable logging");
      delay(5000);
    }
  }

  adc->adc0->setAveraging(4); // Set the number of averages
  adc->adc0->setResolution(12); // Set the resolution of the ADC
  adc->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED); // Set high-speed conversion
  adc->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED); // Set high-speed sampling rate
}

void logData(String Data)
{
  if (sdActive)
  {
    // Check if the file exists
    if (SD.exists(filename))
    {
      // If the file exists, open it in write mode and move to the end of the file
      datalog = SD.open(filename, FILE_WRITE);
      datalog.seek(datalog.size());
    }
    else
    {
      // If the file doesn't exist, open it
      datalog = SD.open(filename, FILE_WRITE);
      datalog.println("Time,Value"); // Assuming your CSV has headers
    }

    datalog.print(Data);
    datalog.flush(); // Ensure data is written to the SD card
    datalog.close(); // Close the file
  }
}

Could it be an issue with having Arduino SD libraries on my computer?
 
Last edited:
If you're interested in greater speed and efficiency, see the SdFat library example TeensySdioLogger. It shows how to greatly increase throughput by pre-allocating the file, leaving the file open, using SdFat's RingBuf, and always writing whole sectors (512 bytes). Since your sample rate is 20 kHz (50 us intervals), you can use the isBusy() function to avoid blocking in SD writes, which can block for 40 ms or more, depending on SD card type. The buffer must be large enough to hold 40+ ms of data. I generally use 50 ms.
 
Back
Top