Compilation error with MscTesting.ino example after migration from teensyduino 1.56 to 1.59

BOBILLIER

Well-known member
Today, I go back to one old project and after a migration to teensyduino 1.59, I encountered one compilation error. In this project, I used a USB stick for datalogging and all worked fine with older teensyduino 1.56 . To find a solution, I tried to compile the MscTesting.ino example proposed in 1.59, but found the same issue.
It's about msController which seems not to exist in SdFat library. Have you a solution to solve this?
 
Today, I go back to one old project and after a migration to teensyduino 1.59, I encountered one compilation error. In this project, I used a USB stick for datalogging and all worked fine with older teensyduino 1.56 . To find a solution, I tried to compile the MscTesting.ino example proposed in 1.59, but found the same issue.
It's about msController which seems not to exist in SdFat library. Have you a solution to solve this?
Those files are outdated and will not work with TD1.59. You need to go into the "USBHost_t36/examples/Storage" in TD1.59 library and check out the examples there. They will show how to initialize and use MSC in TD1.59. "MSCTesting.ino" will not work without modification if at all ;)
 
Ok, thanks wwatson. I have solved the issue by simply replacing "msController " with "USBDrive" in MSCtestting.ino .
 
Hello wwatson.
Sorry , but I need your help with MSC upgrade. Initially in my program, I tested at the start if a USB stick was present and initiated it before writing to it.
For that, I use: msDrive1.checkConnectedInitialized(), but with the Teensyduino upgrade I don't find the same function (I'm a bit lost in USBHost_t36.h) Can you give me a solution for that? thanks
I need to plug and unplug the stick frequently without need to stop and restart all the electronics and be sure that the stick restarts correctly.
Is -there something like a "Mount" and "Unmount" process for USB stick?
 
Last edited:
@BOBILLIER - At the moment here is no mount or unmount commands as this is done automatically when the USB drive is connected to the Teensy. If the USB drive has a valid recognizable filesystem USBHost_t36 will mount the filesystem automatically. When you remove the USB drive USBHost_t36 automatically unmounts the filesystem and marks the USB drive as disconnected. Before disconnecting a USB drive you want to make sure that all open files are closed so as not to loose data. "myusb.Task()" should be called before checking for connected USB drives. This triggers the scan for connected devices. Here is a sketch that demonstrates hot plugging 1 or 2 USB drives:
Code:
/* MSC Hotplug testing */
#include <USBHost_t36.h>

// Setup USBHost_t36 and as many HUB ports as needed.
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
USBHub hub3(myusb);
USBHub hub4(myusb);

// Instances for the number of USB drives you are using.
USBDrive myDrive1(myusb); // Up to two USB drives for testing.
USBDrive myDrive2(myusb);
// Create a drive list
USBDrive *drive_list[] = {&myDrive1, &myDrive2};

// Instances for accessing the files on each drive.
// Up to 4 partitions for each drive times 2 drives = 8 partitions
// if needed. (one partition per drive works as well).
USBFilesystem pf1(myusb);
USBFilesystem pf2(myusb);
USBFilesystem pf3(myusb);
USBFilesystem pf4(myusb);
USBFilesystem pf5(myusb);
USBFilesystem pf6(myusb);
USBFilesystem pf7(myusb);
USBFilesystem pf8(myusb);

// Create a filesystem list for all available partitions.
USBFilesystem *filesystem_list[] = {&pf1, &pf2, &pf3, &pf4, &pf5, &pf6, &pf7, &pf8};

void setup()
{
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for Arduino Serial Monitor to connect.
  }

  // Start USBHost_t36
  myusb.begin();
  delay(500);  // give drives a little time to startup
}

