Teensy 3.6 Datalogger

Status
Not open for further replies.
Hi,

Please see below code I am using to build an 8 channel Teensy 3.6 base datalogger and it works great with one small problem
the time display does not have a leading zero in spite of trying a number of methods for example if (hour < 10) { logfile.print('0');}
any recommendations on how to make it display correctly IMG_5603.jpg?

Thanks in advance !

Jim the Kiwi
Code:
/*With Gratitude to Tom Igoe, Jeremy Blum, Luke Miller LadyAda,Paul Stoffregen and others for their
  opensource code examples. */
#include <SD.h>
#include <SD_t3.h>
#include <SPI.h>
#include <Wire.h>
#include <TimeLib.h>

// A simple data logger for the Teensy analog pins
// how many milliseconds between grabbing data and logging it. 1 ms is 1000 x a second
#define LOG_INTERVAL  5 // millis between entries (reduce to take more/faster data)
// how many Milliseconds before writing the logged data permanently to disk
// set it to the LOG_INTERVAL to write each time (safest)
// set it to 10*LOG_INTERVAL to write all data every 10 datareads, you could lose up to
// the last 10 reads if power is lost but it uses less power and is much faster!
#define SYNC_INTERVAL 5 // millis between calls to flush() - to write data to the card
uint32_t syncTime = 0; // time of last sync()
#define ECHO_TO_SERIAL   1 // echo data to serial port 1 = Turned on
//here is the "go" button
#define WAIT_TO_START    1 // Wait for serial input in setup() 1 = autostart

// The analog pins that connect to the sensors
float Signal0 = A0;        // analog 0 28 Volt input
float Signal1 = A1;        // analog 1 28 Volt input
float Signal2 = A2;        // analog 2 5 Volt input
float Signal3 = A3;        // analog 3 5 Volt input
float Signal4 = A4;        // analog 0 28 Volt input
float Signal5 = A5;        // analog 1 28 Volt input
float Signal6 = A6;        // analog 2 5 Volt input
float Signal7 = A7;        // analog 3 5 Volt input

String zero = (Signal0);
String one = (Signal1);
String two = (Signal2);
String three = (Signal3);
String four = (Signal4);
String five = (Signal5);
String six = (Signal6);
String seven = (Signal7);
String Year = year();
String Mon = month();
String Day = day();
String Hour = hour();
String Min = minute();
String Sec = second();
//concatenate the data into the line
String dataline = (Year + "/" + Mon + "/" + Day + "   " + Hour + ":" + Min + ":" + Sec + "      " + "," + zero  + "," + one  + "," + two  + "," + three + "," + four  + "," + five  + "," + six  + "," + seven);
int ledState = LOW;
unsigned long previousmillis = 0;
long interval = 50;

// Variables will change:

// for teensy 3.x data logging , we set chipSelect = BUILTIN_SDCARD SD cs line
const int chipSelect = BUILTIN_SDCARD;
const int ledPin = 13;

// the logging file
File logfile;

void error(char *str)
{
  Serial.print("SD error: ");
  Serial.println(str);
  while (10); //Stops if you cannot read the SD
}

void setup(void)
{
  setSyncProvider(getTeensy3Time);
  Serial.begin(115200);
  while (!Serial);  // Wait for Arduino Serial Monitor to open
  delay(500);
  if (timeStatus() != timeSet) {
    Serial.println("Unable to sync with the RTC");
  } else {
    Serial.println("RTC has set the system time");
  }

  pinMode(ledPin, OUTPUT);

  // initialize the SD card
  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
  }
  else Serial.println("Card initialized.");


  // create a new file
  char filename[] = "LOGGER00.CSV";
  for (uint8_t i = 0; i < 100; i++) {
    filename[6] = i / 10 + '0';
    filename[7] = i % 10 + '0';
    if (! SD.exists(filename)) {
      // only open a new file if it doesn't exist
      logfile = SD.open(filename, FILE_WRITE);
      break;  // leave the loop!
    }
  }

  if (! logfile) {
    Serial.println("couldnt create file");
  }

  Serial.print("Logging to: ");
  Serial.println(filename);
  // connect to RTC how to invoke the Teensy3.6 RTC?
  Wire.begin();

  logfile.println("Year/Month/Day  hh:mm:ss   ,Signal0,Signal1,Signal2,Signal3,Signal4,Signal5,Signal6,Signal7");

