Storing very first input

I was looking to take in latitude and longitude data and set the very first reading as the origin point on an led. All other location readings would be displayed on the screen in respect to the first stored location.

This is what I tried first:

int m = 0;

void loop(){
if(m=0){
   origin_lat = int_lat;
   origin_long = int_long;
   m++;
}
}

But the values of origin_lat and origin_long equal 0 and don't match int_lat or int_long. Is there an easier way to go about this?

But the values of origin_lat and origin_long equal 0 and don't match int_lat or int_long.

How do you know this? The code snippet you posted looks correct. The rest of the code must be where the problem lies. Care to post more (or, better yet, all) of it?

if(m==0)

:slight_smile:

I changed the stupid double equals error, but i still have the same results.

#include <OLED320.h>
#include <string.h>
#include <ctype.h>
#include <print.h>

 int rx1Pin = 19;                    // RX1 PIN 
 int tx1Pin = 18;                    // TX1 TX
 int byteGPS=-1;
 char linea[300] = "";
 char arguments[13][11];
 float flt_arguments[13];
 char comandoGPR[7] = "$GPRMC";
 int cont=0;
 int bien=0;
 int conta=0;
 int indices[13];
 float latitude, longitude, lat_rad, long_rad;
 float origin_lat, origin_long, int_lat, int_long;
 int m = 0;

OLED320 LED;

void setup() {
pinMode(rx1Pin, INPUT);
pinMode(tx1Pin, OUTPUT);
Serial1.begin(4800);
Serial2.begin(9600);
Serial.begin(19200);
   //delay(100);
for (int i=0;i<300;i++){       // Initialize a buffer for received data
  linea[i]=' ';
}

Serial2.print(0x55,BYTE);
delay(1000);

LED.LED_Clear();
delay(100);

}

void loop() {
  gps();
}

void gps(){
  byteGPS=Serial1.read();         // Read a byte of the serial port
  if (byteGPS == -1) {           // See if the port is empty yet
     delay(100); 
  } else {
     linea[conta]=byteGPS;        // If there is serial port data, it is put in the buffer
     conta++;                      
     //Serial.print(byteGPS, BYTE); 
     if (byteGPS==13){            // If the received byte is = to 13, end of transmission
       cont=0;
       bien=0;
       for (int i=1;i<7;i++){     // Verifies if the received command starts with $GPR
         if (linea[i]==comandoGPR[i-1]){
           bien++;
         }
       }
       if(bien==6){               // If yes, continue and process the data         
           char* str = linea;              //direct linea char array to str pointer array
           char seperator = ',';
           int count = 0, index = 0, sIndex = 0;
           int theSize = 299;
           arguments[index][count] = '\0';  // clear first argument before starting
           flt_arguments[index] = '\0';
        
           while (theSize > sIndex + 1){
             if (*str != seperator){
               arguments[index][count] = *str;  //store array sections into argument arrays
             } 
             else {
               arguments[index][count] = '\0';
             }
             *str++;
             count++;
             sIndex++;

             if (*str == seperator){
               *str++;                          // jump over the separator
               count = 0;
               index++;
               arguments[index][count] = '\0';  // clear argument before starting
             }
             
           }          
                            
          for(int i=1; i<10; i++){
            flt_arguments[i] = atof (arguments[i]);      //convert character in argument array into floating point
          }
          
          latitude = flt_arguments[3];      //assign latitude floating point array to a single floating point variable
          longitude = flt_arguments[5];     //assign longitude floating point array to a single floating point variable 
          int_lat = latitude*10000;
          int_long = longitude*10000;
          
          Serial.print("INT LAT: ");
          Serial.println(int_lat);
          Serial.print("INT LONG: ");
          Serial.println(int_long);
          Serial.println("________");
          
          if(m==0){
            origin_lat = int_lat;
            origin_long = int_long;
            m++;
          }

          getpoint(origin_lat, origin_long, int_lat, int_long);
       }
       conta=0;                    // Reset the buffer
       for (int i=0;i<300;i++){    //  
         linea[i]=' ';             
       }                 
     }
   }
}

