Serial.printf("String without a terminating linefeed"); Doesn't Display on Monitor

Status
Not open for further replies.

paynterf

Well-known member
Serial.printf("String without a terminating linefeed"); Doesn't Display on Monitor

I've run across a weird issue with Serial.printf() on a Teensy 3.2. I am trying to use a small Teensy program I created a few years ago, and discovered that some of my print statements no longer display on the serial monitor. Here's a small demo program that reproduces the issue:

Code:
/*
    Name:       Printf_Demo.ino
    Created:	5/24/2020 10:13:54 AM
    Author:     FRANKNEWXPS15\Frank
*/


void setup()
{

    Serial.begin(115200);


    // wait until serial port opens for native USB devices
    while (!Serial) 
    {
        delay(10);
    }

    Serial.print("Serial.print without a terminating linefeed");

    Serial.printf("Serial.printf without a terminating linefeed");

    Serial.println("Serial.println");
}

void loop()
{


}


When I run this on a Teensy 3.2, I get the following output:

Code:
Opening port
Port open
Serial.print without a terminating linefeedSerial.printf without a terminating linefeedSerial.println

However, if I comment out the "Serial.println("Serial.println");" line, I get no output at all.

If I remove the 'Serial.printf()' statement and change the target to an Arduino Uno, then I get an output with or without a terminating linefeed

Anybody know what I'm doing wrong here?

Dell XPS15 7590
Windows 10 64-bit
Visual Studio 2019 Community Edition
Visual Micro Add-on

TIA,

Frank
 
Don't know if this is relevant or not, but I have also started noticing that the Teensy USB port is being reported with a strange name that doesn't show up as a port in device manager

Code:
Uploading 'Printf_Demo' to 'Teensy 3.2 / 3.1' using 'usb:10000/0/0/2/4/8'
 
FWIW, I think I'm running TeensyDuino 1.48


Code:
Deep search for libraries ...
"C:\Program Files (x86)\Arduino\hardware\teensy\..\tools\arm\bin\arm-none-eabi-g++" -E -CC -x c++ -w  -g -Wall -ffunction-sections -fdata-sections -nostdlib -fno-exceptions -fpermissive -felide-constructors -std=gnu++14 -Wno-error=narrowing -fno-rtti -mthumb -mcpu=cortex-m4 -fsingle-precision-constant   -D__MK20DX256__ -DTEENSYDUINO=148 -DARDUINO=108010 -DF_CPU=96000000 -DUSB_SERIAL -DLAYOUT_US_ENGLISH -I"C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy3" "C:\Users\Frank\AppData\Local\Temp\VMBuilds\Printf_Demo\teensy31\Debug\Printf_Demo.cpp" -o "nul"
 
Sorry I am not sure what your setup is here as you mention Visual Studio and Visual Micro... So are you building with Arduino or are you building within Visual Studio?
Also which monitor program are you using? something with Visual Micro or the stuff built into Arduino?

Note: over the last many releases of Teensyduino (current one is 1.52), I know a lot of work went into improving the Serial monitor.

But I ran your sketch on T3.5 on 1.82 (1.52+) and it works fine with or without... Using Teensy Serial viewer
 
Kurt,

Thanks for looking at this!

I have the Visual Micro add-in to Visual Studio 2019 Community Edition. I develop Arduino code in Visual Studio, and Visual Micro handles the interface to the Arduino world for compiles, and connecting to the VS serial monitor. Interesting that the program runs properly on your setup (1.82/1.52+).

I'm so used to running in the VS environment that I never even thought of trying to run the demo in the Arduino IDE. When I tried it, I got serial monitor output with or without the 'Serial.println("Serial.println");' statement. So, now I know that I have some sort of configuration issue with VS2019/Visual Micro that's only triggered when the target is a Teensy - ugly, but still a step in the right direction! ;-)

Regards,

Frank
 
Here's another short program that exhibits the problem, both in VS2019 with Visual Micro, and in the latest version of Arduino IDE (1.8.12) and Teensyduino (1.52).

Code:
#include <Stepper.h>