#if ECHO_TO_SERIAL
  Serial.println("Year/Month/Day  hh:mm:ss   ,Signal0,Signal1,Signal2,Signal3,Signal4,Signal5,Signal6,Signal7");

#endif //ECHO_TO_SERIAL
  delay(3000);
}

void loop(void)
{
  //use the teensy time library TimeTeensy3

  if (Serial.available()) {
    time_t t = processSyncMessage();
    if (t != 0) {
      Teensy3Clock.set(t); // set the RTC
      setTime(t);
    }
  }
  digitalClockDisplay();
  String Year = year();
  String Mon = month();
  String Day = day();
  String Hour = hour();
  String Min = minute();
  String Sec = second();

  //concatenate hour:minute string

  delay(1);
  delay((LOG_INTERVAL - 1) - (millis() % LOG_INTERVAL));

  analogRead(Signal0);
  delay(3);
  int Sig0 = map((analogRead(Signal0)), 0, 921, 0, 255); //0-29 VDC channel scaled to 0-4.5 VDC

  analogRead(Signal1);
  delay(3);
  int Sig1 = map((analogRead(Signal1)), 0, 921, 0, 255); //0-29 VDC channel scaled to 0-4.5 VDC
  analogRead(Signal2);
  delay(3);
  int Sig2 = map((analogRead(Signal2)), 0, 921, 0, 255); //0-29 VDC channel scaled to 0-4.5 VDC

  analogRead(Signal3);
  delay(3);
  int Sig3 = map((analogRead(Signal3)), 0, 921, 0, 255); //0-29 VDC channel scaled to 0-4.5 VDC

  analogRead(Signal4);
  delay(3);
  int Sig4 = map((analogRead(Signal4)), 0, 921, 0, 255); //0-29 VDC channel scaled to 0-4.5 VDC

  analogRead(Signal5);
  delay(3);
  int Sig5 = map((analogRead(Signal5)), 0, 921, 0, 255); //0-29 VDC channel scaled to 0-4.5 VDC
  analogRead(Signal6);
  delay(3);
  int Sig6 = map((analogRead(Signal6)), 0, 921, 0, 255); //0-29 VDC channel scaled to 0-4.5 VDC

  analogRead(Signal7);
  delay(3);
  int Sig7 = map((analogRead(Signal7)), 0, 921, 0, 255); //0-29 VDC channel scaled to 0-4.5 VDC

  String zero = (Sig0);
  String one = (Sig1);
  String two = (Sig2);
  String three = (Sig3);
  String four = (Sig4);
  String five = (Sig5);
  String six = (Sig6);
  String seven = (Sig7);
  String dataline = (Year + "/" + Mon + "/" + Day + "   " + Hour + ":" + Min + ":" + Sec + "      " + "," + zero  + "," + one  + "," + two  + "," + three + "," + four  + "," + five  + "," + six  + "," + seven);

  logfile.print(dataline);
  logfile.println();
#if ECHO_TO_SERIAL

  Serial.print(dataline);
  Serial.println();
#endif //ECHO_TO_SERIAL
  // Now we write data to disk! Don't sync too often - requires 2048 bytes of I/O to SD card
  // which uses a bunch of power and takes time
  if ((millis() - syncTime) < SYNC_INTERVAL) return;
  syncTime = millis();
  // blink LED to show we are syncing data to the card & updating FAT!
  logfile.flush();//physically save any bytes written to the file to the SD card
  {
    unsigned long currentmillis = millis();

    if (currentmillis - previousmillis > interval) {
      // save the last time you blinked the LED
      previousmillis = currentmillis * 10000;

      // if the LED is off turn it on and vice-versa:
      if (ledState == LOW)
        ledState = HIGH;
      else
        ledState = LOW;

      // set the LED with the ledState of the variable:
      digitalWrite(ledPin, ledState);
    }// wait for a second
  }
}

