Issue with Teensy USB features - handing USB communication when reading data

Status
Not open for further replies.

Matthew

Member
I found a partial (or maybe permanent) solution, but the issue is as follows:

I have used Teensy 3.6, Ubuntu 18.04 with TyCommander from TyTools, Visual Studio Code and PlatformIO extension with Teensyduino 1.44. I used TyCommander as serial monitor, bootloader/reset tool. And there were no problems or maybe I did not experience them.

I run that program during tests with delay(10) instead of delayMicroseconds(200):
Code:
#include <Arduino.h>

void setup()
{
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop()
{
  digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN));
  if (Serial.availableForWrite())
  {
    Serial.println(millis());
  }
  delayMicroseconds(200);
}

However, since (I'm not 100% sure) I upgraded Ubuntu to 18.10 version I have problems with uploading software, hanging USB connection when reading data in serial monitor or it plot only countable number of lines. TyCommander was reporting with something like system info "resource busy" when trying to reset or use TyCommander monitor. The problem was partially solved by changing Teensy USB features from Serial to Serial MIDI. But there were some minor problems. However, on Windows the same program (I just switched to Windows and run Serial Monitor) there weren't any problems.

Then I reinstall Ubuntu back to 18.04, and everything works as expecteded (PlatformIO, Teensyduino 1.45), but I have to use USB Serial MIDI feature (or probably *any other than Serial feature), on PlatformIO (in platformio.ino file) I'm using
Code:
build_flags = -D USB_MIDI_SERIAL
And then serial monitor on Arduino IDE/TyCommander/my Qt app works without problems. When I change USB feature to USB Serial (on PlatformIO it is default ) the connection is hanging or I get only countable number of lines in serial monitor and then the connection is hanging as well the TyCommander / Arduino Serial Monitor is hanging and Teensy is not responding (I have to unplug/plug it).

I can see now, that sometimes increasing the delay time and using USB Serial feature make it possible to read data from Teensy but it is not realiable.

I'm guesing that this is the OS related problem. Am I right or I'm missing something?
 
Last edited:
What happens with :: if (Serial.availableForWrite() > 32)

Not stated what Teensy - but T_3.x or T_LC any can overfill USB system - when it is that busy the bootloader may not get through.
 
Oh sorry i forgot to add information about board - I'am using Teensy 3.6 (I updated first message).

What happens with :: if (Serial.availableForWrite() > 32)

Not stated what Teensy - but T_3.x or T_LC any can overfill USB system - when it is that busy the bootloader may not get through.

Ok, so how can I manage to not overfill system USB? I don't see any solution for now.
 
Did the provided code edit change anything? Assuming it works like … assumed ... without seeing/trying it myself. A write of millis and newline could be 11 bytes - forcing a delay to limit send rate is the only way if that is what the issue is.
 
I can't comment on TyCommander or PlatformIO, but I can explain a little bit about what Teensy is doing and how the Arduino IDE works.

When you choose a USB Type setting with "Serial", Teensy implements USB serial, so you get a COM port in Windows or a /dev/ttyACM* port in Linux. When using "MIDI" without Serial, a HID interface is used for Serial.print(), so you can still print to the Arduino Serial Monitor. I'm pretty sure PlatformIO doesn't know how to use this HID interface.

On top of that, in Arduino there are 2 ways you can select Teensy in the Tools > Ports menu. There is a "Serial ports" section and a "Teensy" section. If you choose under "Serial ports", Arduino's normal Java code uses the JSSC library to talk to the serial port. If you choose "Teensy", there is no Java communication with the hardware at all. Instead a "teensy_ports" program is run. It talks to the serial port or HID interface and communication between it and Java is done by stdin/stdout (technically anonymous pipes on Windows).

On Linux, JSSC tries to gain an advisory lock on the serial port. The teensy_ports program doesn't do any locking. So if you have other software in play, it's possible to get 2 programs opening the same serial device. Usually transmitting works from both, but receive is highly unreliable.

Don't know if any of this helps?
 
Firstly the question before the long post: Did the delay() function from my first post have an impact on USB hardware = it's simply waits and do nothing more or it let's the communication run?

Did the provided code edit change anything? Assuming it works like … assumed ... without seeing/trying it myself. A write of millis and newline could be 11 bytes - forcing a delay to limit send rate is the only way if that is what the issue is.

OK, so If I understand Your reply correctly:

  1. My delay() function (if delay value was great enough) provide the way to non-blocking send rate for OS.
  2. The next issue is the number of bytes written to USB trasmit buffer:
What happens with :: if (Serial.availableForWrite() > 32)
If I will put a higher number of bytes than Serial.availableForWrite() limit = I overfilling the system USB. Am I right?


So considering that I applied this code:
Code:
##include <Arduino.h>

const uint8_t 193887 = 4;
uint8_t buffer[numberOfElements];
uint32_t previousMicros = 0;
uint32_t actualMicros = 0;
uint16_t delayValue = 0; // [us]

void setup()
{
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);

  for (uint8_t i = 0; i < numberOfElements; i++)
  {
    buffer[i] = i;
  }
}