void loop(void) {

  Serial.printf("%c MSC Hotplug Testing\n\n",12); // Best seen using VT100-VT102 aware terminal emulator.
  Serial.printf("This sketch is setup for hotplugging up to 2 devices\n");
  Serial.printf("if using 2 USB drives you will a USB HUB, but is not required for one USB drive testing.\n");
  Serial.printf("After plugging or unplugging drives press enter to refresh display.\n\n");

  myusb.Task();  // Refresh USBHost_t36.

  // lets check each of the drives.
  for (uint16_t drive_index = 0; drive_index < (sizeof(drive_list)/sizeof(drive_list[0])); drive_index++) {
    USBDrive *pdrive = drive_list[drive_index]; // Create a temporary pointer to a drive instance.
    if (*pdrive) { // Is this drive connected??
      Serial.println("***************************************************");
      Serial.printf(" === Drive %d connected and using ", drive_index);
      if (!pdrive->filesystemsStarted()) { // See if filesystem has started yet.
        pdrive->startFilesystems(); // If not started then start filesystem.
      }

      bool first_fs = true;
      // Find filesystem for this drive.
      for (uint16_t fs_index = 0; fs_index < (sizeof(filesystem_list)/sizeof(filesystem_list[0])); fs_index++) {
        USBFilesystem *pfs = filesystem_list[fs_index]; // Create a temporary pointer to filesystem instance.
        if (*pfs && pfs->device == pdrive) { // Associate with correct USB drive.

          Serial.printf("file system %u\n", fs_index);
          const uint8_t *psz;
          // print out some info about drive.
          if ((psz = pfs->manufacturer()) != nullptr) Serial.printf("            Manufacturer: %s\n", psz);
          if ((psz = pfs->product()) != nullptr) Serial.printf("                 Product: %s\n", psz);
          if ((psz = pfs->serialNumber()) != nullptr) Serial.printf("\t   Serial Number: %s\n", psz);
          Serial.printf(F("\t      HUB Number: %d\n"), pdrive->msDriveInfo.hubNumber);
          Serial.printf(F("\t        HUB Port: %d\n"), pdrive->msDriveInfo.hubPort);
          Serial.printf(F("\t  Device Address: %d\n"), pdrive->msDriveInfo.deviceAddress);
          Serial.printf(F("\tRemovable Device: "));
          if(pdrive->msDriveInfo.inquiry.Removable == 1) {
            Serial.printf(F("YES\n"));
          } else {
            Serial.printf(F("NO\n"));
          }
        } else {
          pfs->mscfs.end(); // Unmount partition (sort of!!)
        }
      }
    } else {
      Serial.println("***************************************************");
      Serial.printf(" === Drive %d NOT connected ===\n", drive_index);
    }
      Serial.println("***************************************************");
  }
  while (Serial.read() != -1) ;
  Serial.println("\n *** Press enter after changes to refresh drive list ***");
  while (Serial.read() == -1)  myusb.Task();
  while (Serial.read() != -1) ;
 
}
If testing with two USB sticks you will need a USB HUB connected, but it will work with just one USB drive.
I hope this helps as I did not see your sketch so as to understand what you were trying to accomplish :)
 
@BOBILLIER - At the moment here is no mount or unmount commands as this is done automatically when the USB drive is connected to the Teensy. If the USB drive has a valid recognizable filesystem USBHost_t36 will mount the filesystem automatically. When you remove the USB drive USBHost_t36 automatically unmounts the filesystem and marks the USB drive as disconnected. Before disconnecting a USB drive you want to make sure that all open files are closed so as not to loose data. "myusb.Task()" should be called before checking for connected USB drives. This triggers the scan for connected devices. Here is a sketch that demonstrates hot plugging 1 or 2 USB drives:
Code:
/* MSC Hotplug testing */
#include <USBHost_t36.h>

// Setup USBHost_t36 and as many HUB ports as needed.
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
USBHub hub3(myusb);
USBHub hub4(myusb);

// Instances for the number of USB drives you are using.
USBDrive myDrive1(myusb); // Up to two USB drives for testing.
USBDrive myDrive2(myusb);
// Create a drive list
USBDrive *drive_list[] = {&myDrive1, &myDrive2};

// Instances for accessing the files on each drive.
// Up to 4 partitions for each drive times 2 drives = 8 partitions
// if needed. (one partition per drive works as well).
USBFilesystem pf1(myusb);
USBFilesystem pf2(myusb);
USBFilesystem pf3(myusb);
USBFilesystem pf4(myusb);
USBFilesystem pf5(myusb);
USBFilesystem pf6(myusb);
USBFilesystem pf7(myusb);
USBFilesystem pf8(myusb);

// Create a filesystem list for all available partitions.
USBFilesystem *filesystem_list[] = {&pf1, &pf2, &pf3, &pf4, &pf5, &pf6, &pf7, &pf8};

void setup()
{
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for Arduino Serial Monitor to connect.
  }

  // Start USBHost_t36
  myusb.begin();
  delay(500);  // give drives a little time to startup
}

