writing binary file on SD card in Teency 3.5

Status
Not open for further replies.

Lorenzo

Well-known member
Hello forum!

Where can I found a complete example on how to write a binary file on SD card in Teency 3.5?

Thank you very much in advance,
Lorenzo
 
Writing binary data works basically the same as ordinary text, except you use myfile.write(data, length) rather than myfile.print().

At least one example can be found in File > Examples > Audio > Recorder. Admittedly this example is mostly about audio, but inside it you can find code which collects up groups of audio samples as binary data in a buffer, then writes it to the file.
 
Thank you very much Paul. Tomorrow I will try it on my Teency 3.5. :)

I have just a little question:

If I would like to write on the SD card 8 values (or more) which are acquired at each loop, how can I store them in a queue in order to fill the 512 byte buffer?
 
Last edited:
I have tryed the following code to write 512 bytes on the SD card but there is no file on the SD card.
The 512 bytes (SDPacket) are composed by 16 packets (dataPacket) of 30 bytes each.
Why is it not writing anything on the card? Thank you for any suggestions :)

Code:
#define BYTE_DATA_PACKET 30
uint8_t dataPacket[BYTE_DATA_PACKET];


#define BYTE_SD_PACKET 512
uint8_t SDPacket[BYTE_SD_PACKET];

int16_t packets_number=17; //17
int16_t packets_counter=0;

#include "SdFat.h"
SdFat sd;
File myFile;
unsigned long counter=0;
unsigned long timer;



//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void setup() 
{
  Serial.begin(115200);
  
  for(uint i=0;i<sizeof(dataPacket);i++) dataPacket[i]=0x00;
  for(uint i=0;i<sizeof(SDPacket);i++) SDPacket[i]=0x00;

  
  myFile = sd.open("test000.bin", FILE_WRITE);

}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


void loop() 
{
  timer=millis();
  counter++;
  
  noInterrupts();
  unsigned long timer_local=timer; 
  unsigned long counter_local=counter; 
//  unsigned long timer_local=12345; 
//  unsigned long counter_local=87654; 
  unsigned long ENC_1_pos_local = 1111; 
  unsigned long ENC_2_pos_local = 2222; 
  unsigned long ENC_1_omega_local = 3333; 
  unsigned long ENC_2_omega_local = 4444; 
  float LC_1_local = 5555;
  float LC_2_local = 6666;
  float POT_pos_local = 7777;
  float POT_punto_local = 8888;
  interrupts();

  createDataPacket(dataPacket,
  timer_local,
  counter_local,
  ENC_1_pos_local,
  ENC_2_pos_local,
  ENC_1_omega_local,
  ENC_2_omega_local,
  LC_1_local,
  LC_2_local,
  POT_pos_local,
  POT_punto_local);

  
  if (packets_counter<packets_number)
  {
    for(uint8_t idx=0;idx<BYTE_DATA_PACKET;idx++)
    {
      SDPacket[packets_counter+idx]=dataPacket[idx];
    } 

    /////////////////
                for(uint8_t idx=0;idx<BYTE_DATA_PACKET;idx++)
                {
                Serial.print(SDPacket[packets_counter+idx]);
                }
    //////////////////
    Serial.println();
    Serial.println(packets_counter);
    Serial.println();
    packets_counter++;
  }

  if (packets_counter==packets_number)
  {
    packets_counter=0;
    //myFile = sd.open("test000.bin", FILE_WRITE);


    
    myFile.write(SDPacket,BYTE_SD_PACKET);
    //myFile.close();
  }
  
  
  delay(50);
}


