Leonard serial baud rate

As far as I can tell, baud rate makes no difference when communicating over USB to an Arduino Leonardo. You can open the connection with different baud rates at each end, and still get perfect results. This makes sense since it's a USB transaction, not a 'traditional' serial one.

Is there any way within an Arduino program to tell what baud rate the PC requested and 'thinks' it is communicating at? If I knew this I could relay serial bytes at the same rate via the Serial1 output, which has some useful applications.

I have seen projects that calculate the width of the startbit with a timer. A single character is enough to guess the baudrate. I think that the RX must be connected to a TIMER input to make this work.

However, the Arduino Leonardo does not use a hardware UART. And the RX and TX signals to the usb are not available. To make it even more complex, the Arduino IDE lowers the baudrate to 1200 baud to cause a (soft) reset on the Arduino board to start the bootloader.

Using a device to relay serial data is only used to be able to change data. When you only want to sniff the serial data, just connect two hardware RX inputs to the serial lines. That would require an Arduino Mega 2560, which has 4 hardware serial ports.

Thanks but I'm interested in the Leonardo specifically. Given that it resets on receiving a 1200 baud connection, relaying this rate is out of the question, but the fact that it knows to reset must mean the PC passes the baud rate over USB when it initiates the connection.

If the Leonardo doesn't discard this information, I hoped it could be accessible from an Arduino program.

The serial-over-usb passes the baudrate, the DTR, CTS signals and so on, almost like a real serial port.

However, for the Leonardo, the serial port is part hardware (usb device) and part software (serial data) and is very complex. That is why the Leonardo has less memory for the sketch, because it is doing that very complex thing with the usb serial port.

I don't know how you can use that in a sketch. You might have to rewrite the library for the Leonardo. Compared to an Arduino Uno, it is at least 1000 times harder (maybe a million times).
The Arduino Mega is ideal for what you want, because of its 4 hardware serial ports.

I think perhaps you misunderstood what I'm trying to achieve. I'm asking specifically about the Leonardo. If the baud rate is stored somewhere in memory, it should be possible to retrieve it. If it's discarded, then what I'm asking is impossible. But at the moment I don't know either way.

I know, I know, you specifically ask about the Leonardo, but that is the problem :slight_smile:
You could try to find out about the way the usb-serial is used, perhaps you also have to learn in detail how the bootloader works. And after that I still have doubts if it is possible without rewriting the code of the default library for the Leonardo. And even if you did rewrite it, it might not work very well, since the RX can not be connected to a timer input (that is the trick that is used for other Arduino boards).

In my opinion it is (almost) impossible.

Because the Leonarde emulates a usb serial port, perhaps you think that the data can be captured before the serial port emulation, so before any baudrate is used. I think that is not possible, the usb part acts as a usb device to a computer. That part is in hardware. To capture the data somewhere in between is perhaps possible with a software implemenation of the usb, like V-USB. My knowledge of the Leonardo libraries is limited, I don't have the time at the moment to study it ....

Very nice. Thank you pepe, that was what paulrd is looking for. I'm going to do some tests now...
Sorry paulrd for the confusion and misinformation.

pepe +1

I have been testing it, and the address of ‘LineInfo’ changes for different versions.
So I have added a search for the specific 8 bytes of ‘LineInfo’.
That is not very safe, but at least it works without changing the default libraries.

// Find baudrate of usb-serial of Arduino Leonardo
//
// Arduino IDE 1.0.6 : address : 0x10A
// Arduino IDE 1.5.7 (with extra -flto option) : address 0x102
//
// Changing baudrate in Arduino IDE serial monitor : works
// Using other serial terminal programs, 50 to 921600 baud : works

// The 'LineInfo' is a static volatile structure, used in CDC.cpp.
// It is used for the USB/CDC API in USBAPI.h and USBCore.cpp
// The functions in those files call the CDC and HID functions.

typedef struct {
  unsigned long dwDTERate;      // baud, the number is the baudrate
  unsigned char bCharFormat;    // stopbits: 0=1, 1=1.5, 2=2
  unsigned char bParityType;    // parity: 0=none, 1=odd, 2=even, 3=mark, 4=space
  unsigned char bDataBits;      // databits: the number is the databits 5,6,7,8,16
  unsigned char lineState;
} LineInfo;

int addressLI;
const int max_addressLI = 0x200;

void setup() {
  // Search for the (volatile) LineInfo structure
  // Do this before the Serial port is used, because the default values would be changed.
  LineInfo LI = { 57600, 0x00, 0x00, 0x00, 0x00 };

  for ( addressLI = 0; addressLI < max_addressLI; addressLI++)
  {
    if (memcmp( &LI, (void *) addressLI, sizeof(LineInfo)) == 0)
      break;
  }

  Serial.begin(9600);
  while (!Serial);

  if ( addressLI == max_addressLI) {
    Serial.println("Not found");
  }
  else {
    Serial.print(F("LineInfo at 0x"));
    Serial.println(addressLI, HEX);
  }
}

void loop() {
  // Set pointer to _usbLineInfo address (found during runtine in setup)
  LineInfo *p = (LineInfo *) addressLI; 

  // Original : Serial.println(p->dwDTERate);
  // We might as well print everything.
  Serial.print(F("baud="));
  Serial.print(p->dwDTERate);
  Serial.print(F(", stopbits="));
  char *stoLI[] = { "1", "1.5", "2" };
  Serial.print(stoLI[p->bCharFormat]);
  Serial.print(F(", parity="));
  char *parLI[] = { "none", "odd", "even", "mark", "space" };
  Serial.print(parLI[p->bParityType]);
  Serial.print(F(", databits="));
  Serial.print(p->bDataBits);
  Serial.print(F(", linestate=0x"));
  Serial.print(p->lineState, HEX);
  Serial.println();

  delay(1000);
}

Thanks pepe, that's what I was hoping for. And thanks for the implementation Peter_n, glad we all got there in the end! :slight_smile:

Yes the sample code works fine.

In my case a Lenovo X201 USB port is connected and Oscilloscope indicates 1.9MHz bitrate on the USB wires. That is USB 1.1 speed I think?

Setting the baudrate low 300 or high 230400 on computer side is nicely updated in the Arduino data area but has no effect on the actual USB data transfer rate. Computer and Arduino exchange data as fast as they can.

Baudrate in this case is the concept of a classic serial serial ports with I/O pins. I am happy to notice OS like Windows do not "emulate" the baudrate slowness over the USB wires. It just exchanges the port information to/from the other end as it does with all the other handshake signals like RTS, CTS.

If the Leonardo or Micro Arduino is suposed to convey the USB data using the output pins and Serial1 device it could be a cool idea for "dongle" projects to apply the obtained baudrate from the data area when initiating Serial1 port - like an off shelf USB to Serial device.

I come across this thread and here is my observation on the Leonardo serial communication:

I just had this device handy so I dropped it into a situation where all it does is it receiving some data periodically from a 433Mhz RF sensor and forwarding the data points to a PC for logging.

This is working fine when I have the Leonardo directly attached to my laptop running Arduino IDE 1.6 but once I connect it to my Raspberry PI1 I get nothing, nada is coming through that port no matter how I try.

I have a well working C program to listen on the ttyACM port but I have also tried it with usual

screen /dev/ttyACMx

on the raspi, then I tried different baud rates, still nothing.

Bus 001 Device 004: ID 2341:8036 Arduino SA Leonardo (CDC ACM, HID)

However I also have an RF_433 Mhz transmitter attached on another pin for other purpose and I can actually send commands to the ardu with simply:

echo "COMMAND" > /dev/ttyACMx

So I don't know what's the problem with the reception on serial. Maybe somebody can share some light on this one. I don't have more time messing around with this hardware, I will just drop a mega in place.

So I don't know what's the problem with the reception on serial.

I'm going to go out on a limb and say that it is your code - the code that you didn't post.