void loop(void) {

  Serial.printf("%c MSC Hotplug Testing\n\n",12); // Best seen using VT100-VT102 aware terminal emulator.
  Serial.printf("This sketch is setup for hotplugging up to 2 devices\n");
  Serial.printf("if using 2 USB drives you will a USB HUB, but is not required for one USB drive testing.\n");
  Serial.printf("After plugging or unplugging drives press enter to refresh display.\n\n");

  myusb.Task();  // Refresh USBHost_t36.

  // lets check each of the drives.
  for (uint16_t drive_index = 0; drive_index < (sizeof(drive_list)/sizeof(drive_list[0])); drive_index++) {
    USBDrive *pdrive = drive_list[drive_index]; // Create a temporary pointer to a drive instance.
    if (*pdrive) { // Is this drive connected??
      Serial.println("***************************************************");
      Serial.printf(" === Drive %d connected and using ", drive_index);
      if (!pdrive->filesystemsStarted()) { // See if filesystem has started yet.
        pdrive->startFilesystems(); // If not started then start filesystem.
      }

      bool first_fs = true;
      // Find filesystem for this drive.
      for (uint16_t fs_index = 0; fs_index < (sizeof(filesystem_list)/sizeof(filesystem_list[0])); fs_index++) {
        USBFilesystem *pfs = filesystem_list[fs_index]; // Create a temporary pointer to filesystem instance.
        if (*pfs && pfs->device == pdrive) { // Associate with correct USB drive.

          Serial.printf("file system %u\n", fs_index);
          const uint8_t *psz;
          // print out some info about drive.
          if ((psz = pfs->manufacturer()) != nullptr) Serial.printf("            Manufacturer: %s\n", psz);
          if ((psz = pfs->product()) != nullptr) Serial.printf("                 Product: %s\n", psz);
          if ((psz = pfs->serialNumber()) != nullptr) Serial.printf("\t   Serial Number: %s\n", psz);
          Serial.printf(F("\t      HUB Number: %d\n"), pdrive->msDriveInfo.hubNumber);
          Serial.printf(F("\t        HUB Port: %d\n"), pdrive->msDriveInfo.hubPort);
          Serial.printf(F("\t  Device Address: %d\n"), pdrive->msDriveInfo.deviceAddress);
          Serial.printf(F("\tRemovable Device: "));
          if(pdrive->msDriveInfo.inquiry.Removable == 1) {
            Serial.printf(F("YES\n"));
          } else {
            Serial.printf(F("NO\n"));
          }
        } else {
          pfs->mscfs.end(); // Unmount partition (sort of!!)
        }
      }
    } else {
      Serial.println("***************************************************");
      Serial.printf(" === Drive %d NOT connected ===\n", drive_index);
    }
      Serial.println("***************************************************");
  }
  while (Serial.read() != -1) ;
  Serial.println("\n *** Press enter after changes to refresh drive list ***");
  while (Serial.read() == -1)  myusb.Task();
  while (Serial.read() != -1) ;
 
}
If testing with two USB sticks you will need a USB HUB connected, but it will work with just one USB drive.
I hope this helps as I did not see your sketch so as to understand what you were trying to accomplish :)
Many thanks for your example. I take a look at that and surely progress to my project.
 
Many thanks for your example. I take a look at that and surely progress to my project.
@BOBILLIER - At the moment here is no mount or unmount commands as this is done automatically when the USB drive is connected to the Teensy. If the USB drive has a valid recognizable filesystem USBHost_t36 will mount the filesystem automatically. When you remove the USB drive USBHost_t36 automatically unmounts the filesystem and marks the USB drive as disconnected. Before disconnecting a USB drive you want to make sure that all open files are closed so as not to loose data. "myusb.Task()" should be called before checking for connected USB drives. This triggers the scan for connected devices. Here is a sketch that demonstrates hot plugging 1 or 2 USB drives:
Code:
/* MSC Hotplug testing */
#include <USBHost_t36.h>

// Setup USBHost_t36 and as many HUB ports as needed.
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
USBHub hub3(myusb);
USBHub hub4(myusb);

// Instances for the number of USB drives you are using.
USBDrive myDrive1(myusb); // Up to two USB drives for testing.
USBDrive myDrive2(myusb);
// Create a drive list
USBDrive *drive_list[] = {&myDrive1, &myDrive2};

