Teensy 3.2 Serial Port Error From One Line of Code?

Status
Not open for further replies.

motthomas

Member
Hi All,

I'm currently in the process of building the code for an SD card datalogger using a Teensy 3.2 module as the base and have run into an issue with the serial communication that appears to have been caused by a single line of code.

I won't post the entire code here as it is messy and (I believe?) unecessary. My code is based off the dataLogger example in the SDfat library and I was trying to change the default log file name from "Data00.csv" to a name which included a timestamp from the built in RTC. The below code is what I used to create the file name. This code is run only once during the void setup() routine.

Code:
char timestamp[15];
  sprintf(timestamp, "%04d%02d%02d%02d%02d%02d", year(), month(), day(), hour(), minute(), second());
  char fileName[30];
  strcpy (fileName, "CBR250RRi_");
  strcat (fileName, timestamp);
  strcat (fileName, ".csv");
  puts (fileName);

When this code was executed, the serial monitor went into a loop of opening & closing and the error "Error while setting serial port parameters: 9,600 N 8 1" appeared in the Arduino IDE message window. A bit of googling threw up a number of solutions to this error. Mainly uninstall & reinstall the Arduino IDE & Teensy loader. None have worked so far. The forum post here hasn't really helped either as in that case, communication with the Teensy was still possible and new programs could still be loaded.

My problem is that even if I try to revert to a known sketch such as Blink, it does not work. The Arduino IDE is telling me that the sketch has uploaded but I do not get the characteristic windows alerts of a USB device being disconnected & reconnected. There is also no reaction from the Teensy loader window to suggest that the sketch has been loaded. Pressing the button on the Teensy to enter Manual Mode aslo has no reaction. If I try to connect to the Teensy via an external serial monitor such as Docklight, I get an error message saying "The communication port COMXX could not be opened. Windows error #31 - A device attached to the system is not functioning". At the same time, the PC is recognising that a Teensy device is connected to the COM port.
It should also be noted that no errors get thrown up until the serial monitor is opened. The only indication that there is something wrong is the lack of Windows chimes and response from the Teensy loader window.

Back to the code above, I have determined through further investigation that the troublesome code is the last line, "puts (fileName);". I blindly put this line in after looking at an example of strcat without understanding the purpose. Silly me, that will teach me to do this in future. The code works perfectly without the puts() function and I have verified this on another Teensy. However, I have also verified that the puts() function in this place does in fact cause the same error to occur on another Teensy, so now I have 2off Teensy's that I can seemingly not use...

So my question to you guys is, what is it about the puts function that could have caused the errors that I am experiencing? And now that I know what is causing the error and can avoid it, is there any way that I can salvage the 2 Teensy boards that I apparently can't load a new sketch on to? Is there any way of performing a "factory reset" on the board?

