Odd native USB port behaviour on the Leonardo, Micro, and ProMicro

I've been playing around with the native USB port on the Atmega32U4 chip (on a Promicro board). It has the Arduino bootloader in it. My code is as follows:

    #include <Arduino.h>
    
    // Definitions
    #define BAUD_RATE     115200           // Serial port baud rate
    
    // Variables
    uint16_t   ticker     = 0;
    bool         tick         = 0;
    
    // Interrupt Service Routine
    ISR(TIMER3_OVF_vect)
    {
      TCNT3 = 40535; // Timer Preload for 100ms interval
      tick = 1;
    }

    // Setup
    void setup() {
      //  Setup timer3 for 100ms overflow interrupt
      TCCR3A = 0;           // Init Timer1A
      TCCR3B = 0;           // Init Timer1B
      TCCR3B |= B00000011;  // Set Prescale to 64
      TCNT3 = 40535;        // Timer Preload
      TIMSK3 |= B00000001;  // Enable Timer Overflow Interrupt
    
      // Set up the RX_LED on Port B, pin 0
      DDRB  |= 0b00000001;
      PORTB |= 0b00000001;  // Initialise the RX_LED to ON
    }
    
    // Loop
    void loop() {
      if (tick){
        Serial.begin(BAUD_RATE);
        Serial.print('\r');
        Serial.print("Count = ");
        Serial.print(ticker, DEC);
        Serial.end();
        toggleLED();
        ticker++;
        tick = 0;
        }
    }
    
    void toggleLED(void){
      PORTB ^= (1 << PORTB0);  // Toggle the RX_LED
    }

Out of reset, the 32U4 sends the output to the USB port and toggles the led on Port B, pin 0 on a 100ms interval, as expected. When I connect a terminal to the USB port from the PC end, it continues exactly as before and the data is there. This is what I expected. What I wanted was the micro to spit its data out on the USB port, whether or not the port is being read at the other end.

The weird bit starts when the USB connection is terminated at the PC end. Once disconnected, the time interval changes to about a second (not sure of the exact timing) based on the blink rate of the led on B0.

Then, if I reconnect to the port from the PC, it goes back to the 100ms interval. Thereafter, when the USB port is connected, the interval is 100ms and when disconnected, it's ~1sec. The system is happy to connect and reconnect, no problem, but the timing changes. Until the 32U4 is reset, then it starts at the 100ms interval without a connection. The problem starts on the first disconnection of the USB port from the PC end.

Additionally, I have tried this with the 'Serial.begin()' and the obligatory 'while(!Serial){}' in the setup function. Same behaviour on USB disconnect. I've also tried using Timer1. Same thing.

I understand that there is no easy or good way to detect whether something is connected to the USB port at the far end. This is the first chip I've used that has a native USB port, which is the main reason I picked it. Previously I've always used serial to USB converter chips on a USART port and this has not been a problem. This behaviour in the 32U4 might make it unusable for some projects unless I can figure out what's happening.

My questions are as follows:

Why do the timers seem to work differently once the native USB connection gets closed at the far end?
Is this something to do with 'Serial()' and/or the Arduino built-in code, or is it a hardware issue on the native USB port inside the 32U4?

I'd be grateful for any recommendations to try and figure out what's actually going on.

Your 32U4 USB buffer can no longer get rid of the data when you disconnect the board which is the cause of the slow down.

The solution is to check if there is space in the serial buffer before printing. You can use Serial.availableForWrite() for this. See Serial.print on Leonardo very slow after disconnection from serial - #7 by sterretje

@sterretje,

Many thanks, that fixed it first time. I simply wrapped all the print statements in the code into an if(Serial.availableForWrite()){} and it worked!

The idea of overfilling the USB buffer never occurred to me. The datasheet details an 832byte DPRAM, but it doesn't say what the buffer size is. Nor does it mention full buffer behaviour.

Your assistance is greatly appreciated.

It's part of the Arduino core, not of the hardware; see the other topic. However I have only seen the mention of the slowdown in this forum.

I would make it slightly different; the above way will allow you to print too much; see the other topic to check if there is sufficient space.

You can mark the topic as "solved" by clicking the little checkbox under the most useful reply.

@sterretje,
I have had a look at the other topic, and the work you did to figure it out is pretty extensive, and much appreciated. I fully intend to make use of a tidier, more sophisticated method of handling printing to the port. However, this particular issue arose as I was writing sample bits to shake down, sorry - test, my hardware.

Make no mistake, I have bookmarked your response on the other topic, which amounts to a very useful tutorial on a topic that anyone using the native USB port on the atmel chips should read.