Writing data to SD card (using board slot ) in Teensy 3.5

Status
Not open for further replies.
hii all

I am currently working with Teensy 3.5 boards as a part of my project work . I am new in the forum too :)

As a part of the project I need to make use of the SD card slot in the Teensy 3.5 board. Right now im using Teensy board for data acquisition ( from different sensors and actuators ) and I want to write the data into a SD card directly using Teensy SD slot.

Can you tell me how to write data into the SD card (using boards SD card slot ). Thanks in advance

Please reply at the earliest

Regards
Abin Ephrem
 
With TeensyDuino 1.31 installed there are working examples in the SD library - for newer/larger SD cards. There is a recent thread with added details.
 
If those samples don't work you need to find Paul's thread and show him what you are seeing. Or post exactly what you are doing here and hope he sees it. if you are using an older card that has a pending fix, but a modern SDHC card should work. perhaps it is formatted wrong - such details may be relvant.
 
Im using Teensy board for data acquisition. Since the board have so many GPIO pins this was best suitable one for me .

Ultra sonic sensors ( 8 ) and Lidar Lite V3 sensors are connected to the Teensy board . These sensors will poll me the data at about 250Hz ( I can see the data in the serial monitor ) and what i want to do is to write this data to the SD card as soon as they are received. ( similar to a USB card logger ).

Is this possible with the teensy SD slot ?
 
Im using Teensy board for data acquisition. Since the board have so many GPIO pins this was best suitable one for me .

Ultra sonic sensors ( 8 ) and Lidar Lite V3 sensors are connected to the Teensy board . These sensors will poll me the data at about 250Hz ( I can see the data in the serial monitor ) and what i want to do is to write this data to the SD card as soon as they are received. ( similar to a USB card logger ).

Is this possible with the teensy SD slot ?

You can use T3.5 SD card.
However, If you have not done yet, I would connect first a single sensor (I assume Ultra sonic sensors are 40 kHz distance sensors)
to Teensy, interface with sensor and write data via usb-serial to PC, If that is working, add another sensor and increase slowly the complexity.
If all sensors are working to your satisfaction and you have thought about what type of info you wanted to write to sdCard, take the one of the logger examples in Teensyduino/Arduino and adapt to your sensor suite.

If you encounter problems, please post the complete code you are using, the sensor models with detailed connection to teensy, so we can help you.
 
You can use T3.5 SD card.
However, If you have not done yet, I would connect first a single sensor (I assume Ultra sonic sensors are 40 kHz distance sensors)
to Teensy, interface with sensor and write data via usb-serial to PC, If that is working, add another sensor and increase slowly the complexity.
If all sensors are working to your satisfaction and you have thought about what type of info you wanted to write to sdCard, take the one of the logger examples in Teensyduino/Arduino and adapt to your sensor suite.

If you encounter problems, please post the complete code you are using, the sensor models with detailed connection to teensy, so we can help you.

I have integrated all those sensors in an arduino mega board right now but wanted to change to the teensy board.

As a start I integrated one Lidar lite V3 sensor and its working well with the board . Im able to write data via usb-serial to PC too.

Also I got the example TeensySdioDemo working too. Its writing some randomly generated data ( still trying to understand that code as im not a great coder myslef :) ) to the SD card in Teensy with a file name TeensyDemo.bin . I am trying to use the same program and try to write the sensor readings to a text file ( similar a usb data logger ) but i'm kinda having problems when trying to edit the code. Lidar lite use I2C protocol and this is the code that will give the readings from the sensor.

#include <Wire.h>
float measure();
byte lidarliteAddress=0x62;
byte distance_data[2];
int busy_flag;

void setup()
{
Wire.begin();
Serial.begin(115200);
}
float measure ()
{
Wire.beginTransmission(lidarliteAddress);
Wire.write(0x00);
Wire.write(0x04);
Wire.endTransmission();

Wire.beginTransmission(lidarliteAddress);
Wire.write(0x01);
Wire.endTransmission();
do
{
Wire.requestFrom(lidarliteAddress,1);
busy_flag= bitRead(Wire.read(),0);
} while(busy_flag!=0);
if(busy_flag==0)
{
Wire.beginTransmission(lidarliteAddress);
Wire.write(0x8f);
Wire.endTransmission();
Wire.requestFrom(lidarliteAddress,2);
int count =0;
while(Wire.available())
{
distance_data[count]=Wire.read();
count++;
}
float distance=((distance_data[0]<<8)+distance_data[1]);
return distance;
}
}

