Have somebody implemented Auto Baud Rate Detection for UART.
I have tried the method where you send one command to the device and and receive a know response. This is done in a loop where the baud rate is changing until a correct response is matched.
But I want a method where you do not send a command to the device and changing the baud rate in a loop, but only catch the response and calculate or determine the baud rate.
not sure if the RX pin can be used as PinCapture pin (see: GHIElectronics.NETMF.Hardware), but if so, you can get the pulse width and calculate the bits / second.
Yeah a cool way to cheat and get auto baud detection
I’m gonna try it now! Will come back with results.
Ok i got some results but i’m not there yet.
Here is my code so far.
public static void Main()
{
Thread.Sleep(5000); //keep this under debug else can emx be hard to reach
//Port IO32 on EMX is RX COM2
PinCapture cap = new PinCapture((Cpu.Pin)FEZ_Pin.Digital.IO32, Port.ResistorMode.Disabled);
uint[] buff = new uint[64];
while (true)
{
int bits = cap.Read(false, buff, 0, buff.Length, 3000);
if (bits == 0)
{
Debug.Print("Nothing was captured!");
}
else
{
double total = 0;
for (int i = 0; i < bits; i++)
{
Debug.Print("Bit: " + i + " = " + buff[i]);
total = total + buff[i];
}
Debug.Print("Bits/edges " + bits);
Debug.Print("Total time: " + total);
Debug.Print("Time / bits = " + (total / bits));
Debug.Print("Baud Rate (1000000 * bits) / total = " + (1000000 * bits) / total);
}
}
}
When I send character U (0x55), single or multiple all works great, I get the correct Baud Rate. The
problem is when I sending other character, then the Baud Rate is not correct. Gonna look in to that but if somebody know something I don’t please let me know.
Don’t you need to search for the shortest time and take that as the bit time?
I have tried to search for a pattern but I can’t see it.
This is result when I send “UU”.
Bit: 0 = 44
Bit: 1 = 55
Bit: 2 = 54
Bit: 3 = 55
Bit: 4 = 45
Bit: 5 = 54
Bit: 6 = 55
Bit: 7 = 55
Bit: 8 = 43
Bit: 9 = 55
Bit: 10 = 55
Bit: 11 = 45
Bit: 12 = 57
Bit: 13 = 53
Bit: 14 = 55
Bit: 15 = 43
Bit: 16 = 55
Bit: 17 = 55
Bit: 18 = 56
Bits/edges 19
Total time: 989
Time / bits = 52.05263157894737
Baud Rate (1000000 * bits) / total = 19211.324570273002 (Real Baudrate is 19200)
and this is whe I send “EE” or other character
Bit: 0 = 34
Bit: 1 = 54
Bit: 2 = 57
Bit: 3 = 55
Bit: 4 = 150
Bit: 5 = 49
Bit: 6 = 50
Bit: 7 = 59
Bit: 8 = 49
Bit: 9 = 50
Bit: 10 = 49
Bit: 11 = 60
Bit: 12 = 150
Bit: 13 = 59
Bit: 14 = 49
Bits/edges 15
Total time: 974
Time / bits = 64.933333333333337
Baud Rate (1000000 * bits) / total = 15400.410677618071
If I take the shortest time like “Bit: 5 = 49” I get 974/49 = 20400 , it is near the 19200.
Yes, look at shortest one and this is your baud. Note that you must always ignore the very first one as it maybe shopped.
The next step in auto baud is to either find the closest standard baud or communicate with your “other side” and ask for the correct baud.
I am also trying to make an autobaud routine.
Reached to the same conclusion before seraching for that topic : PinCapture, ignore 1st one, search minimum.
Here is my code :
public static int FindBaudRate(Cpu.Pin _rxPin )
{
uint[] durations = new uint[20];
bool initial = false;
PinCapture pc = new PinCapture( _rxPin, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth );
int n = pc.Read(initial, durations, 0, durations.Length, 1500);
pc.Dispose();
uint minDuration = 1000000000;
// ignoring 1st duration (may be incomplete)
for (int i = 1; i < n; i++)
{
Debug.Print("Duration[" + i.ToString() + "]=" + durations[i]);
if (minDuration > durations[i])
minDuration = durations[i];
}
Debug.Print("minDuration=" + minDuration);
int baudrate = 1000000 / (int)minDuration;
Debug.Print("Baudrate="+baudrate.ToString());
return baudrate;
}
But the resulting values are quite out of what I am expecting.
Knowing that I am receiving continuous data from a GPS, here are the values :
Known baudrate is 38400 which should give a minimum duration of 26 us.
I have tried both with and without interrupts (I’m not sure how this impact the behavior of PinCapture);
Any suggestion to enhance ?
I think you don’t have any chance using Netmf because it’s not realtime OS and timings are not accurate.
Maybe RLP could help, here. But that’s not as easy as Netmf, though ???
I am expecting GHI to have implemented PinCapture in RLP
I don’t believe they’ve done it in C#.
But as far as I understand, this is part of their proprietary code.
Yes pin capture is native and fairly accurate.
Gus
If you’re already doing NetMF all the week, you should go fishing during week-end. ;D
Thanks for the confirmation.
I’ll look if I can improve the baud determination algorithm.
I accomplish more work on weekend, no interruptions
Guys
Here is my solution for baud rate detection.
It use a table of most common baud rate (including MIDI)
Comments welcomed
// most commonly used baud rate - including 31250 for MIDI
static int[] StandardBaudRate = new int[] { 120, 240, 1200, 2400, 4800, 9600, 19200, 31250, 38400, 56700, 115200, 230400 };
// bit duration for those baud rate in us
static int[] StandardBitLength = new int[] { 8333, 4167, 833, 417, 208, 104, 52, 32, 26, 18, 9, 5 };
// Call this function _before_ openning the SerialPort.
public static int FindBaudRate(Cpu.Pin _rxPin )
{
// capture bits length using PinCapture
uint[] bits = new uint[40];
bool initial = false; // not used
PinCapture pc = new PinCapture( _rxPin, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth );
int n = pc.Read(initial, bits, 0, bits.Length, 2000);
pc.Dispose();
if (n == 0)
return 0;
// search for minimum bit duration, ignoring 1st one which may be incomplete
uint minBit = 1000000000;
for (int bit_index = 1; bit_index < bits.Length; bit_index++)
{
if ( minBit > bits[bit_index] )
minBit = bits[bit_index];
}
// computing mean values of all bits duration which are below 2*min
uint sum = 0, count = 0;
for (int bit_index = 1; bit_index < bits.Length; bit_index++)
{
if (bits[bit_index] < (2 * minBit))
{
sum += bits[bit_index];
++count;
}
}
uint meanBit = sum / count;
// search in table for index which match the best
int baud_found = -1;
int minDiff = 100000;
for (int baud_index = 0; baud_index < StandardBitLength.Length; ++baud_index)
{
int diff = System.Math.Abs(StandardBitLength[baud_index] - (int)meanBit);
if (diff < minDiff)
{
minDiff = diff;
baud_found = baud_index;
}
}
// if not found (souldn't be)
if (baud_found == -1)
return 0;
// return the baudrate
return StandardBaudRate[baud_found];
}