UART(COM port) baud rate converter? Help anyone?

Guys, i would really appreciate any help - is there any open sourced baud rate converter implemented in arduino for several com ports? I really need something like 115200 ttl com in, and 38400 + 9600 + 115200 out on several com ports. Anybody done this type of thing before?

You just read from one port and write to another, probably 20 lines of code

setup () {
   Serial1.begin (115200);
   Serial2.begin (9600);
}

loop () {
   if (Serial1.available())
       Serial2.write(Serial1.read());
}

Make that 8 lines :slight_smile:


Rob

But this will not work. More thoughts on the subject

GPS data 10HZ, uses about 32000bps of the com port... Yeah, it will work pushing the stream to 38400, but i'll need probably to discard some data for the low speed 9600.... How?

Well I don't think you have defined your requirements well enough to say it can be done or not on a arduino. However a arduino mega board does have four serial ports available so under certain conditions serial conversion is certainly possible. But again requirements have to be more clear, such as:

Is this to be a one way conversion, that is there to be one input stream to the arduino converted to one or more streams outputting at other baud rates from the arduino?

Is the one input stream the slowest of the baud rates relative to the output streams? If not then possible additional buffering might be required in your sketch, above what the arduino hardware serial library makes available.

Lefty

Yes I was a bit flippant there :slight_smile:

If the average input throughput is faster than the output you are screwed. However if the average input is the same or less than what the output can handle you can buffer the data.

Let's say you have an NMEA string of 100 chars occurring every 100mS. That's an average of 1000 chars a second so your output has to match that or better.

There are usually 10 bits per byte when transmitting so 1000 bytes per second == 10000 bits per second so (if we ignore any overheads) your output stream has to have a baud rate of at least 10000bps.

So the actual input baud rate is fairly immaterial, you need to know the number of bytes received per second.

If the above conditions are met you write some simple ring buffer code to hold the characters while they are waiting for transmission.


Rob

I'll try to be more thorough

Data IN:
One UART TTL input, GPS, 115200, 10HZ updates, NMEA, the data is sent to the arduino at a rate 10 times per second so the average baud rate is 32000bps.

Data OUT:
Will need(arduino mega will do): 2/3/4/(the more the better) outputs. The data communication is unidirectional (recieve at RX and transmit to those 2/3/4 TX ports)

  1. Must have an option to strip the NMEA 10HZ data stream to, lets say 2HZ, or even 1HZ, so that the average baud rate would be sufficient for selected baud rate (lets say in this scenario it's 9600)
  2. If the baud rate allows it - no "stripping" neccesary, and all 10HZ data updates can be pushed to those other COM ports..

So that such a config could exist:
Data IN: 115200, NMEA, 10HZ
Data OUT1: 38400, NMEA, 10HZ
DATA OUT2: 14400, NMEA, 5HZ
DATA OUT3: 9600, NMEA, 2HZ

.. I'm a crappy programmer at arduino

So if i am screwed - It seems that the only way is to parse the NMEA data, and discard some of the NMEA "sentences" in case i need to put this data to the port with lower available bandwidth. Ok - is there a library and a parcer for NMEA? )))))

One UART TTL input, GPS, 115200, 10HZ updates, NMEA, the data is sent to the arduino at a rate 10 times per second so the average baud rate is 32000bps.

A little confusing as you are using baudrate to define something other then what it measures. A baud rate is a fixed clocking speed that both sides of a comm link agree to use to clock individual bits onto the com link and does not change. Character rate is a variable rate that can be any value up to a maximum rate possible that can be supported by the baudrate being used. So at a 115200 baud rate, a link can support a character rate to a maximum of 11,520 characters a second (divide by 10 because, 8 bit character + one stop bit + one start bit). However that same 1152000 baud rate link can certainly be used to send a one character message only every one second, so the link would be working at an effective rate of one character a second, even though the bits in that single character are clocking at 1152000 bits per second rate.

So when you say a device like a GPS will be sending a message at a 10hz rate, it doesn't give us a complete picture of the character rate as you don't state how many characters are going to be sent every 10hz, so an effective character rate per second can't be determined. If the GPS message can be of variable character lengths then it's even more difficult to state the effective character rate, only a possible maximum character rate based on the longest possible message.

Baud rate is essential to know as it is used to configure the AVR serial hardware to run at the correct speed you require to support the comm link. Effective character rate is important to know so that one can determine what software support will be required to handle the message traffic from the link, such as possible arrays of a specific length to use to 'buffer' a complete message, and the amount of time your program will have to possibly parse the messages and take action based on the content in the messages.

So your table:

So that such a config could exist:
Data IN: 115200, NMEA, 10HZ
Data OUT1: 38400, NMEA, 10HZ
DATA OUT2: 14400, NMEA, 5HZ
DATA OUT3: 9600, NMEA, 2HZ

Needs at least one other data value added to each link, what is the maximum number of characters that can happen every xxHz message cycle?

Also do you see a possible fatal problem with your defined links? If you can receive new messages into the arduino at up to 10 messages per second but have to limit sending them out as slow as 2 messages per second then your input stream will certainly be coming in faster then you can output the messages, so input stream will have to be buffered and there is limited SRAM memory to support that and I think that sooner or later you will 'overflow' the input buffered stream and lose information?

Lefty

Stepping back a little, what are you actually trying to do? Presumably, you have several devices that consume NMEA sentences; is their baud rate limited? Does each need all sentences or a subset? Does it matter if not all sentences are delivered?

Having some more detail about the requirement might get you some more insightful advice; as is, it's hard to see the why.