void digitalClockDisplay() {
  // digital clock display of the time
}

time_t getTeensy3Time()
{
  return Teensy3Clock.get();
}

/*  code to process time sync messages from the serial port   */
#define TIME_HEADER  "T"   // Header tag for serial time sync message

unsigned long processSyncMessage() {
  unsigned long pctime = 0L;
  const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013

  if (Serial.find(TIME_HEADER)) {
    pctime = Serial.parseInt();
    return pctime;
    if ( pctime < DEFAULT_TIME) { // check the value is a valid time (greater than Jan 1 2013)
      pctime = 0L; // return 0 to indicate that the time is not valid
    }
  }
  return pctime;
}

void printDigits(int digits) {
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}
 
Thank you very much my Teensy 20 channel datalogger works great!

Serial.printf(":%02d",digits)

Thanks a bunch mlu the suggested code works great 20 channels
Each one recording floats Ten + times per second

Very happy with this
Thanks PJRC
 
Thanks a bunch mlu the suggested code works great 20 channels
Each one recording floats Ten + times per second

Very happy with this
Thanks PJRC

I am new using teensys and looking to build a datalogger found your example but could not replicate your problem/solution.
Sorry my question but where did you change the code?
Try to understand it but could not found...
Can you give me a help?
Thanks,
Timóteo
 
I'll post the working code as soon as I get off this flight

I am new using teensys and looking to build a datalogger found your example but could not replicate your problem/solution.
Sorry my question but where did you change the code?
Try to understand it but could not found...
Can you give me a help?
Thanks,
Timóteo

Sure I'll post the code as soon as I get off this flight
 
Sure I'll post the code as soon as I get off this flight


Here you go this works but I am sure it can be improved on.

Jim

Code:
/*With Gratitude to Tom Igoe, Jeremy Blum, Luke Miller
  LadyAda,Paul Stoffregen mlu Patrick Felicitas and others
  for their   opensource code examples. */

#include <SD.h>
#include <SD_t3.h>
#include <Wire.h>
#include <TimeLib.h>

// A simple data logger for the Teensy analog pins
// how many milliseconds between grabbing data and logging it. 1 ms is 1000 x a second
#define LOG_INTERVAL  1 // millis between entries (reduce to take more/faster data)
// how many Milliseconds before writing the logged data permanently to disk
// set it to the LOG_INTERVAL to write each time (safest)
// set it to 10*LOG_INTERVAL to write all data every 10 datareads, you could lose up to
// the last 10 reads if power is lost but it uses less power and is much faster!
#define SYNC_INTERVAL 1 // millis between calls to flush() - to write data to the card
uint32_t syncTime = 0; // time of last sync()
#define ECHO_TO_SERIAL   1 // echo data to serial port 1 = Turned on
//here is the "go" button
#define WAIT_TO_START    1 // Wait for serial input in setup() 1 = autostart

// The analog pins that connect to the sensors
float Signal0 = A0;        // analog 0
float Signal1 = A1;        // analog 1
float Signal2 = A2;        // analog 2
float Signal3 = A3;        // analog 3
float Signal4 = A4;        // analog 4
float Signal5 = A5;        // analog 5
float Signal6 = A6;        // analog 6
float Signal7 = A7;        // analog 7

String zero = (Signal0);
String one = (Signal1);
String two = (Signal2);
String three = (Signal3);
String four = (Signal4);
String five = (Signal5);
String six = (Signal6);
String seven = (Signal7);
int ledState = LOW;
unsigned long previousmillis = 0;
long interval = 500;
// for teensy 3.x data logging , set chipSelect = BUILTIN_SDCARD SD
const int chipSelect = BUILTIN_SDCARD;
const int ledPin = 13;
// the logging file
File logfile;