// change this to fit the number of steps per revolution for your motor
const int stepsPerRevolution = 200;  
//const int stepsPerRevolution = 32; 

// initialize the stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);
//Stepper myStepper(stepsPerRevolution, 2, 3, 4, 5);

//08/26/17 added for scan support
const int SCAN_START_PIN = 2;
const int SCAN_COMPLETE_PIN = 3;
const float STEPS_PER_REV = 200;
const float STEPS_PER_DEG = STEPS_PER_REV / 360;
const int DEFAULT_STEPS_TO_MOVE = 10;
char Instr[20];
//const int POSITIONING_SPEED_RPM = 20;  
const int POSITIONING_SPEED_RPM = 100;  

int zeroPos;
int scanStartDeg;
int scanStartSteps; //scanStartDeg converted to steps
int scanStopDeg;
int scanStopSteps; //scanStopDeg converted to steps
int stepsToMove;
int curStepVal; //keeps track of current position, in steps

bool bStopPosDone = false;

int scanSpeedRpm = 6;



void setup() {
	Serial.begin(115200);
	pinMode(SCAN_START_PIN, INPUT_PULLUP);
	pinMode(SCAN_COMPLETE_PIN, OUTPUT);
	digitalWrite(SCAN_COMPLETE_PIN, HIGH);

	//added 05/26/20
	Serial.printf("Serial.printf: NEMA-17 Stepper Rotary Table Program\n");
  Serial.println("Serial.printf: NEMA-17 Stepper Rotary Table Program");

	//get motor speed to be used
	scanSpeedRpm = GetIntegerParameter("Motor speed RPM", 6);
	//myStepper.setSpeed(scanSpeedRpm);


	//set zero position
	Serial.println("Set stepper zero position.  Enter +steps for CW, -steps for CCW, Q to exit");
	while (!bStopPosDone)
	{
		while (Serial.available() == 0); //waits for input
		if (toascii(Serial.peek()) == 'Q' || toascii(Serial.peek()) == 'q')
		{
			bStopPosDone = true;
			curStepVal = 0;
		}
		else
		{
			stepsToMove = GetIntegerParameter("Steps to move (- = CCW, + = CW)?", DEFAULT_STEPS_TO_MOVE);
			Serial.print("Steps to move = "); Serial.println(stepsToMove);
			myStepper.setSpeed(POSITIONING_SPEED_RPM);
			myStepper.step(stepsToMove);

////DEBUG!!
//			Serial.printf("First\n");
//			for (size_t i = 0; i < 3; i++)
//			{
//				myStepper.step(stepsToMove);
//			}
//			Serial.printf("Second\n");
//			for (size_t i = 0; i < 3; i++)
//			{
//				myStepper.step(-stepsToMove);
//			}
//			Serial.printf("Third\n");
//			for (size_t i = 0; i < 3; i++)
//			{
//				myStepper.step(2*stepsToMove);
//			}
//			Serial.printf("Fourth\n");
//			for (size_t i = 0; i < 3; i++)
//			{
//				myStepper.step(-2*stepsToMove);
//			}
////DEBUG!!
		}
	}

	Serial.readString(); //clear the input buffer - could still have chars in it
	Serial.print("curStepVal = "); Serial.println(curStepVal);

	//set scan start/stop positions in degrees
	scanStartDeg = GetIntegerParameter("Scan Start Pos in Degrees Relative to Zero", -90);
	scanStopDeg = GetIntegerParameter("Scan Stop Pos in Degrees Relative to Zero", 90);

	Serial.println("Run Parameters:");
	Serial.print("Speed: "); Serial.print(scanSpeedRpm); Serial.println(" RPM");
	Serial.print("Scan Start: "); Serial.print(scanStartDeg); Serial.println(" Deg");
	Serial.print("Scan Stop: "); Serial.print(scanStopDeg); Serial.println(" Deg");
	Serial.println();

	//go to scan start pos
	scanStartSteps = (int)scanStartDeg*STEPS_PER_DEG;
	Serial.print("steps to move = "); Serial.println(scanStartSteps);
	myStepper.step(scanStartSteps);
	curStepVal += scanStartSteps;
	Serial.print("Done - curStepVal = "); Serial.println(curStepVal);

	while (1)  //user has opportunity to exit after each scan
	{
		//wait for trigger
		Serial.printf("waiting for LOW on SCAN_START_PIN (pin %d) ...\n", SCAN_START_PIN);
		while (digitalRead(SCAN_START_PIN) == HIGH)
		{
			delay(100);
		}
		Serial.println("Triggered - starting scan.");

		//go to stop pos
		scanStopSteps = (int)scanStopDeg*STEPS_PER_DEG - curStepVal;
		Serial.print("steps to move = "); Serial.println(scanStopSteps);
		myStepper.setSpeed(scanSpeedRpm);
		myStepper.step(scanStopSteps);
		curStepVal += scanStopSteps;
		Serial.print("Done - curStepVal = "); Serial.println(curStepVal);

		//quit
		Serial.printf("Outputting LOW on SCAN_COMPLETE_PIN (pin %d)\n",SCAN_COMPLETE_PIN);

		//toggle for 1 sec
		digitalWrite(SCAN_COMPLETE_PIN, LOW);
		delay(1000);
		digitalWrite(SCAN_COMPLETE_PIN, HIGH);

		//return to start position
		Serial.println("Resetting for next scan.");
		myStepper.setSpeed(POSITIONING_SPEED_RPM);
		myStepper.step(-scanStopSteps);
		curStepVal -= scanStopSteps;
		Serial.print("Done - curStepVal = "); Serial.println(curStepVal);
		myStepper.setSpeed(scanSpeedRpm);
	}
}


