gps speed based function issues

Hello,

i'm making a controller and gauge for a powered hydrofoil (aka 'wedge') I decided to take an easier approach right now and approximate the position based on time.

The gauge is nonlinear. The wedge has a 90 degree sweep. there is a section of it's travel that adversely affects the speed of the boat and the purpose of the hydrofoil itself. so for that area, I only need an indicator that it's traveling. Since i dont need to make finer adjustments, that portion of the sweep takes up less space on the gauge. Then there is a 'functional' area of about 15-20 degrees that occupies more then 90 degrees of the gauges travel.

i have the initial program running pretty well. my tests look pretty good but as soon as i introduce the gps and newsoftserial libraries i'm unable to figure out how to make them play nice.

I'm unsure if I'm even using the gps library the correct way, but the results are as follows: when i combine the gps program with mine; every second or so the gauge stutters during its travels when the wedge is being 'deployed', there is a delay from when the needle stops and when the relays switch off (delay relay switching). there is also a relay delay after i release the button. this should switch the relay off as soon as i release the button the speed based switching of the relays is erratic. It seems to randomly activate even when the gps is at rest on the table.

any help would be greatly appreciated.

// http://www.ladyada.net/make/gpsshield

// If using Arduino IDE prior to version 1.0,
// make sure to install newsoftserial from Mikal Hart
// http://arduiniana.org/libraries/NewSoftSerial/
#if ARDUINO >= 100
#include "Arduino.h"
#include "SoftwareSerial.h"
#else
#include "WProgram.h"
#include "NewSoftSerial.h"
#endif
// Use pins 2 and 3 to talk to the GPS. 2 is the TX pin, 3 is the RX pin
#if ARDUINO >= 100
SoftwareSerial mySerial = SoftwareSerial(2, 3);
#else
NewSoftSerial mySerial = NewSoftSerial(2, 3);
#endif

// Set the GPSRATE to the baud rate of the GPS module. Most 
#define GPSRATE 9600

// The buffer size that will hold a GPS sentence. They tend to be 80 characters long
// so 90 is plenty.
#define BUFFSIZ 90 // plenty big


// global variables
char buffer[BUFFSIZ]; // string buffer for the sentence
char *parseptr; // a character pointer for parsing
char buffidx; // an indexer into the buffer

// The time, date, location data, etc.
uint8_t hour, minute, second, year, month, date;
uint32_t latitude, longitude;
uint8_t groundspeed, trackangle;
char latdir, longdir;
char status;

#include <EEPROM.h>
#include <Bounce.h>
#include <Stepper.h>
#define BUTTON 8
Bounce bouncer = Bounce( BUTTON, 5 ); 

const int wedgepinLower = 10;
const int wedgepinRaise = 11;
const int analogInPin0 = A0;  // Analog input pin that the right fsr is attached to
const int analogInPin1 = A1;  // Analog input pin that the leftfsr is attached to
int wedgespeed = 10;        // value output to the PWM (analog out)
int speedsafe = 0;


int ADJUSTSPEED = 40;  //ADJUST THIS NUMBER TO ACCOUNT FOR THE AMOUNT OF TIME IT TAKES THE WEDGE TO GO FROM IT STOWED STATE TO ITS FUNCTIONAL STATE
int DEPLOYSPEED = 20;  //ADJUST THIS NUMBER TO ACCOUNT FOR THE SPEED OF THE WEDGE DURING IT'S ACTIVE STATE



int lfsr =0;
int rfsr =0;

//TIME
unsigned long time =0;
int needlepos =0;
int stepspeed =0;
int count =0;
long previousMillis = 0;       

// change this to the number of steps on your motor
#define STEPS (105)

// create an instance of the stepper class, specifying
// the number of steps of the motor and the pins it's
// attached to
Stepper stepper(STEPS, 4, 5, 6, 7);


void setup() {
  pinMode(13, OUTPUT);
  Serial.begin(9600);
  mySerial.begin(GPSRATE);
  pinMode(wedgepinLower, OUTPUT);  
  pinMode(wedgepinRaise, OUTPUT);  
  digitalWrite(wedgepinLower, HIGH);
  digitalWrite(wedgepinRaise, HIGH);
  pinMode(BUTTON, INPUT);     
  stepper.setSpeed(220);
  stepper.step(-650);  //sets the initial home position of the gauge
  stepper.setSpeed(ADJUSTSPEED);
}




uint32_t parsedecimal(char *str) {
  uint32_t d = 0;

  while (str[0] != 0) {
    if ((str[0] > '9') || (str[0] < '0'))
      return d;
    d *= 10;
    d += str[0] - '0';
    str++;
  }
  return d;
}

void readline(void) {
  char c;

  buffidx = 0; // start at begninning
  while (1) {
    c=mySerial.read();
    if (c == -1)
      continue;
    //      Serial.print(c);
    if (c == '\n')
      continue;
    if ((buffidx == BUFFSIZ-1) || (c == '\r')) {
      buffer[buffidx] = 0;
      return;
    }
    buffer[buffidx++]= c;
  }
}



