Teensy Having Problems with this code

Status
Not open for further replies.

amb0027

Member
Background:
I have a project that immediately starts logging data to an sd card when the device is powered on.

The problem:
It must calculate a new filename for every logging session. The code I use to do this works on other arduino devices, but not on the Teensy 3

The code:
Code:
void getUnusedFilename()
{
  int x = 0;
  int y = 0;
  int z = 0;

  //Find the last file on the sd card 
  while( SD.exists(myFilename) )
  {
    for (word i = 0; i < 1000; i++) 
    { // create new filename w/ 3 digits 000-999
      x = i/100;
      myFilename[4] = x + '0';          // calculates hundreds position

      y = (i-(x*100))/10;
      myFilename[5] = y + '0';          // calculates tens position

      z = i - (x*100) - (y*10);
      myFilename[6] = z + '0';          // subtracts hundreds & tens for single digit

      if (! SD.exists(myFilename)) {    // only open a new file if it doesn't exist
        Serial.print("Next file: ");
        Serial.println(myFilename);
        break;                        // leave the loop after finding new filename
      }
    }
  }
  
  Serial.println(myFilename);
}
 
Last edited:
Code:
#include <SD.h>

const int TEENSY_LED=13; // teensy++ 2.0 pin = 6
const int chipSelect=10; // teensy++ 2.0 pin = 20
int iStatus = 0;
unsigned long lastTime = 0;

char* myFilename = "Cube010.txt";

void setup() {
  Serial.begin(9600);
  
  pinMode( TEENSY_LED, OUTPUT );
  
  while( !Serial ) {
    if( iStatus == 1 && millis() - lastTime > 500 )
    {
      digitalWrite( TEENSY_LED, HIGH );
      lastTime = millis();
      iStatus = 1 - iStatus;
    }
    else if( millis() - lastTime > 500 )
    {
      digitalWrite( TEENSY_LED, LOW );
      lastTime = millis();
      iStatus = 1 - iStatus;
    }
  }
  
  pinMode(chipSelect, OUTPUT);
  if( !SD.begin(chipSelect) )
  {
    Serial.println("SD Error!");
  }
  else
  {
    Serial.println("SD card has initialized.");
  }
  
  getUnusedFilename();
  
  Serial.println("Done booting!");
}

void loop()
{
  
}
     
void getUnusedFilename()
{
  int x = 0;
  int y = 0;
  int z = 0;

  //Find the last file on the sd card 
  while( SD.exists(myFilename) )
  {
    for (word i = 0; i < 1000; i++) 
    { // create new filename w/ 3 digits 000-999
      x = i/100;
      myFilename[4] = x + '0';          // calculates hundreds position

      y = (i-(x*100))/10;
      myFilename[5] = y + '0';          // calculates tens position

      z = i - (x*100) - (y*10);
      myFilename[6] = z + '0';          // subtracts hundreds & tens for single digit

      if (! SD.exists(myFilename)) {    // only open a new file if it doesn't exist
        Serial.print("Next file: ");
        Serial.println(myFilename);
        break;                        // leave the loop after finding new filename
      }
    }
  }
  
  Serial.println(myFilename);
}
 
Pin 13 is needed by the SD card.

Please try changing the blink stuff to another pin. If that doesn't solve the problem, post the full code again with this change and I'll try it here on a known-good board+SD.
 
Code:
#include <SD.h>

const int TEENSY_LED=22; //6
const int chipSelect=10; //20
int iStatus = 0;
unsigned long lastTime = 0;

char* myFilename = "Cube010.txt";

void setup() {
  Serial.begin(9600);
  
  pinMode( TEENSY_LED, OUTPUT );
  
  while( !Serial ) {
    if( iStatus == 1 && millis() - lastTime > 500 )
    {
      digitalWrite( TEENSY_LED, HIGH );
      lastTime = millis();
      iStatus = 1 - iStatus;
    }
    else if( millis() - lastTime > 500 )
    {
      digitalWrite( TEENSY_LED, LOW );
      lastTime = millis();
      iStatus = 1 - iStatus;
    }
  }
  
  pinMode(chipSelect, OUTPUT);
  if( !SD.begin(chipSelect) )
  {
    Serial.println("SD Error!");
  }
  else
  {
    Serial.println("SD card has initialized.");
  }
  
  getUnusedFilename();
  
  Serial.println("Done booting!");
}