void loop() 
{
}

int GetIntegerParameter(String prompt, int defaultval)
{
	int param = 0;
	bool bDone = false;

	while (!bDone)
	{
		Serial.print(prompt); Serial.print(" ("); Serial.print(defaultval); Serial.print("): ");
		while (Serial.available() == 0); //waits for input
										 //String res = Serial.readString().trim();
		String res = Serial.readString();
		res.trim();

		int reslen = res.length();
		if (reslen == 0) //user entered CR only
		{
			bDone = true;
			param = defaultval;
		}
		else
		{
			res.toCharArray(Instr, reslen + 1);
			//if (isNumeric(Instr) && atoi(Instr) >= 0)
			if (isNumeric(Instr))
			{
				param = atoi(Instr);
				bDone = true;
			}
			else
			{
				Serial.print(Instr); Serial.println(" Is invalid input - please try again");
			}
		}
	}
	Serial.println(param);
	return param;
}

// check a string to see if it is numeric and accept Decimal point
//copied from defragster's post at https://forum.pjrc.com/threads/27842-testing-if-a-string-is-numeric
bool isNumeric(char * str)
{
	byte ii = 0;
	bool RetVal = false;
	if ('-' == str[ii])
		ii++;
	while (str[ii])
	{
		if ('.' == str[ii]) {
			ii++;
			break;
		}
		if (!isdigit(str[ii])) return false;
		ii++;
		RetVal = true;
	}
	while (str[ii])
	{
		if (!isdigit(str[ii])) return false;
		ii++;
		RetVal = true;
	}
	return RetVal;
}

When this is run, the serial monitor initially displays nothing. If the user then sends a non-numeric character ('x' in this case) via the serial monitor to the Teensy, you get this output

Code:
x Is invalid input - please try again
Motor speed RPM (6):

From then on, the program behaves and responds normally.

Ideas?

Frank
 
Here's another short program that exhibits the problem, both in VS2019 with Visual Micro, and in the latest version of Arduino IDE (1.8.12) and Teensyduino (1.52).

Ideas?

Frank

Frank:

I took your latest program & created a new sketch with the contents (cut & paste) from your post #6. I am running Arduino 1.8.2 & Teensyduino 1.52 under Windows 10pro, using a Teensy 4.1 (that & Teensy 4.0 are all I have, so I can't truly reproduce your environment exactly).