More information.
Below is the Verbose information from the Teensy Loader when a Blink sketch is uploaded to a good Teensy
Code:
18:09:16.763: remote connection opened
18:09:16.765: remote cmd: "comment: Teensyduino 1.37 - WINDOWS (teensy_post_compile)"
18:09:16.767: remote cmd: "status"
18:09:16.769: status data sent
18:09:16.771: remote cmd: "dir:C:\Users\Thomas\AppData\Local\Temp\arduino_build_290298\"
18:09:16.773: remote cmd: "file:Blink.ino.hex"
18:09:16.780: File "Blink.ino.hex". 8104 bytes, 3% used
18:09:16.786: remote cmd: "status"
18:09:16.788: status data sent
18:09:16.798: remote connection closed
18:09:16.894: remote connection opened
18:09:16.894: remote cmd: "comment: Teensyduino 1.37 - WINDOWS (teensy_post_compile)"
18:09:16.894: remote cmd: "status"
18:09:16.894: status data sent
18:09:16.894: remote cmd: "dir:C:\Users\Thomas\AppData\Local\Temp\arduino_build_290298\"
18:09:16.904: remote cmd: "file:Blink.ino.hex"
18:09:16.904: File "Blink.ino.hex". 8104 bytes, 3% used
18:09:16.914: remote cmd: "status"
18:09:16.914: status data sent
18:09:16.924: remote connection closed
18:09:17.044: remote connection opened
18:09:17.054: remote cmd: "comment: Teensyduino 1.37 - WINDOWS (teensy_reboot)"
18:09:17.054: remote cmd: "status"
18:09:17.054: status data sent
18:09:17.054: remote cmd: "status"
18:09:17.064: status data sent
18:09:17.164: remote cmd: "status"
18:09:17.164: status data sent
18:09:17.264: remote cmd: "status"
18:09:17.264: status data sent
18:09:17.364: remote cmd: "status"
18:09:17.364: status data sent
18:09:17.464: remote cmd: "status"
18:09:17.464: status data sent
18:09:17.564: remote cmd: "status"
18:09:17.564: status data sent
18:09:17.644: Device came online, code_size = 262144
18:09:17.654: Board is: Teensy 3.2 (MK20DX256), version 1.03
18:09:17.664: File "Blink.ino.hex". 8104 bytes, 3% used
18:09:17.664: set background IMG_ONLINE
18:09:17.684: File "Blink.ino.hex". 8104 bytes, 3% used
18:09:17.684: elf size appears to be 262144
18:09:17.684: elf binary data matches hex file
18:09:17.694: Code size from .elf file = 262144
18:09:17.694: begin operation
18:09:17.694: remote cmd: "status"
18:09:17.704: status data sent
18:09:17.704: flash, block=0, bs=1024, auto=1
18:09:17.714: flash, block=1, bs=1024, auto=1
18:09:17.714: flash, block=2, bs=1024, auto=1
18:09:17.724: flash, block=3, bs=1024, auto=1
18:09:17.744: HID/win32: waiting for device
18:09:17.764: HID/win32: waiting for device
18:09:17.784: HID/win32: waiting for device
18:09:17.784: flash, block=4, bs=1024, auto=1
18:09:17.804: HID/win32: waiting for device
18:09:17.804: flash, block=5, bs=1024, auto=1
18:09:17.814: flash, block=6, bs=1024, auto=1
18:09:17.824: flash, block=7, bs=1024, auto=1
18:09:17.824: sending reboot
18:09:17.834: begin wait_until_offline
18:09:17.984: offline, waited 3
18:09:17.984: end operation, total time = 0.290 seconds
18:09:17.994: set background IMG_REBOOT_OK
18:09:18.004: redraw timer set, image 14 to show for 1200 ms
18:09:18.004: remote cmd: "status"
18:09:18.014: status data sent
18:09:18.024: HID/win32:  vid:046D pid:C31C ver:6400
18:09:18.024: HID/win32:  vid:046D pid:C31C ver:6400
18:09:18.034: HID/win32:  vid:046D pid:C31C ver:6400
18:09:18.034: HID/win32:  vid:25A7 pid:2410 ver:1001
18:09:18.034: HID/win32:  vid:25A7 pid:2410 ver:1001
18:09:18.044: remote connection closed
18:09:19.204: redraw, image 9


