SoftwareSerial and NMEA question

I'm trying to organize datalogging and RTTY transmission for my balloon project

void loop() {  

  get_data(); //Getting data  GPS
  
  sd_write_log(); 
    
  send_telemetry(); //RTTY
}

void get_data()
{
  //Get GPS data
  bool newData = false;
  unsigned long chars;
  unsigned short sentences, failed;

    unsigned long startTime = millis();
    
    while (1) {
    // Make sure data is available to read
    if (gpsSerial.available()) {
      char c = gpsSerial.read();
                 
      if(gps.encode(c))
        newData = true;
     }
    // Timeout if no valid response in 1 seconds
    if (millis() - startTime > 990) {
      break;
    }
    }

  
  if (newData) //reading GPS variables from TinyGPS library
  {
      //    float flat, flon;
      //    unsigned long age;
      gps.get_datetime(&date, &time, &fix_age);
      gps.f_get_position(&flat, &flon, &ffix_age);
      faltitude = gps.f_altitude();
      fspeed = gps.f_speed_kmph();
      gps.stats(&chars, &sentences, &failed);
  }

My RTTY transmission take some time (15-20 seconds) to complete, after sending telemetry via send_telemetry() function the loop is starting from the begining. The problem is that any time the get_data() function is reading data from GPS the RX buffer already have some incomplete NMEA sentences in it, so it cause some GPS decoding errors (around 7-10 percents from all received sentences).

What is the best way to organize reading NMEA from GPS?

Program can read RX buffer only one time per 15-20 second, not in sync with GPS, cause other time Arduino is busy doing RTTY transmission

Thank you in advance!

Does the arduino have any spare time in the send telemetry function it could use to be reading the GPS?

wildbill: Does the arduino have any spare time in the send telemetry function it could use to be reading the GPS?

Unfortunately no( When transmitting all the time arduino run this function:

void rtty_txbit (int bit)
{
  if (bit)
  {
    // high
    //digitalWrite(RADIOPIN, HIGH);  //For NTX2
    tone(RTTY_PIN, MARK);
  }
  else
  {
    // low
    //digitalWrite(RADIOPIN, LOW);  //For NTX2
    tone(RTTY_PIN, SPACE);

  }

  //delayMicroseconds(3370); // 300 baud
  delayMicroseconds(10000); // For 50 Baud uncomment this and the line below. 
  delayMicroseconds(10150); // You can't do 20150 it just doesn't work as the
                            // largest value that will produce an accurate delay is 16383
                            // See : http://arduino.cc/en/Reference/DelayMicroseconds
                            
  noTone(RTTY_PIN);                          
}

in this case timing is important

May be there is the way to clear softserial RX buffer and then wait for new NMEA data to arrive? Parts of old NMEA data in the buffer are confusing TinyGPS library

Totally a different direction: can you use a standalone ATMEGA328 chip to read the GPS and provide the arduino readings upon request, via its hardware serial?

liudr: Totally a different direction: can you use a standalone ATMEGA328 chip to read the GPS and provide the arduino readings upon request, via its hardware serial?

Curently i am thinking about it. Want to use to arduinos: one for parsing NMEA, writing SD, reading sensors as slave device, and another arduino as master generating RTTY tone, requesting another arduino via i2c or serial for required data...

You think it's a better way to handle all this tasks?

atjnb9: Unfortunately no(

Yes it does; it is spending most of the time there in delayMicroseconds(). There are various ways you could make use of that time.

If you can get loop() to run fast enough (relative to your pulse timing accuracy) then you could restructure this to run asynchronously - I doubt that you will get it to run fast enough, though.

You can replace delayMicroseconds() with a call to a function that delays for the same duration, but checks for and reads any input received from the GPS at regular intervals while it's doing it. (Here you would also consolidate your multiple calls to delayMicroseconds() into a single call for the total delay duration.)

I expect you'll find that the problem with the GPS data is that the receive buffer is overflowing - you only need to read it frequently enough to avoid that, you don't need to pick up every character. Even just handling one GPS character per transmitted bit would probably solve your problem, and you have ample time for that.

The way I'd implement the new delay function would be to read the current time at the start, do the GPS serial data handling, and then spin re-reading the end time until the required interval had elapsed. If the delay time is long, you could repeat that logic as many times as you want, for example once per ms, once per 10 ms or whatever gave you enough time to handle the incoming GPS data without compromising your output timing accuracy.

I suppose the RTTY is sensitive to delays during transmission but the starting point of RTTY is not, right? Say if I want to send out RTTY and I can afford a few milliseconds before deciding on sending and actually sending? If this is the case, I will still run the GPS on the main arduino and have another arduino or a standalone chip run RTTY. This way main arduino tells standalone chip what to send via RTTY and goes right back to feeding GPS. The standalone chip sends the message via RTTY without anything bugging it. It can also accept request to store things to SD card. Have them talk via serial. Arduino serial send is interrupt driven. As long as you don't send data more than the size of send buffer, your main arduino calls serial.print() and returns immediately to do some more NMEA reading.

You could organize it so that the RTTY is transmitted in an interrupt routine using a timer. The GPS can then be read in the loop() function.

Pete