As written, I get the exact same results that you last reported (in post #6).

However, if I add a delay(2000) as follows:

Code:
void setup() {
   Serial.begin(115200);

   delay(2000);
   
   pinMode(SCAN_START_PIN, INPUT_PULLUP);
   pinMode(SCAN_COMPLETE_PIN, OUTPUT);
   digitalWrite(SCAN_COMPLETE_PIN, HIGH);

I get the following report (which I'm assuming represents the result that you are expecting):

Code:
Serial.printf: NEMA-17 Stepper Rotary Table Program
Serial.printf: NEMA-17 Stepper Rotary Table Program

Motor speed RPM (6):

It appears that what you are actually experiencing is the fact that the USB serial port on the Teensy talking thru the Serial Monitor takes some time to initialize before being able to reliably pass data. I would not expect that it is actually related to including Serial.printf() vs. Serial.println().

Experiment with this & see what you think . . .

Mark J Culross
KD5RXT
 
Indeed p#1 has thius where p#6 does not:
Code:
    while (!Serial) 
    {
        delay(10);
    }

As noted Teensy enters setup() (at 300ms) before the PC can cooperate to complete the USB connect ( perhaps some 50 to 500ms later ). Without that complete then early prints can get lost. That will hang forever if not connected to USB where something like this will only wait a fixed time - here 4 seconds.
Code:
    while (!Serial && millis() < 4000 );
 
Thanks for the feedback. I just tested this whole thing again, using delay(2000), delay(3000) and delay(5000). Nothing works on my Printf_Demo program with a T3.2. However, I just tried the same thing with a T3.5, and voila! - it works fine.

Here's the Printf_Demo program again, with code added to display the time required for the Serial object to be available:

Code:
/*
    Name:       Printf_Demo.ino
    Created:	5/24/2020 10:13:54 AM
    Author:     FRANKNEWXPS15\Frank
*/


void setup()
{

    Serial.begin(115200);


    // wait until serial port opens for native USB devices
    unsigned long now = millis();
    while (!Serial)
    {
        delay(10);
    }
    
    Serial.print("Serial available after "); Serial.print(millis()-now); Serial.print(" millisec");
    Serial.print("Serial.print without a terminating linefeed");

    Serial.printf("Serial.printf without a terminating linefeed");

    //Serial.println("Serial.println");
}

void loop()
{


}

Here's the output from this program using a T3.5

Code:
Serial available after 480 millisecSerial.print without a terminating linefeedSerial.printf without a terminating linefeed

Same code, with a T3.2 target. Now I get the exact same (correct) output, and now my Teensy_NEMA17_RotaryTable program also works properly, with either

Code:
delay(3000)
or

Code:
    unsigned long now = millis();
    while (!Serial)
    {
        delay(10);
    }


My head hurts! :(
 
OK, so there may be something going on with the way Teensy is reporting USB ports. There appear to be TWO ports associated with a Teensy connected via a USB cable to my Win10 box. There is a port called something like "Teensy 3.5 at usb:10000/0/0/2/4/8" and another one called "Com 7 - USB Serial Device"

Annotation 2020-05-27 080522.jpg

If I use the '10000/0/0/2/4/8' port, I get the improper behavior. If instead I use the 'Com 7 USB Serial Device', it seems to work fine.

The '10000/0/0...' device nomenclature started showing up a few weeks (or a few months - time gets messed up in lockdown) ago, and I have been using this selection because it is clear it is associated with the Teensy device (I quite often have several USB devices connected simultaneously, some Teensy, some Arduino, some other things entirely). In the past, I only had the 'Com X USB Serial Device' option available, so I had to guess (or disconnect/reconnect the Teensy to see which Com X number disappeared/re-appeared), so I thought the '10000/0/0...' nomenclature was a welcome improvement. Now, I'm thinking 'not so much'.

And now the whole thing seems to be random. I can get proper serial output sometimes by changing boards or changing ports, but there doesn't seem to be anything consistent - UGGGGHHHHH!!!

Frank
 
In the continuing saga, I can sometimes regain full serial monitor functionality by physically disconnecting the Teensy USB cable, closing VS2019 entirely, re-opening it, and then selecting the 'COMX USB Serial Device' entry rather than the 'Teensy 3.x at usb:10000/0/0...' one. What a nightmare!

Annotation 2020-05-27 183409.jpg

Frank
 
Seems to be an issue with VStudio Serial Monitor? Maybe it doesn't ping the USB pins as needed - certainly confused about what is where.

You can install TyCommander (formerly TyQt) as a stand alone SerMon in your case. Either do a button push for upload - or disconnect Serial in TyComm GUI before attempting upload. Then Click the Serial connect icon again after upload.
 
This seems to work semi-consistently:

Close VS2019
Disconnect Teensy USB cable
Re-open VS2019 and verify that Teensy USB port options are missing
Re-connect Teensy USB cable
Select the 'COMx USB Serial' option

Anyone else experiencing this with? I do a LOT of development using Teensy targets (right now I have two 3.5 and a 3.2 project on my bench), and this is turning out to be a major PITA. None of this was happening a month or two ago, so either something in TeensyDuino changed or something in Win10 has changed. Anyone see this in Linux?

Frank
 
defragster,

Thanks! Using TyCommander seems to help. I can now consistently get proper serial port display in TyCommander's serial window after a edit/compile/upload cycle.

Frank
 
Sounds like an issue with Visual Studio (Visual Micro?) on handling Serial port. It may act differently with some Arduino processors who have a separate processor or FTDI like chip on board, which keeps the USB active even when the processor is being programmed.

Note in the past with some Serial ports and the like I had some issues of losing some early on Serial outputs...
So I would put in a delay after the Serial.begin...

Something like:
Code:
while (!Serial && (millis() < 5000)) ; // wait  up to 5 seconds for Serial port. 
Serial.begin(115200);
delay(250);   // give some time for the other side to setup their serial.
Serial.print("System started");
...
You might try the delay and see if that helps.
 
Kurt,

Been there, done that - got the T-shirt. I have something like

Code:
   while (!Serial)
    {
        delay(10);
    }

In all my Teensy programs. While some may argue that 'while(!Serial)' is dangerous because it can block indefinitely, in this case it's fine because if the only way it can block indefinitely is if Serial never gets instantiated at all. In that case, I have bigger problems ;-).

Frank
 
Kurt,

Been there, done that - got the T-shirt. I have something like

Code:
   while (!Serial)
    {
        delay(10);
    }

In all my Teensy programs. While some may argue that 'while(!Serial)' is dangerous because it can block indefinitely, in this case it's fine because if the only way it can block indefinitely is if Serial never gets instantiated at all. In that case, I have bigger problems ;-).

Frank
Actually you don't have a delay AFTER the Serial is available... That is your code will return TRUE for Serial as soon as the USB makes connection with the PC, but some programs on PC may not be ready yet...

And note in my code above I wait only up to 5 seconds... Whenever I post something about waiting for Serial, I put something like that in, as too many have had problems where they say my program works great when it is plugged into USB but not when I run it from battery... So I try to reinforce using a timeout....
 
Hmm, hadn't thought of that - and it seems to help! That REALLY makes my day, as now I can get back to making mistakes with my code, rather than fighting with the serial monitor!

THANKS!!

Frank
 
@KurtE - had not understood why extra delay after Serial online - and with TyComm on Windows - even the IDE t_SerMon when used had not failed to get first messages.

This is odd to see though - waiting for Serial then doing Serial.begin()? Of course Serial.begin() does nothing - just out of order:
Code:
while (!Serial && (millis() < 5000)) ; // wait  up to 5 seconds for Serial port. 
[B]Serial.begin(115200);[/B]
delay(250);   // give some time for the other side to setup their serial.
Serial.print("System started");
...

This is typical for use here to make sure sketch connects - and a reminder what the source was:
Code:
  Serial.begin(38400);
  while (!Serial && (millis() <= 4000));
  Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);

If that doesn't work adding the delay() after the while would be worth doing to assure the first print - though not seen as normally needed.
 
Last edited:
Status
Not open for further replies.
Back
Top