void loop()
{
  actualMicros = micros();
  if((actualMicros - previousMicros) > delayValue)
  {
    digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN));

    if (Serial.availableForWrite() >= sizeof(buffer))
    {
      Serial.write(buffer, sizeof(buffer));
    }  

    previousMicros = actualMicros;
  } 
}

Note, that I am not using any delay (intervalValue = 0) and I using USB Serial feature now (no MIDI anymore). And now, the TyCommander is hanging but not due to overfilling the USB but due to updating the UI. What is more, my Qt app (using qDebug() - provides an output stream - to print data instead of putting data into UI like on TyCommander) is working perfectly. Data is ariving without any blockade of stream. Only sometimes I have to reset Teensy after switching from TyCommander and my app probably due to some operations of opening/closing port.

However... after some tests and diging, when I want to increase the buffer size (by simply changing numberOfElements variable) over the value of 4, then I have to incresing the intervalValue (coresponding to buffer size) because the stream is blocked after a while or imediately.
Then I switched to USB Serial MIDI mode and it is much much better than on USB Serial mode. Now I'm sending 20 bytes with 10ms interval and now is over 6 minutes of communication without any problem (for example with 20 bytes and 2ms interval it hanged up after 3,2 minutes).
And then when I switch to USB Serial Mode, I have no communication (it's starting reading data and hanginig after a while) and I have problems with uploading the new program (it's takes much longer time than normal). Next I'm switching back to USB Serial MIDI mode and it's ok as before.

I specially checked and only the communication is hanging but Teensy is working as before (I have an oscilioscope probe on LED pin).

I can't comment on TyCommander or PlatformIO, but I can explain a little bit about what Teensy is doing and how the Arduino IDE works.

When you choose a USB Type setting with "Serial", Teensy implements USB serial, so you get a COM port in Windows or a /dev/ttyACM* port in Linux. When using "MIDI" without Serial, a HID interface is used for Serial.print(), so you can still print to the Arduino Serial Monitor. I'm pretty sure PlatformIO doesn't know how to use this HID interface.

On top of that, in Arduino there are 2 ways you can select Teensy in the Tools > Ports menu. There is a "Serial ports" section and a "Teensy" section. If you choose under "Serial ports", Arduino's normal Java code uses the JSSC library to talk to the serial port. If you choose "Teensy", there is no Java communication with the hardware at all. Instead a "teensy_ports" program is run. It talks to the serial port or HID interface and communication between it and Java is done by stdin/stdout (technically anonymous pipes on Windows).

On Linux, JSSC tries to gain an advisory lock on the serial port. The teensy_ports program doesn't do any locking. So if you have other software in play, it's possible to get 2 programs opening the same serial device. Usually transmitting works from both, but receive is highly unreliable.
Thank you Paul, it's a good to know information!


So for now, I can freely sending 4 bytes in one loop count without any code delays, or send higher amount of bytes but with some intervals.
 
OK,

A lot of time has passed, but the problem came back to me at the most unexpected moment. However, I found the solution. On Windows everything was OK, but on Ubuntu the problem occurred on every device (tested on Ubuntu v18.04, 18.04.2 LTS). I tested it on an ordinary laptop and Intel NUC. The result was the same. I'm pretty sure that ModemManager cause the problem, after uninstalling the `modemanager` and reboot, the problem disappeared.

Hope it helps somebody:

Code:
sudo apt-get --purge remove modemmanager
reboot

Also now I can freely choose different USB modes (Serial, MIDI etc.)
 
Status
Not open for further replies.
Back
Top