Mini Pro Cereal Timing

This has to be a known issue, but I can’t find an answer on google…

I’m setting up an Arduino mini pro as a buffer/translator between a GPS and an Arduino Uno. The Uno talks to the Mini using i2c, and the GPS talks to the Mini using serial.

[Uno]<–>[Mini]<—[GPS]

As far as I can see, this is a pretty standard setup, and I copied the idea from another Arduino-like device (that tragically died last week).

Anyway, when it’s powered on, the GPS starts sending NMEA frames at 4800 baud, with eight data bits, two stop bits, and no parity. I verified this by plugging its output pin into one of the pins on the Uno and measuring the time between state transitions, and I can manually decode it looking at the output in Notepad:

0 “$”
0
1
0
0
1
0
0

1 Stop bits
1
0

1 “G”
1
1
0
0
0
1
0

1 Stop bits
1
0

0 “P”
0
0
0
1
0
1
0

…and so on. I can even get the GPS to talk to my PC, and it works fine. The problem is that when I plug it into the Arduino Mini (and when I tried to do the same on the previous board I had) I get junk.

Is there any trick I need to do, like make sure the UART knows about the clock timing, etc, to make this work?

Here’s the code I have running on the mini to read from the serial device:

#define SERIAL_INITIAL_SPEED 4800
#define SERIAL_SETTING SERIAL_8N2
Serial.begin(SERIAL_INITIAL_SPEED, SERIAL_SETTING);
while (Serial.available())
{
 if (NewNMEAFrame(Serial.read()))
 {      
   ParseNMEAFrame();
 }
}

Have you tried the standard Serial.begin(4800); ?

I don't understand why you have a Mini and an Uno?

What pins are you using on the Mini to connect to the GPS and what pins are you using on the Mini to connect to the Uno?

Have a look at the examples in Serial Input Basics

...R By the way "cereal" is what you have with your breakfast.

Have you tried the standard Serial.begin(4800); ?

Of course I did. That's the first thing I tried. I'm not a masochist. :D

I don't understand why you have a Mini and an Uno?

The Uno has my servo controller, GSM shield, and 9 axis motor shield on it. If I plug the GPS directly into it, AFAIK, I either have to sacrifice the hardware serial port on it, which I'm using as a debugging monitor or spend precious CPU cycles reading and parsing the GPS data. The mini is in-between so I can have GPS data on demand through i2c.

What pins are you using on the Mini to connect to the GPS and what pins are you using on the Mini to connect to the Uno?

Communication between the Uno and Mini is working fine, so that's not an issue. The GPS is plugged into the middle four pins on the FTDI header -- gnd, vcc, rxi, and txd. I'm pretty sure I've got the order correct because if vcc and ground are mixed up the GPS doesn't power on, and if rxi and txd are mixed up I get silence instead of...junk.

By the way "cereal" is what you have with your breakfast.

No, I have grammar nazis for breakfast! (Admit it, you walked right into that one.)

That is a very clean main loop for your program. It's so clean there could not possibly be any problem there.

Perhaps the problem is in the code you didn't post?

Jon_White:

What pins are you using on the Mini to connect to the GPS and what pins are you using on the Mini to connect to the Uno?

Communication between the Uno and Mini is working fine, so that's not an issue. The GPS is plugged into the middle four pins on the FTDI header -- gnd, vcc, rxi, and txd. I'm pretty sure I've got the order correct because if vcc and ground are mixed up the GPS doesn't power on, and if rxi and txd are mixed up I get silence instead of...junk.

Please just answer the question.

...R

Robin2:
Please just answer the question.

…R

The Mini is attached to the Uno via the VIN, GND, A4, and A5 pins. The GPS is attached to the inner four pins in the FTDI header:

Here’s the most concise repro I have. This listens for data on the Mini and sends it verbatim to the Uno over i2c, where it gets printed to the serial monitor:

// This runs on the Uno.

#include <Wire.h>

#define I2C_PORT 0x13
#define BAUD_RATE 9600

void setup()
{
  Serial.begin(BAUD_RATE);
  Serial.println("Uno ready.");
  Wire.begin(I2C_PORT);
  Wire.onReceive(OnReceive);
}

void loop()
{
}

void OnReceive(int numberOfBytes)
{
  while (Wire.available())
  {
    Serial.write(Wire.read());
  }
}
// This runs on the Mini.

#include <Wire.h>

#define I2C_PORT 0x13
#define BAUD_RATE 4800
#define SERIAL_SETTING SERIAL_8N2
#define BUFFER_SIZE 1000

byte* buffer = new byte[BUFFER_SIZE];

void setup()
{
  Serial.begin(BAUD_RATE, SERIAL_SETTING);
  Wire.begin();
  Wire.beginTransmission(I2C_PORT);
  Wire.write("\r\nMini ready.\r\n");
  Wire.endTransmission();
}

void loop()
{
}

void serialEvent()
{
  Wire.beginTransmission(I2C_PORT);
  int bytesRead = 0;
  while (Serial.available())
  {
    buffer[bytesRead++] = Serial.read();
    if (bytesRead == BUFFER_SIZE)
    {
      Wire.write(buffer, BUFFER_SIZE);
      bytesRead = 0;
    }
  }
  if (bytesRead)
  {
    Wire.write(buffer, bytesRead);
  }
  Wire.endTransmission();
}

The output looks like this:

Uno ready.
Mini ready.
:ËÒòÜ&ëtm~c¸ln"ÃâÜN#ÒÃâÜN£Ðx...etc...

I'm not familiar with the Wire library. The fact that the message "Mini ready" appears suggests it is working properly.

I presume you cannot change the GPS to the more normal 8N1 protocol? If you could you could use Software Serial - at least for testing.

I presume you don't have a Mega, Leonardo or Micro with a spare Hardware Serial port.

I would be tempted to reduce the buffer size from 1000 bytes to 32 bytes to see if that makes a difference. 1000 bytes may be overloading something. For initial testing don't worry about losing data.

Is there a terminating character (perhaps a linefeed) at the end of each GPS message? if so I would use the 2nd example in Serial Input Basics to receive the messages.

Are you sure 8N2 is necessary? It is unusual. Have you tried 8N1?

Post a link to the datasheet for the GPS device.

...R

Robin2: Post a link to the datasheet for the GPS device.

Doh! OK, that set me on the right track. This is the closest thing to a datasheet I've been able to find. Anyway, the pinout lists a TTL TX line and an RS232 TX line. Both of them generate a signal that that you can read through the Arduino's data lines, so softserial works and my timing experiment worked, but only one of them is readable by the UART.

Thanks.