Serial Monitor goes offline

NikoTeen

Well-known member
I have the following test setup:

1) a board with a serial output
2) a Teensy 3.5, RX1 connected to the serial output
Every 8 seconds the board is sending a string and after each fourth string it sends immediately a further string.

The tests are performed on Arduino IDE with Teensyduino and the following sketch on the Teensy3.5:
Code:
#define RFrec Serial1

void setup() {    // ----------------------------------------------

  // Initialize serial port for communication with receiver.
  RFrec.begin(19200);   // from RF receiver

  // Initialize serial port for communication with IDE.
  Serial.begin(38400);  // for Serial Monitor
  delay(1000);

  while (1) {
    char c;
    if (RFrec.available()) {
      c=RFrec.read();
      if ( (c==13) || (c==10) || ((c>31) && (c<91)) ) {
        Serial.print(c);
      }
      else {
        Serial.print((uint8_t)c);
        Serial.print(" ");
      }
    }
  }
  
}

void loop() {

}
On the Serial Monitor I expected to see the received strings line by line.

What I see is one, sometimes two or three, strings. Then the screen is cleared, then again one to three strings, screen cleared, and so on.

When the screen is cleared the head line of the Serial Monitor shows: (offline) Teensy

Obviously the link from Teensy3.5 to my PC breaks down for a short moment and then comes up again. I don't understand why this happens.
In the Tools menue (USB Type: "serial") is selected.

What can be the reason for the link breaking down?
 
You might be trying to print some non-printable characters that are doing unexpected things. Are you sure ASCII 31-91 are all printable? Make sure, modify if necessary, and try replacing:
Code:
  Serial.print((uint8_t)c);
with
Code:
  uint32_t c_value = c;
  Serial.print( c_value );
 
What is sending the Data to the Rx Serial1 Pin? Assuming That Rx pin and GND are connected to the device?

Are the characters received and printed as expected up until the loss of Communication?

On a T_3.5 here with pin #0 wired to #1 so Serial1 Tx comes back on Rx and I get this working as expected:
Code:
C:\T_Drive\tCode\FORUM\Ser1USB_TEST\Ser1USB_TEST.ino Aug 13 2022 15:46:42
HELLO AGAIN ...
2401
HELLO AGAIN ...
3402
HELLO AGAIN ...
4403

   ... // continues

HELLO AGAIN ...
106505
HELLO AGAIN ...
107506

The edited code is:
Code:
#define RFrec Serial1

void setup() {    // ----------------------------------------------

  // Initialize serial port for communication with receiver.
  RFrec.begin(19200);   // from RF receiver

  // Initialize serial port for communication with IDE.
  Serial.begin(38400);  // for Serial Monitor
  delay(1000);
  Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);

  elapsedMillis doSend;
  while (1) {
    char c;
    if (RFrec.available()) {
      c=RFrec.read();
      if ( (c==13) || (c==10) || ((c>31) && (c<91)) ) {
        Serial.print(c);
      }
      else {
        Serial.print((uint8_t)c);
        Serial.print(" ");
      }
    }
    if ( doSend > 1000 ) { // print once a second
      doSend = 0;
      Serial1.println( "HELLO AGAIN ...");
      Serial1.println( millis() );
    }
  }
  
}

void loop() {

}
 
The problem is a different one.
The code I posted was an extract from a large code. I missed to copy some lines with watchdog statements. Sorry for that.

The reset caused by the watchdog clears the Serial Monitor screen.

This rises two new questions:

1) Is it possible to avoid clearing the screen with every reset?
Avoiding clearing the screen during reset is important for debugging. If a program generates outputs to observe the processing steps then all these outputs will disappear when the watchdog resets the controller. But to find the true reason why the watchdog fires, these outputs are essential and the only way to locate the problem in the code.

2) How to control the watchdog?
For this question I will open a new posting.
 
The screen clearing is an artifact of the SerMon tool in use.

TyCommander does not do that (except on upload if chosen) - though it does drop the Teensy after some 10 seconds of it going offline. But it caches all output in a txt file in the TEMP folder, which is findable on the on TAB when the device is active.

If TyCommander works there it might give desired behavior: pjrc.com/threads/27825-Teensy-Qt

As far as WatchDog there are existing threads and one new recent one that may have answers: pjrc.com/threads/70877-Teensy-4-1-WDT_T4-Explanation-of-settings
 
1) Is it possible to avoid clearing the screen with every reset?

Unfortunately, no, at least not with the Arduino Serial Monitor. The problem is a hardware reset turns off the USB hardware. To software on your PC, it looks the same as if the USB cable is physically unplugged.