// Instances for accessing the files on each drive.
// Up to 4 partitions for each drive times 2 drives = 8 partitions
// if needed. (one partition per drive works as well).
USBFilesystem pf1(myusb);
USBFilesystem pf2(myusb);
USBFilesystem pf3(myusb);
USBFilesystem pf4(myusb);
USBFilesystem pf5(myusb);
USBFilesystem pf6(myusb);
USBFilesystem pf7(myusb);
USBFilesystem pf8(myusb);

// Create a filesystem list for all available partitions.
USBFilesystem *filesystem_list[] = {&pf1, &pf2, &pf3, &pf4, &pf5, &pf6, &pf7, &pf8};

void setup()
{
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for Arduino Serial Monitor to connect.
  }

  // Start USBHost_t36
  myusb.begin();
  delay(500);  // give drives a little time to startup
}

void loop(void) {

  Serial.printf("%c MSC Hotplug Testing\n\n",12); // Best seen using VT100-VT102 aware terminal emulator.
  Serial.printf("This sketch is setup for hotplugging up to 2 devices\n");
  Serial.printf("if using 2 USB drives you will a USB HUB, but is not required for one USB drive testing.\n");
  Serial.printf("After plugging or unplugging drives press enter to refresh display.\n\n");

  myusb.Task();  // Refresh USBHost_t36.

  // lets check each of the drives.
  for (uint16_t drive_index = 0; drive_index < (sizeof(drive_list)/sizeof(drive_list[0])); drive_index++) {
    USBDrive *pdrive = drive_list[drive_index]; // Create a temporary pointer to a drive instance.
    if (*pdrive) { // Is this drive connected??
      Serial.println("***************************************************");
      Serial.printf(" === Drive %d connected and using ", drive_index);
      if (!pdrive->filesystemsStarted()) { // See if filesystem has started yet.
        pdrive->startFilesystems(); // If not started then start filesystem.
      }

      bool first_fs = true;
      // Find filesystem for this drive.
      for (uint16_t fs_index = 0; fs_index < (sizeof(filesystem_list)/sizeof(filesystem_list[0])); fs_index++) {
        USBFilesystem *pfs = filesystem_list[fs_index]; // Create a temporary pointer to filesystem instance.
        if (*pfs && pfs->device == pdrive) { // Associate with correct USB drive.

          Serial.printf("file system %u\n", fs_index);
          const uint8_t *psz;
          // print out some info about drive.
          if ((psz = pfs->manufacturer()) != nullptr) Serial.printf("            Manufacturer: %s\n", psz);
          if ((psz = pfs->product()) != nullptr) Serial.printf("                 Product: %s\n", psz);
          if ((psz = pfs->serialNumber()) != nullptr) Serial.printf("\t   Serial Number: %s\n", psz);
          Serial.printf(F("\t      HUB Number: %d\n"), pdrive->msDriveInfo.hubNumber);
          Serial.printf(F("\t        HUB Port: %d\n"), pdrive->msDriveInfo.hubPort);
          Serial.printf(F("\t  Device Address: %d\n"), pdrive->msDriveInfo.deviceAddress);
          Serial.printf(F("\tRemovable Device: "));
          if(pdrive->msDriveInfo.inquiry.Removable == 1) {
            Serial.printf(F("YES\n"));
          } else {
            Serial.printf(F("NO\n"));
          }
        } else {
          pfs->mscfs.end(); // Unmount partition (sort of!!)
        }
      }
    } else {
      Serial.println("***************************************************");
      Serial.printf(" === Drive %d NOT connected ===\n", drive_index);
    }
      Serial.println("***************************************************");
  }
  while (Serial.read() != -1) ;
  Serial.println("\n *** Press enter after changes to refresh drive list ***");
  while (Serial.read() == -1)  myusb.Task();
  while (Serial.read() != -1) ;
 
}
If testing with two USB sticks you will need a USB HUB connected, but it will work with just one USB drive.
I hope this helps as I did not see your sketch so as to understand what you were trying to accomplish :)
Hi wwatson. Thanks for your help, all is wright now . I have modify my program and all functions run as expected.
One another thing, do you now how update the date of the file when you write to them ? Actually all my files have same dates (31/12/2024 23:00] and I don't know were come from this date and how modify it. I have RTC on my device and I can use it to obtain the good time.
 