void error(char *str)
{
  Serial.print("SD error: ");
  Serial.println(str);
  while (10); //Stops if you cannot read the SD
}

void setup(void)
{
  setSyncProvider(getTeensy3Time);
  Serial.begin(115200);
  while (!Serial);  // Wait for Arduino Serial Monitor to open
  delay(500);
  if (timeStatus() != timeSet) {
    Serial.println("Unable to sync with the RTC");
  } else {
    Serial.println("RTC has set the system time");
  }

  pinMode(ledPin, OUTPUT);

  // initialize the SD card
  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
  }
  else Serial.println("Card initialized.");


  // create a new file
  char filename[] = "LOGGER00.CSV";
  for (uint8_t i = 0; i < 100; i++) {
    filename[6] = i / 10 + '0';
    filename[7] = i % 10 + '0';
    if (! SD.exists(filename)) {
      // only open a new file if it doesn't exist
      logfile = SD.open(filename, FILE_WRITE);
      break;  // leave the loop!
    }
  }

  if (! logfile) {
    Serial.println("couldnt create file");
  }

  Serial.print("Logging to: ");
  Serial.println(filename);
  // connect to RTC how to invoke the Teensy3.6 RTC?
  Wire.begin();

  logfile.println("Year/Month/Day      hh:mm:ss   ,Signal0,Signal1,Signal2,Signal3,Signal4,Signal5,Signal6,Signal7");

#if ECHO_TO_SERIAL
  Serial.println("Year/Month/Day      hh:mm:ss   ,Signal0,Signal1,Signal2,Signal3,Signal4,Signal5,Signal6,Signal7");

#endif //ECHO_TO_SERIAL
  delay(3000);
}

void loop(void)
{
  //uses the teensy time library TimeTeensy3

  if (Serial.available()) {
    time_t t = processSyncMessage();
    if (t != 0) {
      Teensy3Clock.set(t); // set the RTC
      setTime(t);
    }
  }
  digitalClockDisplay();
  String Year = year();
  String Mon = month();
  String Day = day();
  String Hour = hour();
  String Min = minute();
  String Sec = second();
  //concatenate hour:minute string
  delay(1);
  delay((LOG_INTERVAL - 1) - (millis() % LOG_INTERVAL));

  analogRead(Signal0);
  delay(3);
  int Sig0 = map((analogRead(Signal0)), 0, 921, 0, 255); //0-29 VDC channel scaled to 0-4.5 VDC
  analogRead(Signal1);
  delay(3);
  int Sig1 = map((analogRead(Signal1)), 0, 921, 0, 255); //0-29 VDC channel scaled to 0-4.5 VDC
  analogRead(Signal2);
  delay(3);
  int Sig2 = map((analogRead(Signal2)), 0, 921, 0, 255); //0-29 VDC channel scaled to 0-4.5 VDC
  analogRead(Signal3);
  delay(3);
  int Sig3 = map((analogRead(Signal3)), 0, 921, 0, 255); //0-29 VDC channel scaled to 0-4.5 VDC
  analogRead(Signal4);
  delay(3);
  int Sig4 = map((analogRead(Signal4)), 0, 921, 0, 255); //0-29 VDC channel scaled to 0-4.5 VDC
  analogRead(Signal5);
  delay(3);
  int Sig5 = map((analogRead(Signal5)), 0, 921, 0, 255); //0-29 VDC channel scaled to 0-4.5 VDC
  analogRead(Signal6);
  delay(3);
  int Sig6 = map((analogRead(Signal6)), 0, 921, 0, 255); //0-29 VDC channel scaled to 0-4.5 VDC
  analogRead(Signal7);
  delay(3);
  int Sig7 = map((analogRead(Signal7)), 0, 921, 0, 255); //0-29 VDC channel scaled to 0-4.5 VDC

  String zero = (Sig0 * 3.0);
  String one = (Sig1 * 4.0);
  String two = (Sig2 * 7.0);
  String three = (Sig3 * 3.9);
  String four = (Sig4 * 1.5);
  String five = (Sig5 * .3);
  String six = (Sig6 * .25);
  String seven = (Sig7 * 2.0);
  int h = Hour.toInt();
  int m = Min.toInt();
  int s = Sec.toInt();
  String ymd = (Year + "," + Mon + "," + Day + ",         ");
  String data = ("        ," + zero + "," + one + "," + two + "," + three + "," + four + "," + five + "," + six + "," + seven);

  logfile.print(ymd);
  logfile.printf("%02d", h);
  logfile.print(",");
  logfile.printf("%02d", m);
  logfile.print(",");
  logfile.printf("%02d", s);
  logfile.print(data);
  logfile.println();

#if ECHO_TO_SERIAL

  Serial.print(ymd);

  Serial.printf("%02d", h);
  Serial.print(":");
  Serial.printf("%02d", m);
  Serial.print(":");
  Serial.printf("%02d", s);
  Serial.print(data);
  Serial.println();
#endif //ECHO_TO_SERIAL
  // Now we write data to disk! Don't sync too often - requires 2048 bytes of I/O to SD card
  // which uses a bunch of power and takes time
  if ((millis() - syncTime) < SYNC_INTERVAL) return;
  syncTime = millis();
  // blink LED to show we are syncing data to the card & updating FAT!
  logfile.flush();//physically save any bytes written to the file to the SD card
  {
    unsigned long currentmillis = millis();

    if ((currentmillis - previousmillis) * 10 > interval) {
      // save the last time you blinked the LED
      previousmillis = currentmillis;

      // if the LED is off turn it on and vice-versa:
      if (ledState == LOW)
        ledState = HIGH;
      else
        ledState = LOW;

      // set the LED with the ledState of the variable:
      digitalWrite(ledPin, ledState);
    }// wait for a second
  }
}