While the following is produced when the same sketch is uploaded to one of the boards with the error. It is like the loader tries to send the sketch to the Teensy several times but times out when it gets no response?
Code:
18:11:38.461: remote connection opened
18:11:38.464: remote cmd: "comment: Teensyduino 1.37 - WINDOWS (teensy_post_compile)"
18:11:38.466: remote cmd: "status"
18:11:38.468: status data sent
18:11:38.470: remote cmd: "dir:C:\Users\Thomas\AppData\Local\Temp\arduino_build_290298\"
18:11:38.472: remote cmd: "file:Blink.ino.hex"
18:11:38.478: File "Blink.ino.hex". 8104 bytes, 3% used
18:11:38.485: remote cmd: "status"
18:11:38.488: status data sent
18:11:38.498: remote connection closed
18:11:38.593: remote connection opened
18:11:38.603: remote cmd: "comment: Teensyduino 1.37 - WINDOWS (teensy_post_compile)"
18:11:38.603: remote cmd: "status"
18:11:38.603: status data sent
18:11:38.603: remote cmd: "dir:C:\Users\Thomas\AppData\Local\Temp\arduino_build_290298\"
18:11:38.603: remote cmd: "file:Blink.ino.hex"
18:11:38.613: File "Blink.ino.hex". 8104 bytes, 3% used
18:11:38.613: remote cmd: "status"
18:11:38.623: status data sent
18:11:38.633: remote connection closed
18:11:38.763: remote connection opened
18:11:38.763: remote cmd: "comment: Teensyduino 1.37 - WINDOWS (teensy_reboot)"
18:11:38.763: remote cmd: "status"
18:11:38.763: status data sent
18:11:38.773: remote cmd: "status"
18:11:38.773: status data sent
18:11:38.873: remote cmd: "status"
18:11:38.873: status data sent
18:11:38.973: remote cmd: "status"
18:11:38.973: status data sent
18:11:39.073: remote cmd: "status"
18:11:39.083: status data sent
18:11:39.183: remote cmd: "status"
18:11:39.183: status data sent
18:11:39.283: remote cmd: "status"
18:11:39.283: status data sent
18:11:39.383: remote cmd: "status"
18:11:39.383: status data sent
18:11:39.483: remote cmd: "status"
18:11:39.483: status data sent
18:11:39.583: remote cmd: "status"
18:11:39.583: status data sent
18:11:39.683: remote cmd: "status"
18:11:39.683: status data sent
18:11:39.783: remote cmd: "status"
18:11:39.783: status data sent
18:11:39.883: remote cmd: "status"
18:11:39.883: status data sent
18:11:39.983: remote cmd: "status"
18:11:39.983: status data sent
18:11:40.083: remote cmd: "status"
18:11:40.083: status data sent
18:11:40.183: remote cmd: "status"
18:11:40.183: status data sent
18:11:40.283: remote cmd: "status"
18:11:40.283: status data sent
18:11:40.383: remote cmd: "status"
18:11:40.383: status data sent
18:11:40.483: remote cmd: "status"
18:11:40.483: status data sent
18:11:40.583: remote cmd: "status"
18:11:40.583: status data sent
18:11:40.683: remote cmd: "status"
18:11:40.683: status data sent
18:11:40.783: remote cmd: "status"
18:11:40.783: status data sent
18:11:40.883: remote cmd: "status"
18:11:40.883: status data sent
18:11:40.983: remote cmd: "status"
18:11:40.983: status data sent
18:11:41.083: remote cmd: "status"
18:11:41.083: status data sent
18:11:41.189: remote cmd: "status"
18:11:41.189: status data sent
18:11:41.289: remote cmd: "status"
18:11:41.289: status data sent
18:11:41.389: remote cmd: "status"
18:11:41.389: status data sent
18:11:41.489: remote cmd: "status"
18:11:41.489: status data sent
18:11:41.589: remote cmd: "status"
18:11:41.589: status data sent
18:11:41.689: remote cmd: "status"
18:11:41.689: status data sent
18:11:41.789: remote cmd: "status"
18:11:41.789: status data sent
18:11:41.889: remote cmd: "status"
18:11:41.889: status data sent
18:11:41.989: remote cmd: "status"
18:11:41.989: status data sent
18:11:42.089: remote cmd: "status"
18:11:42.089: status data sent
18:11:42.189: remote cmd: "status"
18:11:42.189: status data sent
18:11:42.289: remote cmd: "status"
18:11:42.289: status data sent
18:11:42.389: remote cmd: "status"
18:11:42.389: status data sent
18:11:42.489: remote cmd: "status"
18:11:42.489: status data sent
18:11:42.589: remote cmd: "status"
18:11:42.589: status data sent
18:11:42.689: remote cmd: "status"
18:11:42.689: status data sent
18:11:42.789: remote cmd: "status"
18:11:42.789: status data sent
18:11:42.889: remote cmd: "status"
18:11:42.889: status data sent
18:11:42.989: remote cmd: "status"
18:11:42.989: status data sent
18:11:43.089: remote cmd: "status"
18:11:43.089: status data sent
18:11:43.189: remote cmd: "status"
18:11:43.189: status data sent
18:11:43.289: remote cmd: "status"
18:11:43.289: status data sent
18:11:43.389: remote cmd: "status"
18:11:43.389: status data sent
18:11:43.489: remote cmd: "status"
18:11:43.489: status data sent
18:11:43.589: remote cmd: "status"
18:11:43.589: status data sent
18:11:43.689: remote cmd: "status"
18:11:43.689: status data sent
18:11:43.799: remote connection closed
 