void loop()
{
  
}

void getUnusedFilename2()
{
  int i=0;
  
  while( i < 3 )
  {
    if( i==0 )
    {
      if( !SD.exists("cube000.txt") )
      {
        Serial.println("File doesn't exist!");
        break;
      }
    }
    else if( i==1 )
    {
      if( !SD.exists("cube010.txt") )
      {
        Serial.println("File doesn't exist!");
        break;
      }
    }
    else if( i==2 )
    {
      if( !SD.exists("dataLo3g.txt") )
      {
        Serial.println("File doesn't exist!");
        break;
      }
    }
    i++;
  }
}

void getUnusedFilename()
{
  int x = 0;
  int y = 0;
  int z = 0;

  //Find the last file on the sd card 
  while( SD.exists(myFilename) )
  {
    for (word i = 0; i < 1000; i++) 
    { // create new filename w/ 3 digits 000-999
      x = i/100;
      myFilename[4] = x + '0';          // calculates hundreds position

      y = (i-(x*100))/10;
      myFilename[5] = y + '0';          // calculates tens position

      z = i - (x*100) - (y*10);
      myFilename[6] = z + '0';          // subtracts hundreds & tens for single digit

      if (! SD.exists(myFilename)) {    // only open a new file if it doesn't exist
        Serial.print("Next file: ");
        Serial.println(myFilename);
        break;                        // leave the loop after finding new filename
      }
    }
  }
  
  Serial.println(myFilename);
}
 
Are you certain that exact code in message #7 reproduces this problem? I'll dig out my board with SD attached and give it a try.....
 
What is the error?
I ran that code on a Teensy 2 and it prints:
Code:
SD card has initialized.
Cube010.txt
Done booting!
as it should.

Pete
 
What is the error?
I ran that code on a Teensy 2 and it prints:
Code:
SD card has initialized.
Cube010.txt
Done booting!
as it should.

Pete

Thanks for the reply. Sorry, I didn't clarify my current findings. The error only occurs on Teensy 3 devices.
 
I've tried your unmodified code from message #7 on a T3 with the PJRC uSD adapter and it prints:
Code:
SD card has initialized.
Cube010.txt
Done booting!

Pete
 
I've tried your unmodified code from message #7 on a T3 with the PJRC uSD adapter and it prints:
Code:
SD card has initialized.
Cube010.txt
Done booting!

Pete

That's extremely strange then. Any idea what could be going on? We've tried with multiple T3's and multiple uSD adapters, with no luck. It always get's stuck in some weird state and we can't connect with the Serial Monitor.
 
I can't think of anything that would cause it to hang. Have you jumpered the uSD board to use 3.3V for use with the T3 or done 3v3 to 5V level translation if using a 5V supply to the uSD?

Just to clarify: I'm running this on Windows 7 Pro x64, arduino 1.0.5, Teensyduino 1.15 RC1

Pete
 
I can't think of anything that would cause it to hang. Have you jumpered the uSD board to use 3.3V for use with the T3 or done 3v3 to 5V level translation if using a 5V supply to the uSD?

Just to clarify: I'm running this on Windows 7 Pro x64, arduino 1.0.5, Teensyduino 1.15 RC1

Pete