void loop()
{
float distance=measure();
Serial.println(distance);
}

I want to write that distance value to the SD card directly . Can you show me a way to edit the " teensysdiodemo " to write this distance to the SD card .


Note : The project aim is to put this sensor assembly on a hexa-copter and try to map the surroundings from the sensor readings . If I can get one's data to the SD card then I can figure out about the rest of the sensors I believe.

Thanks in advance.
 
I If I can get one's data to the SD card then I can figure out about the rest of the sensors I believe.

I do not have a Lidar so I cannot test it, but I would try with the following code (assuming you code is working)
Code:
#include <Wire.h>
short measure();
byte lidarliteAddress=0x62;
byte distance_data[2];
int busy_flag;

#include "SdFat.h"
SdFatSdio sd;
File file;
#define MaxCount 100000

void setup()
{
  Wire.begin();
  Serial.begin(115200);

  if (!sd.begin()) {
    sd.initErrorHalt();
  }
}

short measure ()
{
  Wire.beginTransmission(lidarliteAddress);
  Wire.write(0x00); 
  Wire.write(0x04); 
  Wire.endTransmission();
  
  Wire.beginTransmission(lidarliteAddress);
  Wire.write(0x01);
  Wire.endTransmission();
  do
  {
    Wire.requestFrom(lidarliteAddress,1);
    busy_flag= bitRead(Wire.read(),0);
  } while(busy_flag!=0);
  
  if(busy_flag==0)
  {
    Wire.beginTransmission(lidarliteAddress);
    Wire.write(0x8f);
    Wire.endTransmission();
    Wire.requestFrom(lidarliteAddress,2);
    for(int count=0; count<2; count++)
    {
      while(Wire.available());
      distance_data[count]=Wire.read();
    }
    short distance=((distance_data[0]<<8)+distance_data[1]); // why conversion from short to float?
    return distance;
  }
}

void doLogging(uint32_t timeStamp, short *data, int nb)
{
  // following is for logging
  static uint32_t ifl = 0;
  static uint32_t count = 0;
  char filename[32];

  if(!count)
  {
     //open file
     sprintf(filename,"Ranging_%04d.bin",ifl); ifl++;
     if (!file.open(filename, O_RDWR | O_CREAT)) {
       sd.errorHalt("open failed");
     count=1;
     }
  }
  //
  if(count>0)
  {
    // write to file
    file.print(timeStamp);
    for(int ii=0; ii<nb; ii++)
    { file.print(',');
      file.print(data[ii]) ;
    }
    file.println();

    count++;
    if(count>MaxCount) count=0;
  }
  //
  if(!count)
  {
     // close file
     file.close();
  }
}


void loop()
{
  uint32_t t0 = millis();
  short distance=measure();
  Serial.println(distance);

  doLogging(t0,&distance,1);
}

As I could not understand why you are converting to float, I modified the measurements to short.
 
Last edited:
I do not have a Lidar so I cannot test it, but I would try with the following code (assuming you code is working)
Code:
#include <Wire.h>
short measure();
byte lidarliteAddress=0x62;
byte distance_data[2];
int busy_flag;

#include "SdFat.h"
SdFatSdio sd;
File file;
#define MaxCount 100000

void setup()
{
  Wire.begin();
  Serial.begin(115200);

  if (!sd.begin()) {
    sd.initErrorHalt();
  }
}

short measure ()
{
  Wire.beginTransmission(lidarliteAddress);
  Wire.write(0x00); 
  Wire.write(0x04); 
  Wire.endTransmission();
  
  Wire.beginTransmission(lidarliteAddress);
  Wire.write(0x01);
  Wire.endTransmission();
  do
  {
    Wire.requestFrom(lidarliteAddress,1);
    busy_flag= bitRead(Wire.read(),0);
  } while(busy_flag!=0);
  
  if(busy_flag==0)
  {
    Wire.beginTransmission(lidarliteAddress);
    Wire.write(0x8f);
    Wire.endTransmission();
    Wire.requestFrom(lidarliteAddress,2);
    for(int count=0; count<2; count++)
    {
      while(Wire.available());
      distance_data[count]=Wire.read();
    }
    short distance=((distance_data[0]<<8)+distance_data[1]); // why conversion from short to float?
    return distance;
  }
}