First, please update to Teensyduino 1.43. Version 1.37 is very old.

I won't post the entire code here as it is messy and (I believe?) unecessary.

Trim away all the unnecessary and messy stuff, so you can post a small program which demonstrates the problem.
 
Ok. Typical! Just after writing all that post above, I tried holding down the button on a faulty Teensy to try again to load a Blink sketch and I got a reaction from the loader. The Blink.ino.hex file that was already open in the loader seems to have been sent successfully and it now works. I can only assume that when I was pressing the button before, the faulty code was still open in the loader?

I don't really understand what the issue was but somehow it is now fixed and I know what caused the issue. There is a lesson there to not just include code willy-nilly without understanding it's purpose and hopefully, if nothing else, it might help other people if they get the same issue.
 
Yes if the bad code hard locks up the teensy on boot, the program button will force it into programming mode to help you reprogram it with good code

The last compiled code will be the one sent to teensy when you push the button
 
Thanks Paul & tonton for the replies. I will update to Teensyduino 1.43. I'm pretty bad at keeping on top of these things!

The below code reproduces the issue without all the unecessary bits and commenting out the puts() function gets it working again. However, I cannot seem to replicate the symptom of "deadness" from the Teensy loader & USB chimes even when pressing the button with bad code. Not sure why... Now when I press the button with bad code, the chimes still come on and the loader just seems to reload the bad code.

Code:
#include <SPI.h>
#include "SdFat.h"
#include <TimeLib.h>
#include <string.h>

// ===============================================================================================================
// Declare variables most likely to be adjusted by user in this block

int log_freq = 2; // Logging rate in Hz
//int can_speed = 500000; // CAN-Bus baud rate in bps 

// ===============================================================================================================


// Initialise SPI pin numbers according to CBR015-0003 Rev00 schematic
const uint8_t chipSelect = 15;
const uint8_t mosi = 7;
const uint8_t miso = 8;
const uint8_t sck = 14;

// Declare variables used by logger
int log_period;
long LogStartMillis, SDWriteTime, MainLoopTime, prev_time, now_time;
bool LogStarted;

// Declare variables logged to file which are not recieved via CAN-Bus
float Time;

//------------------------------------------------------------------------------
// File system object.
SdFat sd;

// Log file.
SdFile file;

// Time in micros for next data record.
uint32_t logTime;

//==============================================================================
// User functions.  Edit writeHeader() and logData() for your requirements.

const uint8_t ANALOG_COUNT = 4;

