Serial.print() stops

Status
Not open for further replies.

Davidelvig

Well-known member
I cannot make this fail on a small program...
With my large project, Serial.Print() (or printf() or println()) stop working after a few seconds.
It has done this on and off as the program has morphed.

After Serial.print() stops outputting, the program otherwise seems to keep running, with microphone and touch pin input and Serial1 output to a MIDI synth. The loop() keep looping.
Just the serial output stops.

Even Serial input appears intact. The following code still executes when the letter D <enter> is typed.
Code:
   if (Serial.available()) {
         char c = Serial.read();
         switch(c) {
             case 'd':  case 'D':
                 midiSynth.testDrums(100);
                 break;
             default:
                 break;
         }
    }

I'm not out of memory from code or initial data:
Sketch uses 154172 bytes (14%) of program storage space. Maximum is 1048576 bytes.
Global variables use 52596 bytes (20%) of dynamic memory, leaving 209548 bytes for local variables. Maximum is 262144 bytes.
Teensy 3.6. Arduino 1.8.3. Teensyduino 1.37


It's challenging to debug (without console output). I've been commenting/uncommenting chunks of code to see if I can reliably make it fall/succeed.

I expect I have a boundary condition not covered well, though I can't find it.

  • Does this ring a bell for anyone?
  • What can clobber Serial without clobbering the program.
  • Any suggestions for how to debug?


Thanks!
 
Thanks, Frank. That's a good thought.
I tried simplifying...
All of the printing now is in this statement, surrounded by a couple of delays
Code:
delay(10);
    Serial.printf("Testing...\n");
delay(10);
Same problem. Serial printing stops after a few seconds.

I tried resetting Serial with the following code:
Code:
   if (Serial.available()) {
         char c = Serial.read();
         switch(c) {
             case 'd':  case 'D':
                 Serial.end();
                 delay(1000);
                 Serial.begin(9600);
                 delay(1000);
                 Serial.println("Wahoo!"); // no luck
                 Serial.write("write..."); // no luck
                 midiSynth.testDrums(100); // <-- The drums start playing
                 break;
             default:
                 break;
         }
    }

Same result... the two lines with the "no luck" comment don't produce any output.
The drums do play, however.

Hmmmm

Any other ideas?
 
Can you show a complete simple program that exhibits the problem with setup and loop?

It may be a cable or computer hardware/serial receive problem. The USB is generally very robust, until something in the code trashes it as it runs, mishandled pointer or array can do it.

Use this to monitor how much is pending output before adding more:
Serial.availableForWrite() // Get the number of bytes (characters) available for writing in the serial buffer without blocking the write operation.

Put a blink in loop() that will confirm the code is running

Also add this for testing to force send : Serial.send_now()

Not sure what effect .end() has.
 
First, make sure you are using the latest Teensyduino release. There's no point wasting time on a problem that may already be fixed in a newer version. You said 1.37 earlier. Update to 1.40 (install into a separate copy of Arduino if you want to keep the old around).

You need to post enough info for us to reproduce the problem. A complete program which can be copied into Arduino and uploaded to a Teensy is the bare minimum. If you're using any libs other than the ones which come with Arduino & Teensyduino, the exact places to get the same libs you're using need to be clearly specified.

From your message, obviously you're doing *something* to send data. We need to know precisely what that is. Are you typing in the Arduino Serial Monitor and clicking the Send button? Think "reproducible". Remember, we can't see your screen. We aren't there in the room with you, so we can't see what you're actually doing. If you don't tell us *exactly* the steps you are using, how are we supposed to recreate the same circumstances to see the problem happen?

Which Teensy you're using, the settings in Tools USB Type and CPU Speed might matter. Which version of Windows, Linux or Mac you use could also play a factor, as can the type of USB port (2.0 vs 3.0) and whether you're directly connected or plugged into a hub is another minor detail that could be important. Remember, nobody can know these details unless you say them clearly.
 
Right. Thanks for these steps to try.
The code is sizable and multi-faceted. This problem has only occurred when the large app is running.
Getting the problem reproducible is challenging at times, even in my setup.
I'll try the steps above.
- I'll update to the latest Teensyduino
- I'll implement something like a "SafeWrite()" method that check for characters in the buffer before sending more (using Serial.availableForWrite() plus Serial.send_now())

I'll report back.

I know well the admonition at the top of the screen to post all code, and I do that when practical.
There seem to be times when that's impractical, and yet the forum could provide value, as it has here.

As always, thanks!
 
I have a macro now that I will use when Serial.print() freezes. The macro is at the top of the code below.

It's still hard to duplicate that problem at will with a small program, but I may have seen it with variations of this code.
Code:
void setup() {
    Serial.begin(9600);
    delay(500);
    Serial.println("Started");
}

// Note that 6 in the following macro is an arbitrary value to find a threshhold where buffer overlaod occurs.
#define SAFESERIAL if (Serial.availableForWrite() <= 6) {Serial.printf("\nSerial.availableForWrite() is %d bytes.\n\n", Serial.availableForWrite()); delay(50); } else 

unsigned long loopCount = 0;
unsigned long lastTime = 0;
void loop() {
    unsigned long thisTime = millis();
    int i = Serial.availableForWrite();
    SAFESERIAL     Serial.printf("%d\t%d\t%d\t%d\t%s\t", loopCount, thisTime, thisTime - lastTime, i, "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890");
    SAFESERIAL     Serial.print("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n");
    delay(4); // <-- change this value to up and down to see the effect of running out of Serial.print() buffer.
              // The buffer appears to be 64 bytes - or at least that the largest value that Serial.availableForWrite() returns
              // on a Teensy 3.6, a value of 5 at left here never triggers the "if" condition in the macro
              // a value of 4 and below does.
    lastTime = thisTime;
    loopCount++;
}

Removing the delay(x) at the end of the macro (put there to let Serial catch up) has interesting effects that I don't fully understand yet.
Regardless, I think I have a tool to proceed.

Thanks for your help!
 
Status
Not open for further replies.
Back
Top