Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 19 of 19

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

  1. #1
    Senior Member
    Join Date
    Jun 2017
    Posts
    114

    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

  2. #2
    Senior Member
    Join Date
    Jun 2017
    Posts
    114
    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'

  3. #3
    Senior Member
    Join Date
    Jun 2017
    Posts
    114
    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"

  4. #4
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,433
    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

  5. #5
    Senior Member
    Join Date
    Jun 2017
    Posts
    114
    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

  6. #6
    Senior Member
    Join Date
    Jun 2017
    Posts
    114
    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

  7. #7
    Senior Member
    Join Date
    Apr 2020
    Location
    DFW area in Texas
    Posts
    119
    Quote Originally Posted by paynterf View Post
    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

  8. #8
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    12,196
    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 );

  9. #9
    Senior Member
    Join Date
    Jun 2017
    Posts
    114
    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!

  10. #10
    Senior Member
    Join Date
    Jun 2017
    Posts
    114
    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"

    Name:  Annotation 2020-05-27 080522.jpg
Views: 67
Size:  15.5 KB

    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

  11. #11
    Senior Member
    Join Date
    Jun 2017
    Posts
    114
    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!

    Name:  Annotation 2020-05-27 183409.jpg
Views: 65
Size:  12.0 KB

    Frank

  12. #12
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    12,196
    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.

  13. #13
    Senior Member
    Join Date
    Jun 2017
    Posts
    114
    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

  14. #14
    Senior Member
    Join Date
    Jun 2017
    Posts
    114
    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

  15. #15
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,433
    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.

  16. #16
    Senior Member
    Join Date
    Jun 2017
    Posts
    114
    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

  17. #17
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,433
    Quote Originally Posted by paynterf View Post
    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....

  18. #18
    Senior Member
    Join Date
    Jun 2017
    Posts
    114
    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

  19. #19
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    12,196
    @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. 
    Serial.begin(115200);
    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 by defragster; 05-28-2020 at 05:49 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •