DTR Off blocks USB serial receive

Status
Not open for further replies.

Kabron

Member
When I used USB serial in Arduino micro, I noticed that after opening USB serial connection with DTR Off everything goes OK. Then if I made DTR On it is still OK, but when I return to DTR Off receiveing stopped and recovers only if DTR is ON.
It does not correspond with ordinary USB to serial behavior, e.g. FT232 chip, which transmits and receves regardless DTR state.

Second issue: RTS state in Serial.rts() routine changed only when DTR state changes, i.e. DTR clocks RTS. It is also illegal behavior.

It could be reproducing with USBtoSerial.pde from arduino\examples\teensy\.
 
I'm confused. Which board has a problem? Is it a Teensy, or an Arduino board, or FTDI chip?

Just to be clear, if you've found a problem and want to see it investigated and fixed, you need to provide clear instructions to reproduce the problem. If key details, like which operating system to use, what software to run on that OS, what steps to perform with that software, which hardware to connect, and if multiple boards, how to connect them to each other, and exactly which code to run on those boards are missing from your message, odds are very slim that anyone will spend the time to guess those missing details.

You need to give a clearly reproducible report for the problem to actually be investigated. I'm not trying to deny there may be a bug. There many indeed be a bug with DTR handling. I'm only saying that bug reports need to have all info necessary for someone to reproduce the problem.
 
Well,
here are the details of software and hardware setup:
1. Windows 10 x64 LTSC Build 17763.rs5_release. 180914-1434
2. Terminal: Moxa PComm Lite 2.6 (https://pcomm-lite.software.informer.com/download/#downloading) or any.
Choosed because of easy DTR/RTS manipulation.
3. Serial Sniffer: IO Ninja 3.7.4(https://tibbo.com/downloads/archive/ioninja/) or any.
For observation DTR/RTS statuses.
4. Arduino 1.8.9 + VisualMicro 1912.28.2
5. Test sketch based on USBtoSerial example:
Code:
unsigned long baud = 115200;
const int dtr_pin = A0;
const int rts_pin = A1;
const int led_pin = 13;  

void setup()
{
  pinMode(led_pin, OUTPUT);
  digitalWrite(led_pin, LOW);
  digitalWrite(dtr_pin, HIGH);
  pinMode(dtr_pin, OUTPUT);
  Serial.begin(baud);	// USB, communication to PC or Mac
  Serial1.begin(baud);	// communication to hardware serial
}

long led_on_time=0;
byte buffer[80];
unsigned char prev_dtr = 0;
unsigned char prev_rts = 0;

void loop()
{
  unsigned char dtr, rts;
  int rd, wr, n;

  // check if any data has arrived on the USB virtual serial port
  rd = Serial.available();
  if (rd > 0) {
    // check if the hardware serial port is ready to transmit
    wr = Serial1.availableForWrite();
    if (wr > 0) {
      // compute how much data to move, the smallest
      // of rd, wr and the buffer size
      if (rd > wr) rd = wr;
      if (rd > 80) rd = 80;
      // read data from the USB port
      n = Serial.readBytes((char *)buffer, rd);
      // write it to the hardware serial port
      Serial1.write(buffer, n);
      // turn on the LED to indicate activity
      digitalWrite(led_pin, HIGH);
      led_on_time = millis();
    }
  }

  // check if any data has arrived on the hardware serial port
  rd = Serial1.available();
  if (rd > 0) {
    // check if the USB virtual serial port is ready to transmit
    wr = Serial.availableForWrite();
    if (wr > 0) {
      // compute how much data to move, the smallest
      // of rd, wr and the buffer size
      if (rd > wr) rd = wr;
      if (rd > 80) rd = 80;
      // read data from the hardware serial port
      n = Serial1.readBytes((char *)buffer, rd);
      // write it to the USB port
      Serial.write(buffer, n);
      // turn on the LED to indicate activity
      digitalWrite(led_pin, HIGH);
      led_on_time = millis();
    }
  }

  // check if the USB virtual serial port has raised DTR
  dtr = Serial.dtr();
  if (dtr && !prev_dtr) {
    digitalWrite(dtr_pin, dtr);
  }
  prev_dtr = dtr;
  // check if the USB virtual serial port has raised RTS
  rts = Serial.rts();
  if (rts && !prev_rts) {
    digitalWrite(rts_pin, rts);
  }
  prev_rts = rts;

  // if the LED has been left on without more activity, turn it off
  if (millis() - led_on_time > 3) {
    digitalWrite(led_pin, LOW);
  }

  // check if the USB virtual serial wants a new baud rate
  if (Serial.baud() != baud) {
    baud = Serial.baud();
    Serial1.begin(baud);
  }
}

Experiment 1
<--> - bidirectional communication;
X--> Arduino to FT232 only
X - does not affect

Arduino Micro connected to FT232RL Serial to TTL(3.3V Jumper) @ 115200 BAUD
Code:
Rx      Tx
Tx      Rx
GND   GND

	DTR  RTS    DTR    RTS  Communication Status
1.	OFF   X      X      X     <-->	First connection
2. 	ON    X      X      X     <-->	Allways
3.	OFF   X      X      X     X-->	Always
1. After first connection with DTR OFF at Arduino side the transmition is bidirectional.
2. Setting DTR ON at the Arduino side changes nothing.
3. Returning(or futher setting) DTR state to OFF at the Arduino side stops the transmition from FT232 to Arduino.
I guess that the BUG located in the Serial.write/Serial.print region, because the LED13 blinks on receive from FT232,
it means that rd = Serial.available() works correctly.

Experiment 2
dtrp_pin(A0) and rts_pin(A1) observed with scope(or LEDs)
changing state of DTR signal from Terminal immediatelly reflects on dtr_pin
changing state of RTS signal from Terminal reflects on rts_pin only after changing DTR signal
Code:
DTR	dtr_pin        RTS	rts_pin
0	0		0	0
1	1		0	0
1	1		1	0
0	0		1	1
0	0		0	1
1	1		0	0
 

Attachments

  • Setup.jpg
    Setup.jpg
    143.2 KB · Views: 87
  • Devices.jpg
    Devices.jpg
    49.1 KB · Views: 80
  • TermNinja.jpg
    TermNinja.jpg
    141.4 KB · Views: 88
Last edited:
This forum is about PJRC products.
Arduino Micro is not a PJRC product.

Maybe ask here: https://forum.arduino.cc
1. This forum is: Technical Support & Questions

2. Arduino Micro is ATMEGA32U4 based and hence the same as Teensy 2.0.
The question concern software and may affect on Teensy operation as well.

3. I trust in Paul more than in forum.arduino.cc.
 
Ok, please verify If the Teensy has the same issue.
It uses it's own (different) USB Stack as far as I know.
 
I was able to reproduce this problem. The bug is in Moxa PComm Lite. Coolterm works perfectly.

I tested both Teensy 2.0 and Teensy 4.0 with this code. Both respond properly to clicks on either RTS or DTR, when using Coolterm on Windows 10.

This is the code I used for testing (only Teensy - no FTDI cable or other Arduino)

Code:
void setup() {
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(20, OUTPUT);
  digitalWrite(9, LOW);
  digitalWrite(10, LOW);
  digitalWrite(20, HIGH);
  Serial1.begin(115200);  // pins 7-8 on Teensy 2.0, pins 0-1 on Teensy 4.0
}

void loop() {
  if (Serial.available()) {
    Serial1.write(Serial.read());
  }
  if (Serial1.available()) {
    Serial.write(Serial1.read());
  }
  digitalWrite(9, Serial.dtr());
  digitalWrite(10, Serial.rts());
}

Using this simple hardware with 2 LEDs to show DTR and RTS.

DSC_0726_web.jpg
 
The first thing I did with CoolTerm - repeat Experiment 1
Here are the results. Absolutelly the same as with Moxa PComm Lite.
 

Attachments

  • CooltermDTR_OFF.jpg
    CooltermDTR_OFF.jpg
    86.7 KB · Views: 109
  • CooltermDTR_ON.jpg
    CooltermDTR_ON.jpg
    90.7 KB · Views: 105
As to Experiment 2, yes I confirm RTS ON/OFF works with CoolTerm independently from DTR.
It is PComm Lite BUG.
 
I'm trying to make transparent interface to Arduino IDE for programming ESP8266 chip via Arduino Micro. Exactly then I noticed that programmer SW did not got response from the ESP8266 chip. It forced me to make this investigation.
 
If you believe there is still some bug involving Teensy, I'm going to ask you to again post clear instructions to reproduce the problem, using Teensy without Arduino Micro or ESP8266.

Otherwise, I'm considering this issue fully resolved and any remaining problems due to ESP8266 or Arduino Micro.

If it the issue happens with a "round trip" through 2 COM ports, or only when the Teensy connected to USB relays data to another board, then get another Teensy to demonstrate the problem! I've already put more time into troubleshooting a problem not using PJRC products, which turned out to be a PC software bug completely unrelated to Teensy. While I'm not necessarily denying any chance of a bug in Teensy's code, I am pretty confident DTR does not block Teensy from communicating. To spend any more time on this, I need the clear test case to involve *ONLY* PJRC products. No ESP8266, no FTDI (which is likely the problem - especially if a counterfeit), no Arduino Micro!
 
Last edited:
I'm trying to make transparent interface to Arduino IDE for programming ESP8266 chip via Arduino Micro. Exactly then I noticed that programmer SW did not got response from the ESP8266 chip. It forced me to make this investigation.

Some years ago I made a board (name was "flexiboard" with teensy + ESP8266)
It was able to flash new firmware to the ESP8266
The code is here:
https://github.com/FrankBoesing/Fle...oard_FlashESP8266/FlexiBoard_FlashESP8266.ino
You can't compile it as it is because it was specifically for my board - but the code might help you to find your problem. The Sketch does a NODEMCU emulation, so set your programmer-tool to NodeMCU-mode.

The main programming loop is more or less like this:

Code:
void loop() {

  int dtr = Serial.dtr();
  int rts = Serial.rts();

  //Implementation of "nodemcu" reset method:
  {
    if (dtr == rts) {
      digitalWriteFast(WLAN_GPIO0, HIGH);
      digitalWriteFast(WLAN_RESET, HIGH);
    }
    else if (rts) {
      digitalWriteFast(WLAN_GPIO0, HIGH);
      digitalWriteFast(WLAN_RESET, LOW);
    } else {
      digitalWriteFast(WLAN_GPIO0, LOW);
      digitalWriteFast(WLAN_RESET, HIGH);
    }
  }


  //Data Transfer
  while (Serial.available())
    WLAN_SERIAL.write(Serial.read());

  while (WLAN_SERIAL.available())
    Serial.write( WLAN_SERIAL.read() );

}
It was used on a Teensy. And worked.
 
Sorry for inconvenience, Paul, I do understand your irritation.
But the problem exists.

Nothing is easier to reproduce the problem with your current setup.
Just do LoopBack test.
Connect RX and TX on Teensy board and look on operation dependance from DTR.
 
Teensy 4.0 works without this isuue. I guess, topic may be closed.
I opened issue on Arduino github.
Thanks again, Paul.
 
Saw your github report. Looks like it's an Arduino-only problem & Teensy works properly. ;)

https://github.com/arduino/Arduino/issues/9786

Thanks for following up here. And if you do find any bugs with Teensy, of course I always do want to hear and try to investigate. Much of the reason Teensy's USB stack works so well comes from many years of people reporting issues in the lesser used cases, and a regular practice of finding and fixing those bugs.

Just please make sure to test that the bug really is with Teensy.
 
Last edited:
Thanks a lot, Paul
One more question: if i flash this test compiled for Teensy 2.0 in Arduino Micro, USB connection does not work, while Serial1 does. What may be a reason?
 
I don't know. I've never used Arduino Micro. I don't even own one, but I do have an Arduino Leonardo. The few times I've used Leonardo, I've run Arduino's code on it. I've never tried running Teensy code on Arduino's hardware.
 
In fact they did it consciously!
File: CDC.cpp
232
size_t Serial_::write(const uint8_t *buffer, size_t size)
{
/* only try to send bytes if the high-level CDC connection itself
is open (not just the pipe) - the OS should set lineState when the port
is opened and clear lineState when the port is closed.
bytes sent before the user opens the connection or after
the connection is closed are lost - just like with a UART. */

// TODO - ZE - check behavior on different OSes and test what happens if an
// open connection isn't broken cleanly (cable is yanked out, host dies
// or locks up, or host virtual serial port hangs)

//// if (_usbLineInfo.lineState > 0)
{
int r = USB_Send(CDC_TX,buffer,size);
if (r > 0) {
return r;
} else {
setWriteError();
return 0;
}
}
setWriteError();
return 0;
}
Commenting if( ... solved the problem.
 
Status
Not open for further replies.
Back
Top