void getpoint(float origin_lati, float origin_longi, float current_lat, float current_long){
  int ya, yb;
  float tempx, tempy;
  tempx = (current_lat - origin_lati);      //set original coordiates at (0,0) 
  tempy = (current_long - origin_longi);
  int x = (int)(tempx*10);
  int y = (int)tempy;
  
  if(y<256){
    ya = 0;
    yb = y;
  }
  else{
    ya = 1;
    yb = y-256;
  }
     
  Serial.print("origin_lat: ");
  Serial.println(origin_lati);
  Serial.print("origin_long: ");
  Serial.println(origin_longi);
  Serial.print("current_lat: ");
  Serial.println(current_lat);
  Serial.print("current_long: ");
  Serial.println(current_long);
  Serial.print("tempx: ");
  Serial.println(tempx);
  Serial.print("tempy: ");
  Serial.println(tempy);
  Serial.print("x: ");
  Serial.println(x);
  Serial.print("y: ");
  Serial.println(y);
  Serial.println("_________");
  
}

There are some things that could be changed in this sketch:

flt_arguments[index] = '\0';

flt_arguments is an array of floats. Storing a NULL in a float does not make sense. Storing 0.0 does. The end result might be the same, but storing a NULL in a float looks weird.

    linea[conta]=byteGPS;        // If there is serial port data, it is put in the buffer
    conta++;

So, linea[0] thru linea[n] are set. Then,

      for (int i=1;i<7;i++){     // Verifies if the received command starts with $GPR
        if (linea[i]==comandoGPR[i-1]){
          bien++;
        }
      }

linea[1] thru linea[6] are compared to comandoGPR[0] thru comandoGPR[5]. Why is linea[0] ignored?

Why are you storing each token in an array, as well as the token converted to a float? You never use the character array again.

Why are you not using strtok to tokenize the input string? It's optimized for just this sort of thing.

         int_lat = latitude*10000;
         int_long = longitude*10000;

Why are you multiplying latitude and longitude by 10000?

 if(y<256){
   ya = 0;
   yb = y;
 }
 else{
   ya = 1;
   yb = y-256;
 }

What's this code for? These values are not used.

What does your output look like?

@mjaredwilson: Please post code using the [#] button in the forum post editor :slight_smile:

I am working off of the GPS tutorial here: Arduino Playground - GPS

The latitude and Longitude values are given for example as 2907.3422 and 09607.3453 so I was attempting to convert these into integers. The (int)latitude approach wasn't working correctly.

I know the values because I am printing them on the Serial Monitor.

And the if else statement storing values into ya and yb split the y value into two parts. I am displaying a dot on a 4D OLED display and the coordinates of the dot have to be sent a byte at a time.

here is the complete code:
http://people.tamu.edu/~jwil04/dir/main_parallax.pde

Oh and i changed the if statement to:

if(m==0)

I asked a number of questions. You danced around and gave partial answers to half the questions. I'll try again.

What is the purpose of saving each token in an array? You never use the array after you convert the value in the array to a float. Just convert the token to a float and store it in the float array.

Where are you checking that there is room in the character array for the character you are adding?

Where do you NULL terminate the character array entries?

Why are you not using strtok? The strtok function has been around for years. It's highly optimized, professionally written and thoroughly tested. It will make your job so much easier if you quit trying to re-invent the strtok function.

If you do nothing else, try printing m along with the other output. Maybe that will give you (and us) a clue.

Well, I am just working off of the example code I found and it has been working so I didn't try to change up the code and implement the strtok function.

I printed the value of m in the previous post.

I am not sure when to terminate the character array entries.

I think that you are overwriting memory somewhere. Notice that m never changes. Since you have an m++ statement, it should. Since it doesn't, it means that it is being stepped on by something else. That something else is most likely happening in your string parsing code.

There is no reason to save the string twice. First you collect all the data in a string. Then, you parse it, and save all the tokens in an array. Then, you convert some of the tokens in that array to floats. There are all kinds of possibilities for where you could be overwriting memory.

All of them could be eliminated by using strtok to do the parsing. It returns a pointer to a token, managing allocation of space to hold that token. Then, all you need to do is convert that token to a float, and store the float in the float array.

If you persist in writing your own parser, fine. But, I think you need to understand what you are doing a lot more than you do.

You have no error checking. A token could be 15 characters long, and you happily stuff than into an array that is sized to hold 11 or 13, counting the terminating NULL, which you never add.

Then, you call atof. The atof function expects its input to be a string. You are supplying an array of characters.

There is a subtle difference between a string and an array of characters. The difference is that a string is an array of characters that is NULL terminated.

I'll keep harping on this because it is so important. You can not expect reasonable results if you supply bad input. Google "GIGO". You're providing the first part, and getting the second part.

I am not sure when to terminate the character array entries./quote]

