Go Down

Topic: Auto Detect Baud Rate (Read 3531 times) previous topic - next topic

tnovak

I have been searching for a solution to auto detect a baud rate of a serial connection with a gps reciever. Lefty has an old post showing interest in this concept, but I had no luck finding a finished solution. Any thoughts??

James C4S

Hope that the GPS unit occasionally sends an ASCII "U".  (so you can detect the 1010 pattern...)
Capacitor Expert By Day, Enginerd by night.  ||  Personal Blog: www.baldengineer.com  || Electronics Tutorials for Beginners:  www.addohms.com

jwatte

You don't need to detect the 1010 pattern. All you need is to measure the shortest interval between two flanks (rising -> falling, or falling -> rising) for some amount of traffic. Assuming the communications wiring is good, the shortest duration between two flanks will be the duration of a single bit. The baud rate will then be 1 divided by that duration (in seconds.) You probably want to round/clamp/adjust that to be the closest "standard" baud rate once measured.

Coding Badly


For a device that transmits continuously (like a GPS) I've found the easiest way to detect the baud rate is to simply try each possibility until something recognizable arrives.  If the baud rates are tested in a logical order (e.g. 4800 first) then, in most cases, the detection takes just a few frames.  On success, saving the baud rate to EEPROM makes detection even faster the next time around.

retrolefty

#4
Mar 29, 2012, 04:14 pm Last Edit: Mar 29, 2012, 04:22 pm by retrolefty Reason: 1

I have been searching for a solution to auto detect a baud rate of a serial connection with a gps reciever. Lefty has an old post showing interest in this concept, but I had no luck finding a finished solution. Any thoughts??


My memory from my attempt was that I was only able to 100% reliably detect the proper baudrate if I could control what character(s) were being sent to base the detection method on using the pulseIn() method, as some characters would falsely cause that method to think the baudrate is slower then actual as there was no single bit length avalible in certain characters. That means a reliable algorithm when using arbitrary input characters would have to look at multiple characters and search for a minimum bit length. That was too complex for me to continue playing with, but certainly possible. On using a single character baudrate detection using the 'U' character I think, did work reliably as did several other characters, but several characters would 'spoof' the detection method, it's been while.

Lefty

retrolefty

#5
Mar 29, 2012, 04:18 pm Last Edit: Mar 29, 2012, 04:29 pm by retrolefty Reason: 1

You don't need to detect the 1010 pattern. All you need is to measure the shortest interval between two flanks (rising -> falling, or falling -> rising) for some amount of traffic. Assuming the communications wiring is good, the shortest duration between two flanks will be the duration of a single bit. The baud rate will then be 1 divided by that duration (in seconds.) You probably want to round/clamp/adjust that to be the closest "standard" baud rate once measured.



The flaw in that method is that there can be characters received that will not contain a valid single bit length. So one has to make a statistical guess at how many consecutive characters to analyze before deciding that you have 100% certainly captured the lowest single bit timing value.

Lefty

celem

#6
Mar 29, 2012, 05:10 pm Last Edit: Mar 29, 2012, 05:17 pm by celem Reason: 1
One option is to connect the GPS directly to a serial port on your computer and capture the initial character after a known operation, such as GPS power cycle, reset, or some other easy function. Then, use the above mentioned bit timing on the, now, known first character. This method is limited to that specific GPS but you didn't indicate that you wanted a universal method, which is, obviously, harder as you don't know what data is being sent. That said, however, a universal method would be to assume that there is a quiet period between data - reasonable with a stationary GPS, and time for the shortest start bit only. A start bit followed by a "high" in data bit zero. would be what you would time for. Hopefully some character in a stream will have this case and all data will not have a "low" in data bit zero. You would time some quantity of characters, only evaluating the time of the initial start bit. Each character ends with a stop of two "high" bits, so a continuous stream of data will always have a "low" start bit following two "high" bits.

8051 assembly code at the link below provides a similar method, in this case measuring the character length:
http://www.programmersheaven.com/download/3733/1/ZipView.aspx

This may help:
Code: [Select]
/* Determine the baud rate to operate at by getting characters until
we find something recognizable. Return with the global 'rate' set and
Novation type modems put in transparent mode. The initial delay is because
the answer modem returns connect info much earlier than the originate. */