//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void createDataPacket(uint8_t *dataPacket,
unsigned long timestamp,
unsigned long cycles,
unsigned long encoder_1_pos,
unsigned long encoder_2_pos,
unsigned long encoder_1_omega,
unsigned long encoder_2_omega,
float load_cell_1,
float load_cell_2,
float pot_pos,
float pot_punto)
{
  uint8_t* pointer;
  int16_t val;
  
  // START
  dataPacket[0]=0x01;
  dataPacket[1]=0x02;
  dataPacket[2]=0x03;

  //Timestamp
  //val=int16_t(timestamp);
  pointer=(uint8_t*)&timestamp;
  dataPacket[3]=pointer[0];
  dataPacket[4]=pointer[1];
  dataPacket[5]=pointer[2];
  dataPacket[6]=pointer[3];
  
  //Cycles
  //val=int16_t(cycles);
  pointer=(uint8_t*)&cycles;
  dataPacket[7]=pointer[0];
  dataPacket[8]=pointer[1];
  dataPacket[9]=pointer[2];
  dataPacket[10]=pointer[3];
  
  //Encoder 1 POS
  val=int16_t(encoder_1_pos);
  pointer=(uint8_t*)&val;
  dataPacket[11]=pointer[0];
  dataPacket[12]=pointer[1];
  
  //Encoder 2 POS
  val=int16_t(encoder_2_pos);
  pointer=(uint8_t*)&val;
  dataPacket[13]=pointer[0];
  dataPacket[14]=pointer[1];

  //Encoder 1 OMEGA
  val=int16_t(encoder_1_omega);
  pointer=(uint8_t*)&val;
  dataPacket[15]=pointer[0];
  dataPacket[16]=pointer[1];
  
  //Encoder 2 OMEGA
  val=int16_t(encoder_2_omega);
  pointer=(uint8_t*)&val;
  dataPacket[17]=pointer[0];
  dataPacket[18]=pointer[1];
  
  //Load cell 1
  val=int16_t(load_cell_1);
  pointer=(uint8_t*)&val;
  dataPacket[19]=pointer[0];
  dataPacket[20]=pointer[1];
  
  //Load cell 2
  val=int16_t(load_cell_2);
  pointer=(uint8_t*)&val;
  dataPacket[21]=pointer[0];
  dataPacket[22]=pointer[1];

  //Potentiometer_pos
  val=int16_t(pot_pos);
  pointer=(uint8_t*)&val;
  dataPacket[23]=pointer[0];
  dataPacket[24]=pointer[1];
 
  //Potentiometer_punto
  val=int16_t(pot_punto);
  pointer=(uint8_t*)&val;
  dataPacket[25]=pointer[0];
  dataPacket[26]=pointer[1];
  
  // STOP
  dataPacket[27]=0x04;
  dataPacket[28]=0x05;
  dataPacket[29]=0x06;
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
I have tryed the following code to write 512 bytes on the SD card but there is no file on the SD card.
The 512 bytes (SDPacket) are composed by 16 packets (dataPacket) of 30 bytes each.
Why is it not writing anything on the card? Thank you for any suggestions :)
Too little info;

maybe your sdCard is not formatted correctly e.g. exFAT (typically for 64GB cards) is not supported.
check if myFile is really opened, if value is zero then not opened.
Finally close file after you are done.
 
Too little info;

maybe your sdCard is not formatted correctly e.g. exFAT (typically for 64GB cards) is not supported.
check if myFile is really opened, if value is zero then not opened.
Finally close file after you are done.

Thank you very much WMXZ.
I checked the file to be opened and I have also implemented the closing of the file after a number of cycles.
In the previous script also the storage of DataPackets in SDPacket was wrong.
Now the code works and I can write data on my SD card.

Here it is the final version:

Code:
#define BYTE_DATA_PACKET 30
uint8_t dataPacket[BYTE_DATA_PACKET];


#define BYTE_SD_PACKET 512
uint8_t SDPacket[BYTE_SD_PACKET];

int16_t packets_number=17; //17
int16_t packets_counter=0;
int16_t close_file_counter=0;

//#include "SdFat.h"
#include "SD.h"
//SD sd;
File myFile;
unsigned long counter=0;
unsigned long timer;

#define SDCARD_CS_PIN    BUILTIN_SDCARD