@BOBILLIER - You will need to make sure that the RTC is set to the current time and date. USBHost_t36 sets the time and date fields whenever a file is created and closed or modified. If I remember correctly, the actual functions that set the modify time and date are located in "FS.h". Not sure though. This sketch shows how to use "getModifyTime()" to display the time and date info:
Code:
/*
 MSC USB Drive basic directory list example
 created   Nov 2010
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe
 modified 08 Apr 2023
 by Warren Watson
 
 This example code is in the public domain.
    
 */
#include <USBHost_t36.h>

// Setup USBHost_t36 and as many HUB ports as needed.
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
USBHub hub3(myusb);
USBHub hub4(myusb);

// Setup MSC for the number of USB Drives you are using. (one for this
// example). Mutiple  USB drives can be used. Hot plugging is supported.
USBDrive myDrive(myusb);
USBFilesystem firstPartition(myusb);

// Volume name buffer
char    volumeName[32];
elapsedMillis mscTimeOut;
uint8_t errCode = MS_CBW_PASS;

void setup()
{
 
  // Wait for port to open:
  while (!Serial) {
    yield(); // wait for serial port to connect.
  }

  // Start USBHost_t36, HUB(s) and USB devices.
  myusb.begin();
  // There is a slight delay after a USB MSC device is plugged in which
  // varys with the device being used. The device is internally
  // initializing.
  Serial.print("\nInitializing USB MSC drive...\n");

  mscTimeOut = 0;
  while(!myDrive) {
    if((mscTimeOut > MSC_CONNECT_TIMEOUT) && (myDrive.errorCode() == MS_NO_MEDIA_ERR)) {
      Serial.println("No drive connected yet!!!!");
      Serial.println("Connect a drive to continue...\n");
      while(!myDrive);
    }
    delay(1);
  }
  mscTimeOut = 0;
  // Wait for claim proccess to finish.
  // But not forever.
  while(!firstPartition) {
    myusb.Task();
    if(mscTimeOut >  MSC_CONNECT_TIMEOUT) {
      Serial.print("Timeout --> error code: ");
      Serial.println(myDrive.errorCode(), DEC);
      Serial.println("Halting...");
      while(1);
    }
    delay(1);
  }
  Serial.println("initialization done.");
  // Get the volume name if it exists.
  firstPartition.mscfs.getVolumeLabel(volumeName, sizeof(volumeName));
  Serial.println("\nDirectory Listing:");
  Serial.print("Volume Name: ");
  Serial.println(volumeName);
  File root = firstPartition.open("/");
  printDirectory(root, 0);
 
  Serial.println("done!");
}

void loop()
{
  // nothing happens after setup finishes.
}

void printDirectory(File dir, int numSpaces) {
   while(true) {
     File entry = dir.openNextFile();
     if (! entry) {
       //Serial.println("** no more files **");
       break;
     }
     printSpaces(numSpaces);
     Serial.print(entry.name());
     if (entry.isDirectory()) {
       Serial.println("/");
       printDirectory(entry, numSpaces+2);
     } else {
       // files have sizes, directories do not
       printSpaces(48 - numSpaces - strlen(entry.name()));
       Serial.print("  ");
       Serial.printf(F("%10ld"),entry.size()); // Formatted filesize.
       DateTimeFields datetime;
       if (entry.getModifyTime(datetime)) {
         printSpaces(4);
         printTime(datetime);
       }
       Serial.println();
     }
     entry.close();
   }
}

void printSpaces(int num) {
  for (int i=0; i < num; i++) {
    Serial.print(" ");
  }
}

void printTime(const DateTimeFields tm) {
  const char *months[12] = {
    "January","February","March","April","May","June",
    "July","August","September","October","November","December"
  };
  for(uint8_t i = 0; i <= 1; i++) Serial.printf(F(" "));
  Serial.printf(F("%9s %02d %02d %02d:%02d:%02d"), // Show date/time.
                months[tm.mon],tm.mday,tm.year + 1900,
                tm.hour,tm.min,tm.sec);
}
Try it :D

EDIT: TYPOS...
 
Finally, I have just add this :

void dateTime(uint16_t* date, uint16_t* time)
{
*date = FAT_DATE(year(), month(), day());
*time = FAT_TIME(hour(), minute(), second());
}

and this in my setup :

SdFile::dateTimeCallback(dateTime);

and now the date and time of my files are ok and updated at each write.

Wonderful

source
 
Back
Top