NMEA multiplexer & logger

Post here about your Arduino projects, get help - for Adafruit customers!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
rgarside
 
Posts: 3
Joined: Fri Jan 18, 2013 1:21 pm

NMEA multiplexer & logger

Post by rgarside »

I am building a device to multiplex two 4800 baud NMEA data streams, echo them to an output port and log them to an SD card. It is based on a Mega 2560 and the Adafruit Datalogger. The NMEA is interfaced through a MAX232 which connects to Serial1 and Serial2 on the Mega. The I2C connections to the Adafruit datalogger have been made by jumpers to the SDA and SCL pins on the Mega.

I have tested the device with a single data stream, and it works fine with the data connected either to port 1 or to port 2. When I connect two data streams, I run into corrupted data - I think this may be tied up with the size of the serial buffers, and the time taken to write to the SD card.

I am using Arduino 1.02 IDE.

Is there any way to increase the size of the serial buffers, or to clear the data quicker from them?

The code I started off with read a complete sentence from a port once it had data available. This approach probably blocks the process until the sentence has been received. I have tried to re-configure the code to read individual characters from each port as they become available, but I am having problems with this also.

Has anyone done anything comparable and found a fix?

Would an Arduino DUE be any better for this application?

Extracts from the code are shown below.

Code: Select all

//-------------------------------------------------------------------------- 
// Main loop segment
// Alternately checks ports 1 & 2, if data present reads and logs sentences.
void loop() 
{ 

  if(Serial1.available()) {
    readline1();
    logline();
    }
  
  if(Serial2.available()) {
    readline2();
    logline();
    } }
//-----------------------------------------------------------------------
void readline2(void) {
  
  buffidx = 0; // start at begninning
  while(1) {
      c=Serial2.read();
      if (c == -1)
        continue;
      if (c == '\n')
        continue;
      if ((buffidx == BUFFSIZ-1) || (c == '\r')) {
        buffer[buffidx] = 0;
        return;
      }
      buffer[buffidx++]= c;
  }
  
} 

//--------------------------------------------------------------------------

The readline1 routine is similar to the readline2 routine above. The logline routine checks the checksums and filters out unwanted sentences, and sends the wanted ones to a fileline routine for saving to the SD card. The buffer character arrays have a max size of 90.

User avatar
adafruit_support_mike
 
Posts: 67485
Joined: Thu Feb 11, 2010 2:51 pm

Re: NMEA multiplexer & logger

Post by adafruit_support_mike »

The code you posted will get stuck in the loop if Serial2.read() returns -1.. it will block until that channel sees more input. It only exits the loop when it fills the buffer or hits an "\r" character, and I can see that causing some strange behavior when you have two versions of the same code trading control of the processor.

Here's a version that will fall through and terminate the string if Serial2.read() doesn't see any input:

Code: Select all


void readline2 (void) {
    int buffidx = 0;
    int c = 0;
    
    do {
  //        skip newlines
        do {
            c = Serial2.read();
        } while ("\n" == c);

  /*        keep normal characters, but convert returns and 
            'end of input' tokens to zero
  */
        c = ((-1 == c) || ("\r" == c)) ? 0 : c;

    //      store the input
        buffer[ buffidx++ ] = c;

  /*        keep looping until we hit the buffer limit 
            or a convert-to-zero character
  */
    } while ((buffidx < BUFFSIZ) && (c));
    
  /*        write a zero to the end of the buffer.
            technically this is only necessary when the data
            extends all the way to the buffer limit, 
            but writing every time is cheaper than testing
            then writing.
  */
    buffer[ BUFFSIZ ] = 0;
    return;
}

rgarside
 
Posts: 3
Joined: Fri Jan 18, 2013 1:21 pm

Re: NMEA multiplexer & logger

Post by rgarside »

Thanks for the reply.

I have re-written the code along similar lines to those you suggested:-

Code: Select all

//-------------------------------------------------------------------------- 
// Main loop segment
// Alternately checks ports 1 & 2, if data present reads and logs sentences.
void loop() 
{ 
// read1:
  while(NewPort1.available()) {
      c1=NewPort1.read();
      if (c1 == -1) continue;
      if (c1 == '\n') continue;
      if ((buff1idx == BUFFSIZ-1) || (c1 == '\r')) {
        buff1[buff1idx] = 0; 
        strcpy(buffer, buff1); NewPort.print(buff1idx); NewPort.print("   ");NewPort.println(buffer);
        buffidx = buff1idx;  logline(); 
        buff1idx=0; continue;}
      buff1[buff1idx++]= c1;
    }

// read2:  
  while(NewPort2.available()) {
      c2=NewPort2.read();
      if (c2 == -1) continue;
      if (c2 == '\r') continue;
      if ((buff2idx == BUFFSIZ-1) || (c2 == '\n')) {
        buff2[buff2idx] = 0; 
        strcpy(buffer, buff2); NewPort.println(buff2idx);  
        buffidx = buff2idx; logline(); 
        buff2idx=0; continue;}
      buff2[buff2idx++]= c2;    
    } 
    
}
This improved things, but I still got failures that looked like buffer overflows particularly while writing the data to the SD card.

I have just included the SerialPort library so I can increase the buffer sizes, and to work with this I have had to change from the SD library to SdFat. I have just completed that and should be able to test it soon. I may be able to improve the SD write speed with SdFat too.

rgarside
 
Posts: 3
Joined: Fri Jan 18, 2013 1:21 pm

Re: NMEA multiplexer & logger

Post by rgarside »

I've tested this now and it works just fine. The SerialPort and SdFat libraries were just what was needed.

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino”