Baud rate error for Tennsy 4.x at 230,400

FLL-Freak

Member
At this page: https://www.pjrc.com/teensy/td_uart.html
there is a nice table showing the baud rate errors for various Teensy boards. Absent is a column for the Teensy 4.0/4.1.
Any one know how to calculate the baud rate error for a Teensy 4.x? Is it identical to another board?

I am having sporadic errors with reading data from a Lidar operating at 230,400 baud.
I have increased the buffer size for the Serial read function and that may have helped a bit.
I am wondering if the baud rate might be different between the Lidar and the Teensy.
The data stream is running close to 100% bandwidth so a mismatch might be an issue.
 
Now assuming I did not totally screw up:

Did a quick and dirty sketch to print out some data as computed by the HardwareSerial.begin( method...
Code:
void setup()
{
  char buffer[17];
  while (!Serial) ;
  Serial.begin(115200);
  PrintGeneratedBaudInfo(4608000);
  PrintGeneratedBaudInfo(2000000);
  PrintGeneratedBaudInfo(1000000);
  PrintGeneratedBaudInfo(921600);
  PrintGeneratedBaudInfo(500000);
  PrintGeneratedBaudInfo(460800);
  PrintGeneratedBaudInfo(250000);
  PrintGeneratedBaudInfo(230400);
  PrintGeneratedBaudInfo(115200);
  PrintGeneratedBaudInfo(57600);
  PrintGeneratedBaudInfo(38400);
  PrintGeneratedBaudInfo(31250);
  PrintGeneratedBaudInfo(19200);
  PrintGeneratedBaudInfo(9600);
  PrintGeneratedBaudInfo(4800);
  PrintGeneratedBaudInfo(2400);
  PrintGeneratedBaudInfo(1200);
  PrintGeneratedBaudInfo(300);
}

void loop() 
{
}

#define UART_CLOCK 24000000
void PrintGeneratedBaudInfo(uint32_t baud)
{
  //printf("HardwareSerial begin\n");
  float base = (float)UART_CLOCK / (float)baud;
  float besterr = 1e20;
  int bestdiv = 1;
  int bestosr = 4;
  for (int osr=4; osr <= 32; osr++) {
    float div = base / (float)osr;
    int divint = (int)(div + 0.5f);
    if (divint < 1) divint = 1;
    else if (divint > 8191) divint = 8191;
    float err = ((float)divint - div) / div;
    if (err < 0.0f) err = -err;
    if (err <= besterr) {
      besterr = err;
      bestdiv = divint;
      bestosr = osr;
    }
  }
  uint32_t gen_baud = UART_CLOCK / ((bestosr)*bestdiv); 
  float error = (((float)baud - (float)gen_baud)/(float)(baud)) * 100.0;
  
  Serial.printf(" baud: %u\tActual: %u\tError: %4.2f\tosr=%d, div=%d\n", baud, gen_baud, error, bestosr, bestdiv);
}

Code:
baud: 4608000	Actual: 4800000	Error: -4.17	osr=5, div=1
 baud: 2000000	Actual: 2000000	Error: 0.00	osr=12, div=1
 baud: 1000000	Actual: 1000000	Error: 0.00	osr=24, div=1
 baud: 921600	Actual: 923076	Error: -0.16	osr=26, div=1
 baud: 500000	Actual: 500000	Error: 0.00	osr=24, div=2
 baud: 460800	Actual: 461538	Error: -0.16	osr=26, div=2
 baud: 250000	Actual: 250000	Error: 0.00	osr=32, div=3
 baud: 230400	Actual: 230769	Error: -0.16	osr=26, div=4
 baud: 115200	Actual: 115384	Error: -0.16	osr=26, div=8
 baud: 57600	Actual: 57692	Error: -0.16	osr=26, div=16
 baud: 38400	Actual: 38400	Error: 0.00	osr=25, div=25
 baud: 31250	Actual: 31250	Error: 0.00	osr=32, div=24
 baud: 19200	Actual: 19200	Error: 0.00	osr=25, div=50
 baud: 9600	Actual: 9600	Error: 0.00	osr=25, div=100
 baud: 4800	Actual: 4800	Error: 0.00	osr=25, div=200
 baud: 2400	Actual: 2400	Error: 0.00	osr=25, div=400
 baud: 1200	Actual: 1200	Error: 0.00	osr=32, div=625
 baud: 300	Actual: 300	Error: 0.00	osr=32, div=2500
 
I meant to ask as well, which Lidar are you using?

I have played with a few different ones,

including one by Robotis used on their Turtlebot3
Plus I played around with one by getSurreal u:https://www.getsurreal.com/product/lidar-controller-v2-0/
Which the first version of it I had used a Teensy 2. This version uses a Teensy LC I have played around with it with other Teensy boards.

Note: with Serial communications if you are using like 100% of the bandwidth, you often run into issues where the boards can not figure out where one byte ends and the next one starts, which leads to issues....
 
I am using the LD19 (LD AIR) Lidar from ldrobot.com.
I do not know how good the clock source is. That will be the next thing I start looking at.

I am aware that that if you do not have a good break once in a while (100% BW), you have no good way to resync the sample clock.

What I am seeing is very strange. If I collect data from the unit with a USR-RS232 dongle on a Linux box, I get no errors.
If I collect raw data on the Teensy 4.x and write to and SD card, that data seems to be good. I get only the occasional 'lost' byte.
But if I run a small state machine to find the sync byte in the stream and then record the data on a valid packet, I see the state machine go in and out of lock.
I can only assume it is a lost or corrupted byte.
Debuging is difficult as the data rate is higher than any printfs can keep up with.
Time to bring out the logic analyzer and start putting in GPIO toggles.
 
For completeness and to close out this thread, I traced my problem down to two things.

The first was insufficient RX buffer size on the Serial port connected to the LIDAR. This was an easy fix with the function call that allows you to specify your own buffer.

The second was an "issue" with the sensor.
It worked on the Linux box because I would connected the serial port to the Lidar after it had been powered up.
When running from the Teensy, it was the power source so I was seeing the first start up of the sensor.
Well it takes a few seconds for the "spinning laser of death" to get up to speed and stabilize.
During that first second or so, the data is all wacky. Ignore it for a bit, and all is good.

I am ashamed to say it took several hours to figure that all out.
 
Glad you have it working.
FLL-Freak;296651 The second was an "issue" with the sensor. It worked on the Linux box because I would connected the serial port to the Lidar after it had been powered up. When running from the Teensy said:
Been there! (many times)
 
Back
Top