void doLogging(uint32_t timeStamp, short *data, int nb)
{
  // following is for logging
  static uint32_t ifl = 0;
  static uint32_t count = 0;
  char filename[32];

  if(!count)
  {
     //open file
     sprintf(filename,"Ranging_%04d.bin",ifl); ifl++;
     if (!file.open(filename, O_RDWR | O_CREAT)) {
       sd.errorHalt("open failed");
     count=1;
     }
  }
  //
  if(count>0)
  {
    // write to file
    file.print(timeStamp);
    for(int ii=0; ii<nb; ii++)
    { file.print(',');
      file.print(data[ii]) ;
    }
    file.println();

    count++;
    if(count>MaxCount) count=0;
  }
  //
  if(!count)
  {
     // close file
     file.close();
  }
}


void loop()
{
  uint32_t t0 = millis();
  short distance=measure();
  Serial.println(distance);

  doLogging(t0,&distance,1);
}

As I could not understand why you are converting to float, I modified the measurements to short.

Wow..thanks dude..that worked big time :)

Thanks again :)
 
I just received my Teensy 3.5 and am trying to use the SD card.

I'm using the example sketch below but when I run it, nothing shows in the serial window. The SD card has data on it and I can read it from my windows 10 PC OK.

I am using Ardunuio IDE 1.6.13 and Teensyduino 1.32 Beta.

Thank you for any help.

UPDATE: I discovered that if I manually press the 3.5 reset button, this sketch runs. It's been awhile since I've done any Ardunio IDE programming but I remember I didn't have to press the reset button to get my sketches to run. Maybe I'm forgetting to do something that is requiring me to have to press the reset button?

Code:
/*
  SD card test 
   
 This example shows how use the utility libraries on which the'
 SD library is based in order to get info about your SD card.
 Very useful for testing a card when you're not sure whether its working or not.
 	
 The circuit:
  * SD card attached to SPI bus as follows:
 ** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila, pin 7 on Teensy with audio board
 ** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
 ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila, pin 14 on Teensy with audio board
 ** CS - depends on your SD card shield or module - pin 10 on Teensy with audio board
 		Pin 4 used here for consistency with other Arduino examples

 
 created  28 Mar 2011
 by Limor Fried 
 modified 9 Apr 2012
 by Tom Igoe
 */
 // include the SD library:
#include <SD.h>
#include <SPI.h>

// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
// Teensy audio board: pin 10
// Teensy 3.5 & 3.6 on-board: BUILTIN_SDCARD
// Wiz820+SD board: pin 4
// Teensy 2.0: pin 0
// Teensy++ 2.0: pin 20
//const int chipSelect = 4;    
const int chipSelect = BUILTIN_SDCARD;

void setup()
{
  //UNCOMMENT THESE TWO LINES FOR TEENSY AUDIO BOARD:
  SPI.setMOSI(7);  // Audio shield has MOSI on pin 7
  SPI.setSCK(14);  // Audio shield has SCK on pin 14
  
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  Serial.print("\nInitializing SD card...");


  // we'll use the initialization code from the utility libraries
  // since we're just testing if the card is working!
  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card inserted?");
    Serial.println("* is your wiring correct?");
    Serial.println("* did you change the chipSelect pin to match your shield or module?");
    return;
  } else {
   Serial.println("Wiring is correct and a card is present."); 
  }

  // print the type of card
  Serial.print("\nCard type: ");
  switch(card.type()) {
    case SD_CARD_TYPE_SD1:
      Serial.println("SD1");
      break;
    case SD_CARD_TYPE_SD2:
      Serial.println("SD2");
      break;
    case SD_CARD_TYPE_SDHC:
      Serial.println("SDHC");
      break;
    default:
      Serial.println("Unknown");
  }

  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
    return;
  }


  // print the type and size of the first FAT-type volume
  uint32_t volumesize;
  Serial.print("\nVolume type is FAT");
  Serial.println(volume.fatType(), DEC);
  Serial.println();
  
  volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
  volumesize *= volume.clusterCount();       // we'll have a lot of clusters
  if (volumesize < 8388608ul) {
    Serial.print("Volume size (bytes): ");
    Serial.println(volumesize * 512);        // SD card blocks are always 512 bytes
  }
  Serial.print("Volume size (Kbytes): ");
  volumesize /= 2;
  Serial.println(volumesize);
  Serial.print("Volume size (Mbytes): ");
  volumesize /= 1024;
  Serial.println(volumesize);

  
  Serial.println("\nFiles found on the card (name, date and size in bytes): ");
  root.openRoot(volume);
  
  // list all files in the card with date and size
  root.ls(LS_R | LS_DATE | LS_SIZE);
}