connect() {

unsigned n;

        delay(100);                    /* delay */
        flush(1);                            /* flush garbage */
        cd_flag= 0;                    /* watch carrier */

        while (1) {
                rate= 300;
                baud(rate);               /* test at 300 baud */
                n= mrconin();         /* get a raw key */

/* At 1200 and above, one byte (CR or anything) fits into 1/4th a character,
so the rest of it is ones. If we find f0h, try more or less the same thing
as the 300 vs. 600 case, but at 1200 baud. */

                if ((n & 0xf0) == 0xf0) {
                        rate= 1200;
                        baud(rate);
                        n= mrconin();      /* RAW Modem conin() */
                        if ((n & 0x7f) == CR) break;
                        if ((n & 0x7f) == ' ') break;
                        if ((n & 0xf0) == 0xf0) {
                                rate= 2400;
                                baud(rate);
                                break;
                        }

/* For 300 baud, we should get a CR. If so, get another to make sure. It
might have been garbage or a leftover result code. Baud rate is already
set to 300. */

                } else {
                        n= mrconin();
                        if ((n & 0x7f) == CR) break;
                        if ((n & 0x7f) == ' ') break;
                }

/* None of the above. Now we need to flush before we try again, as we
somehow might have ended up receiving 300 baud chars at 1200, and that
generates multiple garbage bytes. */

                flush(5);                     /* 50 mS quiet, flush garbage */
        }

/* All set. Put Novation modems to sleep, and flush the software ring buffer
and things. */

        if (mdmtype == SMARTCAT) atp("\016U 0",CR);
        if (mdmtype == IBMJR) atp("\016T 0",CR);
        if ((mdmtype == IBMJR) || (mdmtype == SMARTCAT)) delay(100);
        mconflush();
}

robtillaart


I recall from NetworkClass that you should not look at the individual bits only but to the whole frame first to be able to detect the number of databits stopbits.
The advantage of checking the whole frame is that you know for sure that the startbit and stop bit are HIGH

If you would only measure the framelength that would be typical be 1 start, 8 data and 1 or 2 stopbits, so that are 10 or 11 bits. 10% margin.

The default speeds differ mostly a factor 1.5-2 . 300, 600, 1200,2400,4800,9600,14400,19200 etc

The formula is similar than with reading one bit.  baudrate = (10/time);  // or 11/time
and find the nearest value.

my 2 bits



Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

retrolefty



I recall from NetworkClass that you should not look at the individual bits only but to the whole frame first to be able to detect the number of databits stopbits.
The advantage of checking the whole frame is that you know for sure that the startbit and stop bit are HIGH

But for sure the start bit is LOW. Finding the true 'frame length' is no straight forward task either without knowledge of the character(s) being sent, and especially if called with a continuous serial stream already being sent.
If you would only measure the framelength that would be typical be 1 start, 8 data and 1 or 2 stopbits, so that are 10 or 11 bits. 10% margin.

Again I think you might be understating how straight forward the task may be.

The default speeds differ mostly a factor 1.5-2 . 300, 600, 1200,2400,4800,9600,14400,19200 etc

Some auto-baud rate algorithms might assume 'standard' rates must be being used, but that is both an assumption and a limitation, no?

The formula is similar than with reading one bit.  baudrate = (10/time);  // or 11/time
and find the nearest value.

my 2 bits

Worth what you are charging.  ;)

Lefty




robtillaart

Quote
But for sure the start bit is LOW.

Is it? In fact I think it depends ==> the soft serial lib has an inverted flag, so that is a thing you should know too.

Other idea is to measure the timing of all flanks within a frame (sofar as possible) and determine the greatest common denominator

if you have only 2 distances 20 and 50 then the GCD is 10.  This is the best estimator for a single bit you have by using the multibit info
(drawback is that if you have 20 and 40 it wont work).

Think this can become a late night project....==> todo list



Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Nick Gammon

I think it could be done with a reasonable amount of data. Putting aside whether or not the data is inverted (hopefully you know that?). In short bursts you might not be able to tell the difference between 001100 at 9600 baud and 010 at 4800 baud. Also if the data comes in long, close-together, bursts, the stop-bit/start-bit transition might look like data.