void digitalClockDisplay() {
  // digital clock display of the time
}

time_t getTeensy3Time()
{
  return Teensy3Clock.get();
}

/*  code to process time sync messages from the serial port   */
#define TIME_HEADER  "T"   // Header tag for serial time sync message

unsigned long processSyncMessage() {
  unsigned long pctime = 0L;
  const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013

  if (Serial.find(TIME_HEADER)) {
    pctime = Serial.parseInt();
    return pctime;
    if ( pctime < DEFAULT_TIME) { // check the value is a valid time (greater than Jan 1 2013)
      pctime = 0L; // return 0 to indicate that the time is not valid
    }
  }
  return pctime;
}

void printDigits(int digits) {
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(": ");
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}
 
You are using SIGNAL0, SIGNAL1, etc. as inputs to analogRead. Since these are declared to be float, and analogRead takes an uint8_t argument for the pin number, the compiler has to convert the floating point number to 8-bit unsigned integer before each call. It would be better to make them const uint8_t to save the needless conversion.

Second, you are using the String library quite a bit. The String library allocates memory behind your back, and it can be slow to format the string. If it is performance critical, it may be time to drop down to C and format things manually using char arrays, rather than a complex String library. In addition, there is the possibility that memory allocation can fragment memory, and potentially run out of memory some time in the future.

Finally, you are doing one analogRead and throwing away the result, and doing another read that you pass to the map function. I'm not sure what the point is doing the analog read and ignoring the value.
 
Hello Jim,

Thanks for sharing the code.
But have tested and the data is keeping with just one digit.
Do I have to change some detail?

Thanks,
Timóteo
 
Hello All,

I'm sorry for some off topic...
Can I use <Audio.h> and play some music during logging?
My attempts severely corrupt all the files.
I would really appreciate any hints.
 
Some example based on WavFilePlayer, logging is simplified:
Code:
// Modified Simple WAV file player example
// by adding simulated log - 250 times per sec

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