// Error messages stored in flash.
#define error(msg) sd.errorHalt(F(msg))
//------------------------------------------------------------------------------
void setup() {


  Serial.begin(9600);
  
  // Wait for USB Serial 
  while (!Serial) {
    SysCall::yield();
  }

  // Set up SD card pins. SdFat cannot access card without these declarations
  SPI.setMOSI(mosi);
  SPI.setMISO(miso);
  SPI.setSCK(sck);
  pinMode(chipSelect, OUTPUT);
  
  delay(1000);

  setSyncProvider(getTeensy3Time); // use teensy rtc as time source

  ///*
  char timestamp[15];
  sprintf(timestamp, "%04d%02d%02d%02d%02d%02d", year(), month(), day(), hour(), minute(), second());
  char fileName[30]; 
  strcpy (fileName, "CBR250RRi_");
  strcat (fileName, timestamp);
  strcat (fileName, ".csv");
  puts (fileName);
  //*/

  log_period = (1000000/log_freq); // calculate log period in µs from frequency  
  
  // Initialize at the highest speed supported by the board that is
  // not over 50 MHz. Try a lower speed if SPI errors occur.
  if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) {
    sd.initErrorHalt();
  }

  if (!file.open(fileName, O_CREAT | O_WRITE | O_EXCL)) {
    error("file.open");
  }
  // Read any Serial data.
  do {
    delay(10);
  } while (Serial.available() && Serial.read() >= 0);

  Serial.print(F("Logging to: "));
  Serial.println(fileName);
  Serial.println(F("Type any character to stop"));

  // Write data header.
  writeHeader();

  // Initialise log time
  logTime = (micros() + 1);

  LogStarted = false; //initialise log started flag 
}
//------------------------------------------------------------------------------
void loop() {
  // Time for next record.
  logTime += log_period;

  // Wait for log time.
  int32_t diff;
  do {
    diff = micros() - logTime;
    //Serial.println(diff); 
  } while (diff < 0);

  // Check for data rate too high.
  if (diff > 10) {
    error("Missed data record");
  }

  logData();

  // Force data to SD and update the directory entry to avoid data loss.
  if (!file.sync() || file.getWriteError()) {
    error("write error");
  }

  // Original log stop trigger from dataLogger example. Keep for testing to avoid errors but remove when code complete
  if (Serial.available()) {
    // Close file and stop.
    file.close();
    Serial.println(F("Done"));
    SysCall::halt();
  }

}


//------------------------------------------------------------------------------
// Write data header.
void writeHeader() {

  // Write variable names on first line of file
  file.print(F("Time"));
  for (uint8_t i = 0; i < ANALOG_COUNT; i++) {
    file.print(F(",adc"));
    file.print(i, DEC);
  }
  file.println();

  // Write units on first line of file
  file.print(F("s"));
  for (uint8_t i = 0; i < ANALOG_COUNT; i++) {
    file.print(F(",cnt"));
  }
  file.println();
}
//------------------------------------------------------------------------------
// Log a data record.
void logData() {

  uint16_t data[ANALOG_COUNT];

  if (LogStarted == false){ //check log started flag
    LogStartMillis = millis(); // store time from first log. This is used to calculate Time variable (time since log start in seconds)
    LogStarted = true; //set log started flag to true to avoid this section of code from running again
  }
  
  Time = ((millis() - LogStartMillis) / 1000.0); // calculate time since log start in s

  // Read all channels to avoid SD write latency between readings.
  for (uint8_t i = 0; i < ANALOG_COUNT; i++) {
    data[i] = analogRead(i);
  }
  // Write data to file.  Start with log time in s.

  
  file.print(Time, 3);

  // Write ADC data to CSV record.
  for (uint8_t i = 0; i < ANALOG_COUNT; i++) {
    file.write(',');
    file.print(data[i]);
  }
  file.println();


}
//==============================================================================

time_t getTeensy3Time()
{
  return Teensy3Clock.get();
}
 
yes every time you press it it reloads the last compiled code, try recompiling again with the fixed code or blink code, then press the program button, should work :)
 
Teensy Loader has 2 modes, auto and manual. When in auto mode, which is the default if you've used Arduino to Verify or Upload, when Teensy Loader sees your board appear it will program the most recent code and reboot to it. If you're unsure of this, I recommend arranging your windows so you can keep an eye on Teensy Loader. The programming process goes quickly, so you only have a couple seconds to notice it doing the programming.

In manual mode, it works like you'd expect most GUI programs. You have to open the file and then you click the button to cause it to programmed to your board.
 
Regarding the puts() function, how is that supposed to work? I don't see any way it's related to the SdFat library.

You're probably running the C library puts() function, which will crash unless you go to quite a bit of work to define a "File" for stdout. Otherwise, you can expect a crash or maybe something else very undesirable to happen. This isn't a regular PC operating system!

If you want to actually write data to the SD card, you need to call functions from SD or SdFat or whatever other lib you use that actually accesses the SD card.
 
Status
Not open for further replies.
Back
Top