Forums

baud rate autodetection on AVR 8-bit?

Started by Ivan Shmakov December 7, 2012
	BTW, is there an easy way to autodetect the baud rate while
	using an AVR UART?  (Preferably something that works with
	ATmega8, given that those MCU's are such a cheap thing
	nowadays.)

	There're some ideas (and 8051 code) for that on [1], but I'd
	like to know if there could be any better techniques.

	TIA.

[1] http://www.pjrc.com/tech/8051/autobaud.html

PS.  It seems that I'm slowly drifting into designing my own, AVR-based
	Bus Pirate clone.  The good news is that the parts for this one
	will likely cost under $10... (connectors included.)

-- 
FSF associate member #7257
On Fri, 07 Dec 2012 21:17:16 +0700, Ivan Shmakov <oneingray@gmail.com>
wrote:

> BTW, is there an easy way to autodetect the baud rate while > using an AVR UART? (Preferably something that works with > ATmega8, given that those MCU's are such a cheap thing > nowadays.) > > There're some ideas (and 8051 code) for that on [1], but I'd > like to know if there could be any better techniques.
It's pretty straightforward if you can use a timer capture pin; it takes care of grabbing the timer count on the active edge and you can examine it at leisure. Essentially, you will want to listen to an incoming serial stream to measure the narrowest pulse and when you've seen enough identical pulses, that determines the rate. If you get a narrower pulse (that is wider than a glitch width), start the count over. A little more robust is to add N to an accumulator when you see a pulse within epsilon of the current narrow width, subtract M if there is a wider pulse, or reset to zero and start over if there is a narrower. When the accumulator reaches Q, you've found the pulse width. If it counts down to zero (from too many wider pulses), assume you saw a narrow noise pulse and start over. A divide-by-16 (>>4) works pretty well for epsilon. -- Rich Webb Norfolk, VA
>>>>> Rich Webb <bbew.ar@mapson.nozirev.ten> writes: >>>>> On Fri, 07 Dec 2012 21:17:16 +0700, Ivan Shmakov wrote:
>> BTW, is there an easy way to autodetect the baud rate while using an >> AVR UART? (Preferably something that works with ATmega8, given that >> those MCU's are such a cheap thing nowadays.) >> There're some ideas (and 8051 code) for that on [1], but I'd like to >> know if there could be any better techniques. > It's pretty straightforward if you can use a timer capture pin; it > takes care of grabbing the timer count on the active edge and you can > examine it at leisure. Well, I guess I can use a pin change interrupt instead, and just save the timer's counter in the handler. (Thus introducing a constant delay, which will disappear anyway in the delta.) > Essentially, you will want to listen to an incoming serial stream to > measure the narrowest pulse and when you've seen enough identical > pulses, that determines the rate. Indeed, thanks! > If you get a narrower pulse (that is wider than a glitch width), > start the count over. > A little more robust is to add N to an accumulator when you see a > pulse within epsilon of the current narrow width, subtract M if there > is a wider pulse, or reset to zero and start over if there is a > narrower. When the accumulator reaches Q, you've found the pulse > width. If it counts down to zero (from too many wider pulses), > assume you saw a narrow noise pulse and start over. A divide-by-16 > (>> 4) works pretty well for epsilon. I guess I'd need to meditate over this one for some time. Thanks. -- FSF associate member #7257
On Fri, 07 Dec 2012 23:31:21 +0700, Ivan Shmakov <oneingray@gmail.com>
wrote:

>>>>>> Rich Webb <bbew.ar@mapson.nozirev.ten> writes: >>>>>> On Fri, 07 Dec 2012 21:17:16 +0700, Ivan Shmakov wrote: > > >> BTW, is there an easy way to autodetect the baud rate while using an > >> AVR UART? (Preferably something that works with ATmega8, given that > >> those MCU's are such a cheap thing nowadays.) > > >> There're some ideas (and 8051 code) for that on [1], but I'd like to > >> know if there could be any better techniques. > > > It's pretty straightforward if you can use a timer capture pin; it > > takes care of grabbing the timer count on the active edge and you can > > examine it at leisure. > > Well, I guess I can use a pin change interrupt instead, and just > save the timer's counter in the handler. (Thus introducing a > constant delay, which will disappear anyway in the delta.) > > > Essentially, you will want to listen to an incoming serial stream to > > measure the narrowest pulse and when you've seen enough identical > > pulses, that determines the rate. > > Indeed, thanks! > > > If you get a narrower pulse (that is wider than a glitch width), > > start the count over. > > > A little more robust is to add N to an accumulator when you see a > > pulse within epsilon of the current narrow width, subtract M if there > > is a wider pulse, or reset to zero and start over if there is a > > narrower. When the accumulator reaches Q, you've found the pulse > > width. If it counts down to zero (from too many wider pulses), > > assume you saw a narrow noise pulse and start over. A divide-by-16 > > (>> 4) works pretty well for epsilon. > > I guess I'd need to meditate over this one for some time. > Thanks.
The problem is that if a rogue pulse is detected then you could end up waiting forever for the confirming pulses. Say you expect baud rates from 4800 to 115200, corresponding to pulses from 2400 to 100 ticks wide (picking an artificial clock rate) and selected a minimum of 80 ticks (where 80 or less is ignored as a glitch). Say the actual baud rate was 4800 but before you sync'd to it a noise pulse from, say, inserting the connector was detected that was 1200 ticks wide. You'd wait forever watching the 4800 baud pulses (2400 wide) and never see another, so there has to be some mechanism to abandon the current minimum and start the search anew. One way to avoid the trap is to add, say, 10 to an accumulator for every pulse matching the currently observed minimum and declaring a valid minimum if, say, a count of 50 is reached. Deduct 1 from the accumulator whenever a pulse wider than the current minimum is seen and start the search over if the count ever gets back to zero (or if a narrower pulse is detected, of course). -- Rich Webb Norfolk, VA
On Fri, 07 Dec 2012 23:31:21 +0700, Ivan Shmakov wrote:

>>>>>> Rich Webb <bbew.ar@mapson.nozirev.ten> writes: On Fri, 07 Dec 2012 >>>>>> 21:17:16 +0700, Ivan Shmakov wrote: > > >> BTW, is there an easy way to autodetect the baud rate while using an > >> AVR UART? (Preferably something that works with ATmega8, given that > >> those MCU's are such a cheap thing nowadays.) > > >> There're some ideas (and 8051 code) for that on [1], but I'd like to > >> know if there could be any better techniques. > > > It's pretty straightforward if you can use a timer capture pin; it > > takes care of grabbing the timer count on the active edge and you can > > examine it at leisure. > > Well, I guess I can use a pin change interrupt instead, and just
save
> the timer's counter in the handler. (Thus introducing a constant > delay, which will disappear anyway in the delta.)
The delay will only be constant if you have no higher priority interrupt active. Depending on what you're trying to do this will range anywhere from completely painless to an absolute deal-killer. -- My liberal friends think I'm a conservative kook. My conservative friends think I'm a liberal kook. Why am I not happy that they have found common ground? Tim Wescott, Communications, Control, Circuits & Software http://www.wescottdesign.com
On Friday, December 7, 2012 11:31:21 AM UTC-5, Ivan Shmakov wrote:
> Well, I guess I can use a pin change interrupt instead, and just > save the timer's counter in the handler. (Thus introducing a > constant delay, which will disappear anyway in the delta.)
No "capture" function available on the timer, so that you get an exact measurement ? Sorry I don't remember on this part...
>>>>> Dave Nadler <drn@nadler.com> writes: >>>>> On Friday, December 7, 2012 11:31:21 AM UTC-5, Ivan Shmakov wrote:
>> Well, I guess I can use a pin change interrupt instead, and just >> save the timer's counter in the handler. (Thus introducing a >> constant delay, which will disappear anyway in the delta.) > No "capture" function available on the timer, so that you get an > exact measurement? Sorry I don't remember on this part... AIUI, ATmega8 only allows for input capture to happen on an "event" occuring either on analog comparator output, or a specific ICP1 pin. Unfortunately, I'd need the latter for GPIO. (Naturally, ICP1 is distinct from UART's RxD.) -- FSF associate member #7257
On 12/7/2012 9:42 AM, Rich Webb wrote:
> On Fri, 07 Dec 2012 23:31:21 +0700, Ivan Shmakov<oneingray@gmail.com> > wrote: > >>>>>>> Rich Webb<bbew.ar@mapson.nozirev.ten> writes: >>>>>>> On Fri, 07 Dec 2012 21:17:16 +0700, Ivan Shmakov wrote: >> >>>> BTW, is there an easy way to autodetect the baud rate while using an >>>> AVR UART? (Preferably something that works with ATmega8, given that >>>> those MCU's are such a cheap thing nowadays.) >> >>>> There're some ideas (and 8051 code) for that on [1], but I'd like to >>>> know if there could be any better techniques. >> >>> It's pretty straightforward if you can use a timer capture pin; it >>> takes care of grabbing the timer count on the active edge and you can >>> examine it at leisure. >> >> Well, I guess I can use a pin change interrupt instead, and just >> save the timer's counter in the handler. (Thus introducing a >> constant delay, which will disappear anyway in the delta.) >> >>> Essentially, you will want to listen to an incoming serial stream to >>> measure the narrowest pulse and when you've seen enough identical >>> pulses, that determines the rate. >> >> Indeed, thanks! >> >>> If you get a narrower pulse (that is wider than a glitch width), >>> start the count over. >> >>> A little more robust is to add N to an accumulator when you see a >>> pulse within epsilon of the current narrow width, subtract M if there >>> is a wider pulse, or reset to zero and start over if there is a >>> narrower. When the accumulator reaches Q, you've found the pulse >>> width. If it counts down to zero (from too many wider pulses), >>> assume you saw a narrow noise pulse and start over. A divide-by-16 >>> (>> 4) works pretty well for epsilon. >> >> I guess I'd need to meditate over this one for some time. >> Thanks. > > The problem is that if a rogue pulse is detected then you could end up > waiting forever for the confirming pulses. Say you expect baud rates > from 4800 to 115200, corresponding to pulses from 2400 to 100 ticks wide > (picking an artificial clock rate) and selected a minimum of 80 ticks > (where 80 or less is ignored as a glitch). > > Say the actual baud rate was 4800 but before you sync'd to it a noise > pulse from, say, inserting the connector was detected that was 1200 > ticks wide. You'd wait forever watching the 4800 baud pulses (2400 wide) > and never see another, so there has to be some mechanism to abandon the > current minimum and start the search anew. > > One way to avoid the trap is to add, say, 10 to an accumulator for every > pulse matching the currently observed minimum and declaring a valid > minimum if, say, a count of 50 is reached. Deduct 1 from the accumulator > whenever a pulse wider than the current minimum is seen and start the > search over if the count ever gets back to zero (or if a narrower pulse > is detected, of course). >
I gave up several times on a similar project when I couldn't determine the characteristics of the data stream...or even if there was one. Been thinking about this for an hour or so. If you take a random pulse width measurement. Save that as mmpw, minimum measured pulse width. Have a table of pulse widths for the allowable baud rates. Scan up the table till you find a number match. IF not, multiply the table by 2 then three then four... Eventually you should find a match. Program that into the USART. Have the character input interrupt start looking for framing errors. Take another random pulse width measurement. If it's smaller than mmpw, plug it into mmpw and restart. If it's larger, subtract the two numbers. The difference should be an integral multiple of the REAL pulse width for the actual baud rate. Divide the numbers. If the remainder isn't zero, mmpw isn't the correct bit time. I think the correct bit time is an integer multiple of the remainder, but I haven't got my head fully around that one. Use those numbers to scan for a higher baud rate and an inferred new mmpw. Quit when you get tired of looking for narrower mmpw or those that aren't an integral multiple of the trial bit time and aren't getting framing errors. Of course, there are all kinds of issues with timing synchronization, error bounds, glitches etc. that need to be dealt with. And the simplest way of thinking about it seems to result in a recursive algorithm which isn't nice on a simple processor...so maybe the details kill the concept...but it would be interesting to play with. I like it because I think it converges even if you never catch an actual one-bit-wide pulse.
On Fri, 07 Dec 2012 13:35:14 -0800, mike <ham789@netzero.net> wrote:

>On 12/7/2012 9:42 AM, Rich Webb wrote: >> On Fri, 07 Dec 2012 23:31:21 +0700, Ivan Shmakov<oneingray@gmail.com> >> wrote: >> >>>>>>>> Rich Webb<bbew.ar@mapson.nozirev.ten> writes: >>>>>>>> On Fri, 07 Dec 2012 21:17:16 +0700, Ivan Shmakov wrote: >>> >>>>> BTW, is there an easy way to autodetect the baud rate while using an >>>>> AVR UART? (Preferably something that works with ATmega8, given that >>>>> those MCU's are such a cheap thing nowadays.) >>> >>>>> There're some ideas (and 8051 code) for that on [1], but I'd like to >>>>> know if there could be any better techniques. >>> >>>> It's pretty straightforward if you can use a timer capture pin; it >>>> takes care of grabbing the timer count on the active edge and you can >>>> examine it at leisure. >>> >>> Well, I guess I can use a pin change interrupt instead, and just >>> save the timer's counter in the handler. (Thus introducing a >>> constant delay, which will disappear anyway in the delta.) >>> >>>> Essentially, you will want to listen to an incoming serial stream to >>>> measure the narrowest pulse and when you've seen enough identical >>>> pulses, that determines the rate. >>> >>> Indeed, thanks! >>> >>>> If you get a narrower pulse (that is wider than a glitch width), >>>> start the count over. >>> >>>> A little more robust is to add N to an accumulator when you see a >>>> pulse within epsilon of the current narrow width, subtract M if there >>>> is a wider pulse, or reset to zero and start over if there is a >>>> narrower. When the accumulator reaches Q, you've found the pulse >>>> width. If it counts down to zero (from too many wider pulses), >>>> assume you saw a narrow noise pulse and start over. A divide-by-16 >>>> (>> 4) works pretty well for epsilon. >>> >>> I guess I'd need to meditate over this one for some time. >>> Thanks. >> >> The problem is that if a rogue pulse is detected then you could end up >> waiting forever for the confirming pulses. Say you expect baud rates >> from 4800 to 115200, corresponding to pulses from 2400 to 100 ticks wide >> (picking an artificial clock rate) and selected a minimum of 80 ticks >> (where 80 or less is ignored as a glitch). >> >> Say the actual baud rate was 4800 but before you sync'd to it a noise >> pulse from, say, inserting the connector was detected that was 1200 >> ticks wide. You'd wait forever watching the 4800 baud pulses (2400 wide) >> and never see another, so there has to be some mechanism to abandon the >> current minimum and start the search anew. >> >> One way to avoid the trap is to add, say, 10 to an accumulator for every >> pulse matching the currently observed minimum and declaring a valid >> minimum if, say, a count of 50 is reached. Deduct 1 from the accumulator >> whenever a pulse wider than the current minimum is seen and start the >> search over if the count ever gets back to zero (or if a narrower pulse >> is detected, of course). >> >I gave up several times on a similar project when I couldn't determine >the characteristics of the data stream...or even if there was one. > >Been thinking about this for an hour or so. > >If you take a random pulse width measurement. >Save that as mmpw, minimum measured pulse width. >Have a table of pulse widths for the allowable baud rates. >Scan up the table till you find a number match. >IF not, multiply the table by 2 then three then four... >Eventually you should find a match. >Program that into the USART. Have the character input interrupt >start looking for framing errors. > >Take another random pulse width measurement. >If it's smaller than mmpw, plug it into mmpw and restart. >If it's larger, subtract the two numbers. The difference should >be an integral multiple of the REAL pulse width for the actual baud rate. >Divide the numbers. If the remainder isn't zero, mmpw isn't the >correct bit time. I think the correct bit time is an integer multiple >of the remainder, but I haven't got my head fully around that one. >Use those numbers to scan for a higher baud rate and an inferred new mmpw. >Quit when you get tired of looking for narrower mmpw or those that >aren't an integral multiple of the trial bit time and aren't >getting framing errors. > >Of course, there are all kinds of issues with timing synchronization, >error bounds, glitches etc. that need to be dealt with. And the >simplest way of thinking about it seems to result in a recursive >algorithm which isn't nice on a simple processor...so maybe the >details kill the concept...but it would be interesting to play with. > >I like it because I think it converges even if you never catch an actual >one-bit-wide pulse.
For any given algorithm [*] it's probably possible to construct a data stream that can fool it. I have found the "accumulator with decrement" method to be reliable and simple [**] to sync with ASCII (NMEA 0183) data that's always at 4800 baud except when it isn't. It certainly helps that on common 8N1 lines, ASCII's 0 MSB precedes the 1 of the stop bit and that is followed by a 0 for the next start bit. It is a good idea to check the discovered pulse width against expected values for legal (for the application) baud rates and then take appropriate action if there isn't a match. [*] The exception may be the "Hit the <some specific> key until the terminal replies with OK" method. Even then it might be possible to find bogus inputs that "work" at the wrong baud rate for some keys. [**] Always a plus when coming back do maintenance on the code several years later. -- Rich Webb Norfolk, VA
In article <k9tnfa$8pf$1@dont-email.me>, ham789@netzero.net says...
> > On 12/7/2012 9:42 AM, Rich Webb wrote: > > On Fri, 07 Dec 2012 23:31:21 +0700, Ivan Shmakov<oneingray@gmail.com> > > wrote: > > > >>>>>>> Rich Webb<bbew.ar@mapson.nozirev.ten> writes: > >>>>>>> On Fri, 07 Dec 2012 21:17:16 +0700, Ivan Shmakov wrote: > >> > >>>> BTW, is there an easy way to autodetect the baud rate while using an > >>>> AVR UART? (Preferably something that works with ATmega8, given that > >>>> those MCU's are such a cheap thing nowadays.) > >> > >>>> There're some ideas (and 8051 code) for that on [1], but I'd like to > >>>> know if there could be any better techniques. > >> > >>> It's pretty straightforward if you can use a timer capture pin; it > >>> takes care of grabbing the timer count on the active edge and you can > >>> examine it at leisure. > >> > >> Well, I guess I can use a pin change interrupt instead, and just > >> save the timer's counter in the handler. (Thus introducing a > >> constant delay, which will disappear anyway in the delta.) > >> > >>> Essentially, you will want to listen to an incoming serial stream to > >>> measure the narrowest pulse and when you've seen enough identical > >>> pulses, that determines the rate. > >> > >> Indeed, thanks! > >> > >>> If you get a narrower pulse (that is wider than a glitch width), > >>> start the count over. > >> > >>> A little more robust is to add N to an accumulator when you see a > >>> pulse within epsilon of the current narrow width, subtract M if there > >>> is a wider pulse, or reset to zero and start over if there is a > >>> narrower. When the accumulator reaches Q, you've found the pulse > >>> width. If it counts down to zero (from too many wider pulses), > >>> assume you saw a narrow noise pulse and start over. A divide-by-16 > >>> (>> 4) works pretty well for epsilon. > >> > >> I guess I'd need to meditate over this one for some time. > >> Thanks. > > > > The problem is that if a rogue pulse is detected then you could end up > > waiting forever for the confirming pulses. Say you expect baud rates > > from 4800 to 115200, corresponding to pulses from 2400 to 100 ticks wide > > (picking an artificial clock rate) and selected a minimum of 80 ticks > > (where 80 or less is ignored as a glitch). > > > > Say the actual baud rate was 4800 but before you sync'd to it a noise > > pulse from, say, inserting the connector was detected that was 1200 > > ticks wide. You'd wait forever watching the 4800 baud pulses (2400 wide) > > and never see another, so there has to be some mechanism to abandon the > > current minimum and start the search anew. > > > > One way to avoid the trap is to add, say, 10 to an accumulator for every > > pulse matching the currently observed minimum and declaring a valid > > minimum if, say, a count of 50 is reached. Deduct 1 from the accumulator > > whenever a pulse wider than the current minimum is seen and start the > > search over if the count ever gets back to zero (or if a narrower pulse > > is detected, of course). > > > I gave up several times on a similar project when I couldn't determine > the characteristics of the data stream...or even if there was one. > > Been thinking about this for an hour or so. > > If you take a random pulse width measurement. > Save that as mmpw, minimum measured pulse width. > Have a table of pulse widths for the allowable baud rates. > Scan up the table till you find a number match. > IF not, multiply the table by 2 then three then four... > Eventually you should find a match. > Program that into the USART. Have the character input interrupt > start looking for framing errors. > > Take another random pulse width measurement. > If it's smaller than mmpw, plug it into mmpw and restart. > If it's larger, subtract the two numbers. The difference should > be an integral multiple of the REAL pulse width for the actual baud rate. > Divide the numbers. If the remainder isn't zero, mmpw isn't the > correct bit time. I think the correct bit time is an integer multiple > of the remainder, but I haven't got my head fully around that one. > Use those numbers to scan for a higher baud rate and an inferred new mmpw. > Quit when you get tired of looking for narrower mmpw or those that > aren't an integral multiple of the trial bit time and aren't > getting framing errors. > > Of course, there are all kinds of issues with timing synchronization, > error bounds, glitches etc. that need to be dealt with. And the > simplest way of thinking about it seems to result in a recursive > algorithm which isn't nice on a simple processor...so maybe the > details kill the concept...but it would be interesting to play with. > > I like it because I think it converges even if you never catch an actual > one-bit-wide pulse.
If you've got lots of time and continuous input, you can try the timing approach, then try to verify your estimate by looking for known patterns in the data. If you can't find the pattern (or correct checksum, etc.), start over. If the data has known patterns, and you can assume a limited set of standard baud rates, you can simply look for a known character stream in the data. I once used an instrument which would accept any standard baud rate. The manual said "when you power up the instrument, press the space bar repeatedly until the instrument responds with the startup message. The instrument simply stepped through baud rates with each incoming character until it found a space character. You could apply the same approach, with a more complex algorithm, to any source that provides a data stream with known characteristics. Mark Borgerson