Yep, jumped the pads so I can use 3.3V. All of the example source for checking filenames, listing files, and reading files all work fine. Just that getUnusedFilename function jacks it up (and doesn't mess with other Teensy or Arduino devices).

I'm running Windows 7 Home, Arduino 1.0.3, and Teensyduino 1.07. I just downloaded teensyduino a couple of days ago from the website, not sure why it's such an old version? But I don't see our setups causing this dilemma (besides the Teensyduino program)
 
Last edited:
I just ran it here, on a Teensy 3.0 using Arduino 1.0.5 and Teensyduino 1.15-rc1 on Linux (64 bit).

Code:
SD card has initialized.
Cube010.txt
Done booting!
 
OK. It does work if Cube010.txt does not exist, but if it does exist, weird things start to happen. I have added:
while(!Serial);
immediately after the Serial.begin so that the sketch doesn't, in theory, proceed until I start the serial monitor. When the code is compiled it takes about five seconds before Teensy uploads it. Then COM5 disappears and reappears. When I try to start the serial monitor (COM5) the whole thing hangs. Sometimes it says that COM5 is already in use.
I'm still playing with it but I can't see how the presence or absence of a file on the uSD card can cause a program to fail before it even executes.

Pete
 
OK. It does work if Cube010.txt does not exist, but if it does exist, weird things start to happen. I have added:
while(!Serial);
immediately after the Serial.begin so that the sketch doesn't, in theory, proceed until I start the serial monitor. When the code is compiled it takes about five seconds before Teensy uploads it. Then COM5 disappears and reappears. When I try to start the serial monitor (COM5) the whole thing hangs. Sometimes it says that COM5 is already in use.
I'm still playing with it but I can't see how the presence or absence of a file on the uSD card can cause a program to fail before it even executes.

Pete

This is exactly my experience! I didn't try with the Cube010.txt file not on the SD card. Strange behavior. Still unknown cause.
 
The problem seems to be a difference in the compilers. The compiler for T3 puts the myFilename string somewhere where very bad things happen if you change it at all. The code hangs when it gets to:
Code:
      myFilename[4] = x + '0';

If you change getUnusedFilename so that it prints to a temporary local string, it works.

Code:
char  myFilename[16];

  for(int i=0;i<1000;i++) {
    sprintf(myfilename,"Cube%03d.txt",i);
   ....
   ....
  }
}

Pete
 
Wow, good catch Pete!!

In the original code, myFilename allocates 4 bytes in RAM and 12 bytes in Flash (the string is 11 bytes plus a zero terminator). The 4 bytes in RAM are initialized with the address where the 12 bytes in flash are stored.

Any attempt to write to flash memory causes a bus fault. The default handler just loops infinitely. Because interrupts are disabled, the USB can't respond any longer, so it's necessary to press the pushbutton to reboot. If using Windows and the serial port is in use, that might also trigger a bug in Microsoft's driver where the COM port isn't recognized the next time it appears, because the driver sometimes leaves junk in the Windows registry and is confused by it later (it's pretty shameful how poor Microsoft's own drivers are). Even without the driver bug, this would lock up a Teensy3 and require pressing the button to reprogram.

Changing to myFilename[] allocates 12 bytes in RAM and 12 bytes in Flash. The startup code copies the Flash to RAM before your program begins, so the RAM has a copy of the string which is writable.

In hindsight, there were warning from the compiler (with verbose info turned on from File > Preferences).

Code:
sketch_jun18b.ino:8:20: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
sketch_jun18b.ino: In function 'void getUnusedFilename2()':
sketch_jun18b.ino:58:35: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
sketch_jun18b.ino:66:35: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
sketch_jun18b.ino:74:36: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]

Indeed, the warning for line 8 tries to warn that a constant string address is being giving to a pointer that will allow writing.

This warning also happens for 3 calls to the SD library. It's really a bug in the SD library, where those functions should be declared with "const". I'll fix that in 1.15.
 
In hindsight, there were warning from the compiler

I have verbose info turned on, but I didn't notice those warnings because they flash by so fast and are replaced by dozens of subsequent lines of output. Another problem is that some library code produces warnings and after seeing them over and over I tend to ignore all warnings.
It would be nice if the IDE could print a summary line at the bottom saying how many warnings there were, if any.

Pete
 
Wow guys, thanks so much for the help. Nice catch! Just one of those small overlooks that cause the biggest headaches! Thanks again. Hopefully this thread can help someone else down the road.
 
Status
Not open for further replies.
Back
Top