Then, you should be using a function or library that does.

Ok so how about something along these lines...

void gps(){
  byteGPS=Serial1.read();         // Read a byte of the serial port
  if (byteGPS == -1) {           // See if the port is empty yet
     delay(100); 
  } else {
     linea[conta]=byteGPS;        // If there is serial port data, it is put in the buffer
     conta++;                      
     //Serial.print(byteGPS, BYTE); 
     if (byteGPS==13){            // If the received byte is = to 13, end of transmission
       cont=0;
       bien=0;
       for (int i=1;i<7;i++){     // Verifies if the received command starts with $GPR
         if (linea[i]==comandoGPR[i-1]){
           bien++;
         }
       }
       if(bien==6){               // If yes, continue and process the data           
               char delims[] = ",";
               char* result1 = NULL;
               char* result2 = NULL;
               char* result3 = NULL;
               
               result1 = strtok(linea, delims);
               result2 = strtok(NULL, delims);
               result3 = strtok(NULL, delims);
}

giving:
result1 = "$GPRMC"
result2 = "123519"
result3 = "A"

for example.

$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A

So far, so good. If you know what the order of the tokens is, there's no reason to store pointers to them individually, if you never need the string representation of the value again.

For instance, result1 is a pointer that points to the string "$GPRMC". Do you care about result1 later? If not, do something like this:

char *token;
int tokNum;

token = strtok(linea, ",");
if(strcmp(token, "$GPRMC") == 0)
{
   // Good string. Tokenize the rest...
   tokNum = 0;
   token = strtok(NULL, ",");
   while(token)
   {
      tokNum++;

      // Decide whether to save or convert the token, or not
      switch(tokNum)
      {
          case 1: // token = "123519"
             // Maybe do something
             break;
          case 2: // token = "A"
             // maybe do something
             break;
          // More case statements
      }
      token = strtok(NULL, ",");
   }
}

Thanks Paul! It works great now. I used this code:

if(bien==6){               // If yes, continue and process the data         
          char *token;
          int tokNum;
          char delims[] = ",";
          char *time_char = NULL;
          char *fix_char = NULL;
          char *lat_char = NULL;
          char *latdir_char = NULL;
          char *long_char = NULL;
          char *longdir_char = NULL;
          char *date_char = NULL;

          token = strtok(linea, delims);
            tokNum = 0;
            while(token){
            // Decide whether to save or convert the token, or not
            switch(tokNum){
                case 1:                     // token = time
               time_char = token;
               break;
              case 2:                     // token = fix
               fix_char = token;
               break;
                case 3:                     // token = latitude
               lat_char = token;
               break;
                case 4:                     // token = latitude direction
               latdir_char = token;
               break;
                case 5:                     // token = longitude
               long_char = token;
               break;
                case 6:                     // token = longitude direction
               longdir_char = token;
               break;                
                case 9:                     // token = fix
               date_char = token;
               break;     
            }
            token = strtok(NULL, delims);
              tokNum++;
            }  
          time = atof(time_char);
          latitude = atof(lat_char);
          latitude = latitude/100;
          longitude = atof(long_char);
          longitude = longitude/100;
          date = atof(date_char); 
}

I was also wondering the best way to truncate the latitude and longitude floats. The values have 8 numbers such as 4807.0385 and I want to multiply by 1000 to give 4807038.5 and round the number to 4807039.

Using:

latitude = atof(lat_char);
longitude = atof(long_char);
latitude = latitude*1000;
longitude = longitude*1000;  
int_lat = (int)latitude;
int_long = (int)longitude;
          
          Serial.print("latitude: ");
          Serial.println(latitude);
          Serial.print("longitude: ");
          Serial.println(longitude);
          Serial.print("INT LAT: ");
          Serial.println(int_lat);
          Serial.print("INT LONG: ");
          Serial.println(int_long);

I see:

latitude: 3037100.25
longitude: 9620388.00
INT LAT: 22444
INT LONG: -13404

Thanks!