One possible workaround is to transmit to Serial1 or any of the other hardware serial ports. Then use a use a USB-serial adapter or another Teensy running File > Examples > Teensy > USB_Serial > USBtoSerial. When the Teensy with watchdog resets, this other hardware will remain running and your PC will see it continuously connected. Since this is real serial between the 2 boards, you do need to get the baud rate configured correctly. You might use a non-Arduino program like CoolTerm to view the incoming data. When you get it set up properly, that other window will show you everything it receives, no matter how many times the watchdog reboots the hardware.

You might also take a little time to consider whether using a watchdog is really a good idea. They always seem like a good idea at first. But unless your program is a very simple fixed function, effectively using a watchdog is notoriously difficult. Often watchdogs just make everything worse. The main problem is you need to have some way to check whether everything about your program is still working properly and only reset the watchdog timer when you're sure all is correct. If you just reset it as a normal course of your program running, it can become worthless. For example, we recently has a thread where a buffer overflow was causing a program to stop receiving input data, but the main loop kept resetting the watchdog. Technically the program hadn't "crashed" but for all practical purpose was unresponsive to the outside world. But assuring that every part of your program is still fully functional can be pretty much impossible with larger or more complex program. It's usually only feasible with simple fixed function designs. For programs which respond to commands or handle different scenarios in various ways, somehow assuring everything is working on a fixed timing schedule needed by a watchdog is extremely difficult to design. Often a watchdog will end up needlessly resetting a hardware that was working properly, which has an overall effect of making the final product less reliable, not more. The cold hard reality of watchdog timers, which never gets told in the pretty marketing material (eg, datasheets) is they're a simple piece of hardware that's actually get hard to use in a truly effective way.
 
As far as WatchDog there are existing threads and one new recent one that may have answers: pjrc.com/threads/70877-Teensy-4-1-WDT_T4-Explanation-of-settings

WDT_T4 is for Teensy4. I'm using Teensy3.5.
I found a thread for Teensy3x which only suggests functions to set the timeout and to reset the WD-timer.
I also need to stop the watchdog and to continue the timer. Therefore I wrote the following functions:
Code:
/*
  watchdog library for Teensy 3.x
  according to https://forum.pjrc.com/threads/25370-Teensy-3-0-Watchdog-Timer
 */

 #include "wdtTeensy.h"
 
void wdt_config(uint16_t timeout) {
// timeout ist die Zeit, bis der Watchdog zuschlaegt, in ms
  noInterrupts();
  WDOG_UNLOCK = WDOG_UNLOCK_SEQ1;
  WDOG_UNLOCK = WDOG_UNLOCK_SEQ2;
  WDOG_TOVALL = (timeout); // this and next line sets the time-out value. This is the value that the watchdog timer compare itself to.
  WDOG_TOVALH = 0;
  WDOG_STCTRLH = (WDOG_STCTRLH_ALLOWUPDATE | WDOG_STCTRLH_WDOGEN |
  WDOG_STCTRLH_WAITEN | WDOG_STCTRLH_STOPEN); // Enable WDG
  WDOG_PRESC = 0; // This sets prescale clock so that the watchdog timer ticks at 1kHZ instead of the default 1kHZ/4 = 200 HZ
  interrupts();
}

void wdt_halt(void) {
//  Anhalten:
  noInterrupts();
  WDOG_UNLOCK = WDOG_UNLOCK_SEQ1;
  WDOG_UNLOCK = WDOG_UNLOCK_SEQ2;
  WDOG_STCTRLH &= ~(WDOG_STCTRLH_WDOGEN);
  interrupts();
}

void wdt_continue(void) {
//  Weiterlaufen lassen:
  noInterrupts();
  WDOG_UNLOCK = WDOG_UNLOCK_SEQ1;
  WDOG_UNLOCK = WDOG_UNLOCK_SEQ2;
  WDOG_STCTRLH |= WDOG_STCTRLH_WDOGEN;
  interrupts();
}

void wdt_reset(void) {
//  Refresh/Reset:
  noInterrupts();
  WDOG_REFRESH = 0xA602;
  WDOG_REFRESH = 0xB480;
  interrupts();
}
The manual for Teensy3.5, chapter 24.3.5, says: "When the watchdog is disabled through the WDOG_EN bit in the watchdog status and
control register, the watchdog timer is reset to zero and is disabled from counting ...".
But my function wdt_halt() does not stop the WD-timer.
What is wrong with it?
 
Back
Top