void loop(){
  rfsr = analogRead(analogInPin0);            
  lfsr = analogRead(analogInPin1);            

// Lower Wedge
  if (needlepos >= 485)      {        //opens relays to stop the wedge when the gauge hits it's limit
    digitalWrite (wedgepinLower,LOW);
    digitalWrite (wedgepinRaise,LOW);
  }
  if ((rfsr > 1000)&&(needlepos < 485)){  // if the needle position is below the gauge marker this will allow the wedge to lower
    count++;
    if ((needlepos != 0)&&(count >5)){
      if (needlepos < 485){
        digitalWrite (wedgepinLower,LOW);
        digitalWrite (wedgepinRaise,HIGH);
      }
      stepper.step(wedgespeed);
      needlepos = needlepos + (wedgespeed);
    }
    if ((needlepos ==0)&&(count >30)){        // if the wedge is in it's retracted state, holding the button for a 30 count will move it into it's functional position
      digitalWrite (wedgepinLower,LOW);       // this will need to be only possible at speeds below 5 mph
      digitalWrite (wedgepinRaise,HIGH);
      stepper.setSpeed(DEPLOYSPEED);
      stepper.step(206);
      needlepos =206;
      stepper.setSpeed(ADJUSTSPEED);
    }
  }

  if ((lfsr > 1000)&& (needlepos >= 206)){  //opens relays to stop the wedge when it reaches it's highest functional limit
    count++;
    if (needlepos == 206){                // this stops the wedge from moving at it's highest position, regardless if the fsr is beeing pressed or not
      digitalWrite (wedgepinLower,LOW);
      digitalWrite (wedgepinRaise,LOW);
    }
    else if (count >5){                   //a slight delay to stop any false triggers
      if (needlepos >+ 206){
        digitalWrite (wedgepinLower,HIGH);
        digitalWrite (wedgepinRaise,LOW);
      }
      stepper.step(-wedgespeed);            
      needlepos = needlepos - wedgespeed;
    }
    if ((needlepos ==206)&&(count >30)){   //this was my attempt to trigger a speed based action.  see below in the gps area
      speedsafe =1;                        //i wanted this action (retracting the wedge) only possible between certain speeds
    }                                      // to initiate it after 1 mph so it doesn't hurt anyone that could be behind the boat and under 10mph to avoid stress on the mechanics
  }
  if ((lfsr ==0 )&& (rfsr == 0)){          // this area sets the counter to 0 when nothing is being pressed
    count = 0;


    }
    digitalWrite (wedgepinLower,LOW);
    digitalWrite (wedgepinRaise,LOW);
  }


  /////////////////////////////GPS/////////////////////////
  uint32_t tmp;

  //  Serial.print("\n\rRead: ");
  if (speedsafe == 1){                      // here is the function that i want to be triggered past a certain speed
    readline();
    if (groundspeed > 0){      
      digitalWrite (wedgepinLower,HIGH);
      digitalWrite (wedgepinRaise,LOW);
      stepper.setSpeed(DEPLOYSPEED);
      stepper.step(-206);
      needlepos =0;
      stepper.setSpeed(ADJUSTSPEED);
     groundspeed =0;
     speedsafe =0;
    }
  }
  // check if $GPRMC (global positioning fixed data)
  if (strncmp(buffer, "$GPRMC",6) == 0) {

    // hhmmss time data
    parseptr = buffer+7;
    tmp = parsedecimal(parseptr);
    hour = tmp / 10000;
    minute = (tmp / 100) % 100;
    second = tmp % 100;

    parseptr = strchr(parseptr, ',') + 1;
    status = parseptr[0];
    parseptr += 2;

    // grab latitude & long data
    // latitude
    latitude = parsedecimal(parseptr);
    if (latitude != 0) {
      latitude *= 10000;
      parseptr = strchr(parseptr, '.')+1;
      latitude += parsedecimal(parseptr);
    }
    parseptr = strchr(parseptr, ',') + 1;
    // read latitude N/S data
    if (parseptr[0] != ',') {
      latdir = parseptr[0];
    }

    //Serial.println(latdir);

    // longitude
    parseptr = strchr(parseptr, ',')+1;
    longitude = parsedecimal(parseptr);
    if (longitude != 0) {
      longitude *= 10000;
      parseptr = strchr(parseptr, '.')+1;
      longitude += parsedecimal(parseptr);
    }
    parseptr = strchr(parseptr, ',')+1;
    // read longitude E/W data
    if (parseptr[0] != ',') {
      longdir = parseptr[0];
    }


    // groundspeed
    parseptr = strchr(parseptr, ',')+1;
    groundspeed = parsedecimal(parseptr);

    // track angle
    parseptr = strchr(parseptr, ',')+1;
    trackangle = parsedecimal(parseptr);


    // date
    parseptr = strchr(parseptr, ',')+1;
    tmp = parsedecimal(parseptr);
    date = tmp / 10000;
    month = (tmp / 100) % 100;
    year = tmp % 100;

    Serial.print("\n\tTime: ");
    Serial.print(hour, DEC); 
    Serial.print(':');
    Serial.print(minute, DEC); 
    Serial.print(':');
    Serial.println(second, DEC);
    Serial.print("\tDate: ");
    Serial.print(month, DEC); 
    Serial.print('/');
    Serial.print(date, DEC); 
    Serial.print('/');
    Serial.println(year, DEC);
    Serial.print("groundspeed:  ");
    Serial.println (groundspeed, DEC);
  }
  ////////////////////////////END GPS//////////////////////////

}
while (1) {
  c=mySerial.read();
  if (c == -1)
      continue;

It seems to me that this will block while it is reading a number line. How about reading non-blocking?

http://www.gammon.com.au/serial