char LogFileName[] = "test003.bin";

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void setup() 
{
  Serial.begin(115200);
  
  for(uint i=0;i<sizeof(dataPacket);i++) dataPacket[i]=0x00;
  for(uint i=0;i<sizeof(SDPacket);i++) SDPacket[i]=0x00;

  if (!(SD.begin(SDCARD_CS_PIN))) {
    // stop here if no SD card, but print a message
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
  
  

}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


void loop() 
{
  timer=millis();
  counter++;
  
  noInterrupts();
  unsigned long timer_local=timer; 
  unsigned long counter_local=counter; 
//  unsigned long timer_local=12345; 
//  unsigned long counter_local=87654; 
  unsigned long ENC_1_pos_local = 1111; 
  unsigned long ENC_2_pos_local = 2222; 
  unsigned long ENC_1_omega_local = 3333; 
  unsigned long ENC_2_omega_local = 4444; 
  float LC_1_local = 5555;
  float LC_2_local = 6666;
  float POT_pos_local = 7777;
  float POT_punto_local = 8888;
  interrupts();

  createDataPacket(dataPacket,
  timer_local,
  counter_local,
  ENC_1_pos_local,
  ENC_2_pos_local,
  ENC_1_omega_local,
  ENC_2_omega_local,
  LC_1_local,
  LC_2_local,
  POT_pos_local,
  POT_punto_local);

  
  if (packets_counter<packets_number)
  {
    for(uint8_t idx=0;idx<BYTE_DATA_PACKET;idx++)
    {
      SDPacket[packets_counter*BYTE_DATA_PACKET+idx]=dataPacket[idx];
    } 

    /////////////////
                for(uint8_t idx=0;idx<BYTE_DATA_PACKET;idx++)
                {
                Serial.print(SDPacket[packets_counter+idx]);
                }
    //////////////////
    Serial.println();
    Serial.println(packets_counter);
    Serial.println();
    packets_counter++;
  }

  if (packets_counter==packets_number)
  {
    packets_counter=0;

    if (close_file_counter<1)
    {
    myFile = SD.open(LogFileName, FILE_WRITE);
    }
    else
    {
      if ((close_file_counter % 10) ==0 ) //roughly every 10*512 bytes
      {
        myFile.close();
        myFile = SD.open(LogFileName, FILE_WRITE);
        myFile.write(SDPacket,BYTE_SD_PACKET);
      }
      else
      {
        myFile.write(SDPacket,BYTE_SD_PACKET);
      }
    }
    close_file_counter++;
    
  }
  
  
  delay(50);
}


//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void createDataPacket(uint8_t *dataPacket,
unsigned long timestamp,
unsigned long cycles,
unsigned long encoder_1_pos,
unsigned long encoder_2_pos,
unsigned long encoder_1_omega,
unsigned long encoder_2_omega,
float load_cell_1,
float load_cell_2,
float pot_pos,
float pot_punto)
{
  uint8_t* pointer;
  int16_t val;
  
  // START
  dataPacket[0]=0x01;
  dataPacket[1]=0x02;
  dataPacket[2]=0x03;

  //Timestamp
  //val=int16_t(timestamp);
  pointer=(uint8_t*)&timestamp;
  dataPacket[3]=pointer[0];
  dataPacket[4]=pointer[1];
  dataPacket[5]=pointer[2];
  dataPacket[6]=pointer[3];
  
  //Cycles
  //val=int16_t(cycles);
  pointer=(uint8_t*)&cycles;
  dataPacket[7]=pointer[0];
  dataPacket[8]=pointer[1];
  dataPacket[9]=pointer[2];
  dataPacket[10]=pointer[3];
  
  //Encoder 1 POS
  val=int16_t(encoder_1_pos);
  pointer=(uint8_t*)&val;
  dataPacket[11]=pointer[0];
  dataPacket[12]=pointer[1];
  
  //Encoder 2 POS
  val=int16_t(encoder_2_pos);
  pointer=(uint8_t*)&val;
  dataPacket[13]=pointer[0];
  dataPacket[14]=pointer[1];

  //Encoder 1 OMEGA
  val=int16_t(encoder_1_omega);
  pointer=(uint8_t*)&val;
  dataPacket[15]=pointer[0];
  dataPacket[16]=pointer[1];
  
  //Encoder 2 OMEGA
  val=int16_t(encoder_2_omega);
  pointer=(uint8_t*)&val;
  dataPacket[17]=pointer[0];
  dataPacket[18]=pointer[1];
  
  //Load cell 1
  val=int16_t(load_cell_1);
  pointer=(uint8_t*)&val;
  dataPacket[19]=pointer[0];
  dataPacket[20]=pointer[1];
  
  //Load cell 2
  val=int16_t(load_cell_2);
  pointer=(uint8_t*)&val;
  dataPacket[21]=pointer[0];
  dataPacket[22]=pointer[1];

  //Potentiometer_pos
  val=int16_t(pot_pos);
  pointer=(uint8_t*)&val;
  dataPacket[23]=pointer[0];
  dataPacket[24]=pointer[1];
 
  //Potentiometer_punto
  val=int16_t(pot_punto);
  pointer=(uint8_t*)&val;
  dataPacket[25]=pointer[0];
  dataPacket[26]=pointer[1];
  
  // STOP
  dataPacket[27]=0x04;
  dataPacket[28]=0x05;
  dataPacket[29]=0x06;
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
I have one more question:

Is there a way to write binary data on the SD card without closing the file at the end of the writing?
The opening and closing operations are becoming really time-consuming if I would like to increase the writing frequency (for example at 1 or 2 kHz).

In case the answer is not, do you have any suggestion on how to manage the opening and closing operations in order to reduce the computational time?

Thank you very much :)
 
There are a few ways to do this, but a place to start is looking at the sdfat low latency example. If you search the forum, you will find many other example of people writing a lot of data very quickly to the sd card.
https://github.com/greiman/SdFat-be...xamples/LowLatencyLogger/LowLatencyLogger.ino
https://github.com/tni/teensy-samples/blob/master/SdFatSDIO_low_latency_logger.ino (specific to teesny 3.5/3.6)

But if you need low latency, you need to allocate write blocks, get your data, stop recording, truncate file. With this method you can record >10kHz.
 
I have one more question:

Is there a way to write binary data on the SD card without closing the file at the end of the writing?
The opening and closing operations are becoming really time-consuming if I would like to increase the writing frequency (for example at 1 or 2 kHz).

In case the answer is not, do you have any suggestion on how to manage the opening and closing operations in order to reduce the computational time?

Thank you very much :)

You can write to uSD without opening/closing files, but that means you are not using a file system and consequently cannot simply read files, for example on a PC.
fast logging is typically done in the following way:
data acquisition is done at interrupt level (with or without DMA)
saving and all interaction with uSD is done at the loop level (lowest priority)

The recorder example Paul was suggesting as a starting point is indeed a good starting point.
further, as turtle9er indicated, the forum is full of logging examples. Even if they are not 100% suited for your application, understanding what they are doing is fundamental.

to give you max performance continuous recording of 16 Bytes at 375 kHz sampling is possible on a T3.6 without loss of data.
 
Status
Not open for further replies.
Back
Top