Personally I would sample a few dozen bits, and look for the shortest transition. Presumably that is a single bit length. Then try to find the nearest "standard" baud rate to that. You might also guess that any long periods of a single value are the idle state (usually that would be 1 bits). Knowing the idle state, and timing between one idle state and another should give you the character time. However that could be problematic, as something like this could be valid:

Code: [Select]
1111101111111111111111111

The 0 is the start bit, the rest is sending the character 0xFF. You can't really tell much from that ... except that by measuring the length of the zero you have one bit time. But if they sent 0xFE you would see:

Code: [Select]
11111001111111111111111111

Now that single bit time looks twice as long. So, not totally reliable.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nick Gammon

BTW the Salaea logic analyzer has an "auto-baud" mode which is quite useful for plugging in and seeing what it comes up with. I think with enough data it makes a reasonable guess. Out of interest I found it got 9600 exactly right, but when I sent 115200 it reported 117647 baud. Quite possibly it was correct, a couple of percentage points out could be accounted for by the processor clock not being exactly right.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

retrolefty

#12
Mar 29, 2012, 11:54 pm Last Edit: Mar 30, 2012, 12:13 am by retrolefty Reason: 1
Quote
Is it? In fact I think it depends ==> the soft serial lib has an inverted flag, so that is a thing you should know too.



No, it doesn't depend on anything, no matter inverted or non-inverted, with asynchronous serial data the start bit and the stop bit(s) are always of opposite state of each other. A start bit is consider a SPACE bit condition no matter what the logic polarity is and a stop bit(s) are always considered a MARK bit condition.  

Bottom line is that auto-baud detection can be as easy or difficult as one can imagine depending on the how robust and reliable one requires and if there is any assumptions or not one can make about the incoming serial stream. For instance what if there is no data arriving, does your detection function just block all further processing waiting for it to possibly be coming? Or should it be interrupt driven so as to auto-detect only kicks in when activity starts on the serial stream and does a one time check and never run again until reset or power cycled? Does on make the assumption that parity even or odd isn't being sent or that the stop bits are one or two (there is even a ancient 1 1/2 stop bit option). If parity is detected should the transmit response be made to match? It's one of those applications that the more you look into possible 'difficulties' the deeper the hole appears to be. I think most auto-baud rate detection methods just resign to be 'good enough' for the overall application and use whatever assumptions that the specific application allows one to take. It's a hard one to make bullet proof perfect under all possible conditions internal and external to the sketch.

My company purchased for us in around 1979 a state of the art hardware based asynchronous serial data analyzer, a model called the Data Hawk but I forget the company name. It had a small 9" crt screen and could be configured to display and or send at all the standard baud rates, show serial control signal statues, flag parity errors if configured, detect framing errors, display in ascii, hex, binary, octal data format, able to monitor in series with an existing serial circuit and display data from both directions, and many other features and functions that I can't even specifically recall. As I do recall it cost $12,000 and was invaluable in troubleshooting the many many mixed vendor systems we had in the refinery. One thing it didn't even try to do was auto-baud rate detect, one just had to keep trying a various standard rates until you could recognize a valid data stream. It's amazing that today just a standard arduino board and a little RS-232 voltage converter chips could probably duplicate the same functions, but the sketch would not be trival by any means.

Lefty


PaulS

Quote
It's a hard one to make bullet proof perfect.

If it weren't, there would be no need to ever set a baud rate.

Graynomad

#14
Mar 30, 2012, 12:20 am Last Edit: Mar 30, 2012, 12:22 am by Graynomad Reason: 1
Agreed that fully robust algorithm will be very difficult, but a fairly good system should be easy enough.

As has been mentioned timing between edges should to the job, after say 50 edges you would be very unlucky not to have a valid reading with any normal data. Sure if you received 50 bytes with only the lower bits set to 0 you would be fooled because they would merge with the start bit, but that won't happen with a GPS data stream.

As for stop/parity/inversion etc that's a different problem that doesn't affect the bit rate detection.

______
Rob
Rob Gray aka the GRAYnomad www.robgray.com

Go Up