Graynomad:
You just read from one port and write to another, probably 20 lines of code

setup () {

Serial1.begin (115200);
   Serial2.begin (9600);
}

loop () {
   if (Serial1.available())
       Serial2.write(Serial1.read());
}




Make that 8 lines :)

______
Rob

You may want to add the lines that define the pins used in the softserial library too :slight_smile:

OK .... so ...

We have two frequencies going on here, and some confusion as to the requirements of the "baud" rate.

The interface speed of the GPS is the baud rate, the rate at which it sends messages is the message rate, the two are not really inter dependent unless you are expecting to be transmitting data at 32 baud :slight_smile:

So even if the messages are coming in at 10Hz unless there is a VERY good reason why not then they can also go out at 10 Hz independently of the baud rates.

The very simple serial repeater posted by Rob will do what you want, all you have to do is extend it to have the number of ports you are expecting to repeat to and specify the pins you are intending to use for the soft serial library. Most NMEA sentences are quite short and will not require buffering but can just be squirted directly out.

If you need more guidance with the coding just shout, I am sure there are plenty of people including myself who can knock this up in 5 minutes for you.

If my understanding is too simplistic and you do need to be throttling the NEMA message rate then it all gets much more complicated.

Cheers Pete.

Guys, really, really thx on advices, i am probably describing the task incorrectly.

  • NMEA - is the protocol for GPS(NMEA 108 to be exact).
  • 10HZ is a must, as the more accurate, the better

10HZ NMEA cannot fit into 9600. That's 100% sure ), although calculating required bandwidth of the NMEA0183 is a bit tricky. And some sort of NMEA parser is needed to discard every 5th NMEA sentence.

The application is RC plane OSD and telemetry. It's really weird using 2-3-4 GPS recievers, instead of just one, but with a splitter, that can split the protocol to the required baudrate(requirment of the end device) and the update rate(also a requirment of the end device)

The longest example of an NMEA0183 sentence I can find is 72 bytes, at 10 transmissions a second that's 720 bytes per second and at 9600bps you can transmit 960 bytes per second.

So on those numbers it should work even with processing overhead.

However we still don't know how long your sentences are and that's the main issue.


Rob

My GPS module is setup so it send only 1 message a second
As many people asked before: what are you trying to do?
Best regards
Jantje

I've already explained. I'm trying to get my OSD, my Flight controller, my telemetry to get to work with one GPS.

When using MTK utility for setting the GPS, it gives an overhead in procentage, when you set the baud rate. And it doesent allow to set any update rates higher than 2HZ for 9600baud... I'am not sure that the sentence is 72bytes, i do believe it's much, much larger.

olaf
You will probably need to filter your GPS input. You do this by sending messages to your GPS module. This way you reduce the input on your arduino.
For my gps module the code looks like this

// what to log
#define LOG_RMC 1 // RMC-Recommended Minimum Specific GNSS Data, message 103,04
#define LOG_GGA 0 // GGA-Global Positioning System Fixed Data, message 103,00
#define LOG_GLL 0 // GLL-Geographic Position-Latitude/Longitude, message 103,01
#define LOG_GSA 0 // GSA-GNSS DOP and Active Satellites, message 103,02
#define LOG_GSV 0 // GSV-GNSS Satellites in View, message 103,03
#define LOG_VTG 0 // VTG-Course Over Ground and Ground Speed, message 103,05
void GPSModule::setup()
{
	bufferidx = 0;
	WDTCSR |= (1 << WDCE) | (1 << WDE);
	WDTCSR = 0;

	// connect to the GPS at the desired rate
	(*m_gpsSerial).begin(m_gpsRate);
	pinMode(m_powerPin, OUTPUT);
	digitalWrite(m_powerPin, LOW);
	//delay(250);
	(*m_gpsSerial).print(SERIAL_SET);
	delay(250);

#if (LOG_DDM == 1)
	(*m_gpsSerial).print(DDM_ON);
#else
	(*m_gpsSerial).print(DDM_OFF);
#endif
	delay(250);
#if (LOG_GGA == 1)
	(*m_gpsSerial).print(GGA_ON);
#else
	(*m_gpsSerial).print(GGA_OFF);
#endif
	delay(250);
#if (LOG_GLL == 1)
	(*m_gpsSerial).print(GLL_ON);
#else
	(*m_gpsSerial).print(GLL_OFF);
#endif
	delay(250);
#if (LOG_GSA == 1)
	(*m_gpsSerial).print(GSA_ON);
#else
	(*m_gpsSerial).print(GSA_OFF);
#endif
	delay(250);
#if (LOG_GSV == 1)
	(*m_gpsSerial).print(GSV_ON);
#else
	(*m_gpsSerial).print(GSV_OFF);
#endif
	delay(250);
#if (LOG_RMC == 1)
	(*m_gpsSerial).print(RMC_ON);
#else
	(*m_gpsSerial).print(RMC_OFF);
#endif
	delay(250);

#if (LOG_VTG == 1)
	(*m_gpsSerial).print(VTG_ON);
#else
	(*m_gpsSerial).print(VTG_OFF);
#endif
	delay(250);

#if (USE_WAAS == 1)
	(*m_gpsSerial).print(WAAS_ON);
#else
	(*m_gpsSerial).print(WAAS_OFF);
#endif
}

I'm using a buffer of 90 characters for the RMC mesage

Best regards
Jantje

I'am not sure that the sentence is 72bytes, i do believe it's much, much larger.

The message length is at the crux of the matter here.


Rob

Check this video you can comment and ask for the code 100 percent operational and customised baudrate converter for GPS nmea