AudioPlaySdWav           playWav1;
// Use one of these 3 output types: Digital I2S, Digital S/PDIF, or Analog DAC
AudioOutputI2S           audioOutput;
//AudioOutputSPDIF       audioOutput;
//AudioOutputAnalog      audioOutput;
AudioConnection          patchCord1(playWav1, 0, audioOutput, 0);
AudioConnection          patchCord2(playWav1, 1, audioOutput, 1);
AudioControlSGTL5000     sgtl5000_1;

// Use these with the Teensy Audio Shield
#define SDCARD_CS_PIN    10
#define SDCARD_MOSI_PIN  7
#define SDCARD_SCK_PIN   14

// Use these with the Teensy 3.5 & 3.6 SD card
//#define SDCARD_CS_PIN    BUILTIN_SDCARD
//#define SDCARD_MOSI_PIN  11  // not actually used
//#define SDCARD_SCK_PIN   13  // not actually used

// Use these for the SD+Wiz820 or other adaptors
//#define SDCARD_CS_PIN    4
//#define SDCARD_MOSI_PIN  11
//#define SDCARD_SCK_PIN   13

// the logging file
File logfile;

void setup() {
  Serial.begin(115200);
  delay(300); //whait for init of serial
  //while (!Serial);  // Wait for Arduino Serial Monitor to open <- t_ debugging only

  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example
  AudioMemory(8);

  // Comment these out if not using the audio adaptor board.
  // This may wait forever if the SDA & SCL pins lack
  // pullup resistors
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.5);

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

  //create log directory
  if(! SD.exists("LOG")){
    if(! SD.mkdir("LOG")){
      Serial.println("cannot create LOG dir !!!");  
    }  
  }

   // create a new file
  char filename[] = "LOG/Lg00.CSV";
  for (uint8_t i = 0; i < 100; i++) {
    filename[6] = i / 10 + '0';
    filename[7] = i % 10 + '0';
    if (! SD.exists(filename)) {
      // only open a new file if it doesn't exist
      logfile = SD.open(filename, FILE_WRITE);
      break;  // leave the loop!
    }
  }

  if (! logfile) {
    Serial.println("couldnt create file");
  } else {
    Serial.print("Logging to: ");
    Serial.println(filename);
  }


}

void playFile(const char *filename)
{
  Serial.print("Playing file: ");
  Serial.println(filename);

  // Start playing the file.  This sketch continues to
  // run while the file plays.
  playWav1.play(filename);

  // A brief delay for the library read WAV info
  delay(5);

  // Simply wait for the file to finish playing.
  while (playWav1.isPlaying()) {
    // uncomment these lines if you audio shield
    // has the optional volume pot soldered
    float vol = analogRead(15);
    vol = vol / 1024;
    sgtl5000_1.volume(vol);
    logging();
    delay(4);
  }
}

// just counter to catch stale data
int count = 0;

// writes one string to log file and Serial output
void logging(){
  char buff [2];
  sprintf (buff, "%02x", count++);
  logfile.print(buff);
  logfile.println(" some other stuff: 90 23 56 89 12");
  logfile.flush();
  Serial.print(buff);
  Serial.println(" some other stuff: 90 23 56 89 12");
  if(count > 255){
    count = 0;  
  }
  
}

void loop() {
  playFile("SDTEST1.WAV");  // filenames are always uppercase 8.3 format
  for(int i = 0; i< 125; i++){ // 500 ms of just logging
    logging();
    delay(4);
  }
  playFile("SDTEST2.WAV");
  for(int i = 0; i< 125; i++){ // 500 ms of just logging
    logging();
    delay(4);
  }
  playFile("SDTEST3.WAV");
  for(int i = 0; i< 125; i++){ // 500 ms of just logging
    logging();
    delay(4);
  }
  playFile("SDTEST4.WAV");
  for(int i = 0; i< 375; i++){ // 500 ms of just logging
    logging();
    delay(4);
  }
}
 
Status
Not open for further replies.
Back
Top