If, Else Statement Only Running Else

Hi All, this is my first post here so bear with me as I try to adhere to the typical policies in place in computer engineering forums.

I have been borderline bullied in the past for "not doing sufficient research" before reaching out for help but I can confidently say I feel like I have scoured the internet on this one and require the help of some Arduino-junkies far more skilled than I.

Enough about the past - here is the rundown...

  1. MKR Wifi 1010
  2. Arduino MKR GPS Shield attached via included I2C cable
  3. Micro-USB cable for power and programming
  4. The GPS Shield WORKS
  5. The GPS Shield has been altered [thanks to a lovely post here] to post information every 200-300ms

The code:

#include <Arduino_MKRGPS.h>


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  while (!Serial) {
    ;
  }

  if (!GPS.begin()) {
    Serial.println("Failed to initilaize GPS!");
    while(1);
  }
  Serial.println("Configuring GPS refresh rate...");

  //  UBX-CFG-RATE (0x06 0x08) Navigation/Measurement Rate Settings
  //  See UBX-13003221 section 32.10.23.1
  byte payload[6];

  memset(payload, 0x00, sizeof(payload));

  uint16_t measRate = 250;    // ms between gps data publish  (min of 100)
  uint16_t navRate  =   1;    // ratio between measurements and nav solution calculations
  uint16_t timeRef  =   1;    // The time system to which measurements are aligned (0: UTC, 1:GPS, ...)

  // write out the unsigned shorts in little-endian form
  payload[0] = measRate & 0xff;   
  payload[1] = (measRate >> 8) & 0xff;   
  payload[2] = navRate & 0xff;
  payload[3] = (navRate >> 8) & 0xff;
  payload[4] = timeRef & 0xff;
  payload[5] = (timeRef >>8) && 0xff;

  GPS.sendUbx(0x06, 0x08, payload, sizeof(payload));

  Serial.println("  > done");
}

void loop() {
  if (GPS.available() > 0) {
    float speed = GPS.speed();
    int satellites = GPS.satellites();
    float latitude = GPS.latitude();
    float longitude = GPS.longitude();
    float course = GPS.course();
 
    Serial.print("Location: ");
    Serial.print(latitude, 7);
    Serial.print(", ");
    Serial.print(longitude, 7);
    Serial.println();
    
    Serial.println("Ground speed: ");
    float ms_speed = speed * 0.2777778;
    Serial.print(ms_speed);
    Serial.println(" m/s");
  }else{
    /*ANYTHING HERE IS RUN CONSTANTLY, REGARDLESS OF WHAT IT IS
    examples:
    Serial.println("I'm here!");
    float test_variable = 9.765;*/
  }
}

The goal of the program:

  1. If GPS data is available - print it (in a later version of the program, store it)
  2. If GPS data is not available - do something else (this "something else" is getting data from an accelerometer)
  3. Complete the above in a loop fashion

The problem:
If I put anything at all in the "else" portion of the if-else statement for GPS availability, it only runs the "else" portion. My best guess was that while the else statement was running, GPS data became available and I suppose the Ardunio missed it. This was proven wrong when I realized the true speed that the if statement was running at and the time required to run the "else" portion.

I'm really lost on this one. I don't mind being shown a massive oversight of mine, in fact, I highly encourage it.

Thanks in advance...

What is the expected return value of gps.available()?

GPS.Available returns either "1" for data or "0" for no data. Essentially a boolean response...

Serial.print(GPS.available());

??

Then the question is why is it always returning 0, not why is the else always running.

Incredibly interesting response! It only prints 0. Nothing but 0. I re-introduced the if statement to make sure the GPS was functioning correctly, and it was. So the question truly is, to gibbobaz's point, why is it always returning 0?

Just to be clear. When the else statement is empty the .available() return value at the head of loop is >0, but when there is anything in the else block the return is always 0?

I don't know the answer because I am not familiar with the GPS hardware you are using, however, I have a suspicion of what the problem is.

First off, how does the GPS shield communicate with the Arduino? All the GPS modules I've seen (not many) output serial, but you suggest I2C, so which is correct?

Serial is glacial compared to what the processor can do, I2C is faster but even so the processor can still do an awful lot in the time it takes to get a complete message from a GPS receiver. So, I would expect that nearly every time loop goes around there would not be any GPS data available. I would expect that loop might go round 10000 times or even maybe 1000000 times before there was data available, you have to write code to take this into account.

Some places to learn are:
Serial Input Basics - updated - #11 (Even if it is I2C the principals are the same)
Using Nextion displays with Arduino (Look how I handle data from a Nextion display, there is almost never any data there, but when there is my code captures it)
Demonstration code for several things at the same time (Understand that and you will understand how to capture incoming data that appears briefly)

None of the above directly answers your questions but all of them contribute to what you need to know to answer the question yourself.

Good luck.

1 Like

That is correct. If the else statement is empty, keeping in mind it still exists, there are no problems. If the else statement has something simple like Serial.println("I'm here!"); in it, all you see is "I'm here!" No data from the GPS whatsoever.

What about if the else statement has the simple variable assignment

byte x = 1;
or possibly if the compiler is going to ignore this
unsigned long x = x+1;

As stated,

I would expect that loop might go round 10000 times or even maybe 1000000 times before there was data available, you have to write code to take this into account.

Serial printing in the else statement will fill an output buffer, and I believe that the program can block.

It works! Amazing. I suppose I have to figure out how to get data selectively now.

1 Like

Thanks for all the helpful links! Truly appreciate it. To answer your question for anyone coming across this in the future, yes, it is I2C...at least according to the product page

It interfaces with Arduino boards either through a serial interface, when used with headers and put on top of a MKR board, or through an I2C interface and a dedicated ESLOV cable supplied as bundle.

I am using the ESLOV cable and have connected it directly to the MKR's port.

1 Like

OK, it makes no significant difference to my answer, the key point is that most of the time there won't be any data there and you have to consider this.

What exactly do you want to place in the else block?

You can indeed have some serial printing if you put it on a millis() timer so that the output buffer can empty and not block the program.

Here is the code from the near final version.

Noting that variables like "speed" and "satellites" are declared earlier.

    if(GPS.available()) {
      speed = GPS.speed();
      satellites = GPS.satellites();
      latitude = GPS.latitude();
      longitude = GPS.longitude();
      course = GPS.course();
      boat_speed = speed * 0.2777778;
    }else{
       //Accelerometer...
      acceleration_x = ((myIMU.readFloatAccelY() - tilt_calibration) * 9.8);
      acceleration_y = ((myIMU.readFloatAccelY() - height_calibration) * 9.8);
      acceleration_z = ((myIMU.readFloatAccelZ() - roll_calibration) * 9.8);
      //Gyroscope
      gyro_x = (myIMU.readFloatGyroX());
      gyro_y = (myIMU.readFloatGyroY());
      gyro_z = (myIMU.readFloatGyroZ());
    }

What are you trying to do?

It looks like available polls to see if a sentence has come in from the GPS and then parses it. That may take a little while, so you're probably getting accelerometer data rather more frequently. Is that necessary?

This device is an embedded device for athletic use.

The end goal is this:

  1. Record accelerometer and gyroscopic data every 100ms.
  2. Record GPS data as often as possible

I would think that the GPS block needs to stand on its own so that it executes whenever .available() and the accellerometer/gyroscope block should be on a separate millis() timer. How long does it take to read the accel/gyro data? Is the max frequency possibly less than than 10Hz?

1 Like

You are my hero.