void loop(void) {
  
}
 
Last edited:
So on my second sketch below, the only text I see in the serial window is:

t exist.

So, obviously, I'm not seeing all the text that I should.

Any thoughts on what's wrong?

Thanks...

Code:
/*
  SD card basic file example
 
 This example shows how to create and destroy an SD card file 	
 The circuit:
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11, pin 7 on Teensy with audio board
 ** MISO - pin 12
 ** CLK - pin 13, pin 14 on Teensy with audio board
 ** CS - pin 4, pin 10 on Teensy with audio board
 
 created   Nov 2010
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe
 
 This example code is in the public domain.
 	 
 */
#include <SD.h>
#include <SPI.h>

File myFile;

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
// Teensy audio board: pin 10
// Teensy 3.5 & 3.6 on-board: BUILTIN_SDCARD
// Wiz820+SD board: pin 4
// Teensy 2.0: pin 0
// Teensy++ 2.0: pin 20
const int chipSelect = BUILTIN_SDCARD;

void setup()
{
 //UNCOMMENT THESE TWO LINES FOR TEENSY AUDIO BOARD:
 SPI.setMOSI(7);  // Audio shield has MOSI on pin 7
 SPI.setSCK(14);  // Audio shield has SCK on pin 14
  
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  Serial.print("Initializing SD card...");

  if (!SD.begin(chipSelect)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

  if (SD.exists("example.txt")) {
    Serial.println("example.txt exists.");
  }
  else {
    Serial.println("example.txt doesn't exist.");
  }

  // open a new file and immediately close it:
  Serial.println("Creating example.txt...");
  myFile = SD.open("example.txt", FILE_WRITE);
  myFile.close();

  // Check to see if the file exists: 
  if (SD.exists("example.txt")) {
    Serial.println("example.txt exists.");
  }
  else {
    Serial.println("example.txt doesn't exist.");  
  }

  // delete the file:
  Serial.println("Removing example.txt...");
  SD.remove("example.txt");

  if (SD.exists("example.txt")){ 
    Serial.println("example.txt exists.");
  }
  else {
    Serial.println("example.txt doesn't exist.");  
  }
}

void loop()
{
  // nothing happens after setup finishes.
}
 
UPDATE: I discovered that if I manually press the 3.5 reset button, this sketch runs. It's been awhile since I've done any Ardunio IDE programming but I remember I didn't have to press the reset button to get my sketches to run. Maybe I'm forgetting to do something that is requiring me to have to press the reset button?

The button on Teensy is NOT a reset button , but a program button. Pressing it and having Teensy.exe running, results in downloading the program with restart. To simply restart, best is to disconnect/reconnect teensy from power (USB). Alternatively there is a reset line (difficult to reach on T3.2 but easy to connect to on T3.5/3.6). Connecting this line to GND resets Teensy.
 
So on my second sketch below, the only text I see in the serial window is:

t exist.

So, obviously, I'm not seeing all the text that I should.

Any thoughts on what's wrong?


Teensy is simply too fast for Serial monitor to react. (So this is a problem with PC and not Teensy)
inserting a delay(1000); after while(!Serial) {;} helps.
 
The post #11 code above does have this while(){}:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}

So any .print() after that should display as the Teensy will WAIT (forever if on 'battery', or a Serial Monitor otherwise never connects) until Serial/USB comes online. The code I generally see work better is (when SerMon output is optional):
Serial.begin(9600);
while (!Serial && (micros()<4000)) {
; // wait for serial port to connect. Needed for Leonardo only
}
That will wait, in this case, 4 seconds before continuing without SerMon. I also generally use TYQT which is a much better SerMon. But for best use it takes a "Tools / integrate to Arduino' update to replace Teensy.exe loader - otherwise Teensy.exe is blinded to the Teensy by TYQT holding the port so a button press is required.

I don't see the problem area - or OS info - Once Serial is online you should see all output - perhaps a computer reboot is in order. Switching to Integrated TYQT might better show the output giving a solution or showing a next step. TYQT has a thread and is precompiled for MAC and WINDOWS.
 
I put P#11 sketch on a T_3.6 and it failed on a 16GB exFAT card. I did get complete error output string on TYQT: "Initializing SD card...initialization failed!"
> Error is from card format type, I checked it with 'properties' under Windows to see exFAT.

When I put in a 32GB card with acceptable FAT32 formatting I get this::
Initializing SD card...initialization done.
example.txt doesn't exist.
Creating example.txt...
example.txt exists.
Removing example.txt...
example.txt doesn't exist.

T_3.5's out of arms reach - by a foot - but I suspect it would work the same.
 
The post #11 code above does have this while(){}:


So any .print() after that should display as the Teensy will WAIT (forever if on 'battery', or a Serial Monitor otherwise never connects) until Serial/USB comes online. The code I generally see work better is (when SerMon output is optional):

That will wait, in this case, 4 seconds before continuing without SerMon. I also generally use TYQT which is a much better SerMon. But for best use it takes a "Tools / integrate to Arduino' update to replace Teensy.exe loader - otherwise Teensy.exe is blinded to the Teensy by TYQT holding the port so a button press is required.

I don't see the problem area - or OS info - Once Serial is online you should see all output - perhaps a computer reboot is in order. Switching to Integrated TYQT might better show the output giving a solution or showing a next step. TYQT has a thread and is precompiled for MAC and WINDOWS.

I found sometimes that Serial monitors, being it Arduino, or putty, are missing initial data (especially from T3.6 & 240 MHz, even with "while(!Serial);" ). My hunch is that there is a lot of activity around USB inside the PC, so this is not a surprise for me, especially if other devices are also connected (like disks that must first spin-up). Different monitors may also react differently.
OK with "while(!Serial & millis() <4000);", but serial-monitor free operation was not the issue.
 
Indeed the problem making the error may be noted in P#15 - wrong card format. But Serial / USB debug spew should work right after while(!Serial).

Even with T_3.6 [at 240 MHz or other] {or other LC, 3.0, 3.2} the latest TYQT never misses on my 5 yr old Win_10 laptop or i7 Desktop - latest TYQT version connects in 402-419 ms ( Teensy does delay of 400 ms before calling setup() extra time is Windows finding it - with my teensy cores hack - I need to update my PULL request ). I've tried IDE SerMon and Putty and Tera Term and MegunoLinkPro paid thing I got free - They are no comparison with TYQT Serial connect, throughput, ease of use and added functionality (multi Teensy support, Reset, device ID naming, ...) .
 
No need to promote TYQT, I have it, but I prefer my own system.

Only hoping to encourage @rfresh737 to try it to see if it works to solve his viewing problem and get meaningful use from Teensy, and not distracted by what should be a non-issue - separate from the real problem. The added bit was just that speed of startup isn't an issue with a working tool.
 
I found sometimes that Serial monitors, being it Arduino, or putty, are missing initial data (especially from T3.6 & 240 MHz, even with "while(!Serial);" ). My hunch is that there is a lot of activity around USB inside the PC, so this is not a surprise for me, especially if other devices are also connected (like disks that must first spin-up). Different monitors may also react differently.
OK with "while(!Serial & millis() <4000);", but serial-monitor free operation was not the issue.
Are you using HID serial emulation or USB CDC?

With USB CDC, "while(!Serial);" reliably hangs for me until the serial connection is opened and no data is lost.

teensy_gateway (HID serial emulation) reliably looses some data that is printed immediately after "while(!Serial);".
 
Teensy is simply too fast for Serial monitor to react. (So this is a problem with PC and not Teensy)
inserting a delay(1000); after while(!Serial) {;} helps.

Ahhh yes...you're right...now that sketch works fine on 3.5...thanks...
 
Only hoping to encourage @rfresh737 to try it to see if it works to solve his viewing problem and get meaningful use from Teensy, and not distracted by what should be a non-issue - separate from the real problem. The added bit was just that speed of startup isn't an issue with a working tool.

Both my SD example sketches are now working once I added "while (!Serial & millis() <4000)" -- thanks to both of you...
 
Status
Not open for further replies.
Back
Top