GPS and COMPASS

Hello everyone, with an arduino nano, a neo-6 GPS sensor, a GY-271 (QMC5883L) magnetic sensor and a 128x64 OLED screen I would need to see altitude, speed and compass degrees on the screen, I think I wrote the code quite well , but I don't see the gps data on the screen (the compass works instead). I connected the gps to pins D4 and D5, while the GY-271 and the screen have common SDA and SCL pins and on port A4 and A5.
Can you help me, please show the GPS data.
Thank you

This is my code

// I2C Library
#include <Wire.h>
// QMC5883L Compass Library
#include <QMC5883LCompass.h>
// U8g Library
#include <U8glib.h>
// TinyGPS++ Library
#include <TinyGPS++.h>

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);

TinyGPSPlus gps;
QMC5883LCompass compass;

void setup() {
  // Initialize the serial port.
  Serial.begin(9600);
  // Initialize I2C.
  Wire.begin();
  // Initialize the Compass.
  compass.init();
  // Initialize the OLED display.
  u8g.begin();
}

void loop() {
  int x, y, z;
  float heading, headingDegrees, speed, altitude;

  // Read compass values
  compass.read();

  x = compass.getX();
  y = compass.getY();
  z = compass.getZ();

  // Calculate the heading in degrees
  heading = atan2(y, x);
  if (heading < 0) {
    heading += 2 * PI;
  }
  headingDegrees = heading * 180 / PI;

  // Read GPS values
  while (Serial.available() > 0) {
    if (gps.encode(Serial.read())) {
      if (gps.location.isValid()) {
        // Get the speed in kilometers per hour.
        speed = gps.speed.kmph();
      }
      if (gps.altitude.isValid()) {
        // Get the altitude in meters.
        altitude = gps.altitude.meters();
      }
    }
  }

  Serial.print("X: ");
  Serial.print(x);
  Serial.print("   Y: ");
  Serial.print(y);
  Serial.print("   Z: ");
  Serial.print(z);
  Serial.print("   Heading: ");
  Serial.print(headingDegrees);
  Serial.println(" degrees");

  Serial.print("Speed: ");
  Serial.print(speed);
  Serial.print(" km/h   Altitude: ");
  Serial.print(altitude);
  Serial.println(" m");

  // Print the heading, speed, and altitude to the OLED display.
  u8g.firstPage();
  do {
    u8g.setFont(u8g_font_profont15);
    u8g.drawStr(80, 15, String(headingDegrees).c_str());
    u8g.drawStr(30, 25, String(speed).c_str());
    u8g.drawStr(10, 55, String(altitude).c_str());
  } while (u8g.nextPage());

  delay(1000);
}

you miss the gpsSerial implementation.
it does not feed data because you did not declare where should tinygps look.

here is the example code you need to consider reading, it is from lastminuteengineering.com

code goes here...

#include <TinyGPS++.h>
#include <SoftwareSerial.h>

// Choose two Arduino pins to use for software serial
int RXPin = 2;
int TXPin = 3;

int GPSBaud = 9600;

// Create a TinyGPS++ object
TinyGPSPlus gps;

// Create a software serial port called "gpsSerial"
SoftwareSerial gpsSerial(RXPin, TXPin);

void setup()
{
  // Start the Arduino hardware serial port at 9600 baud
  Serial.begin(9600);

  // Start the software serial port at the GPS's default baud
  gpsSerial.begin(GPSBaud);
}

void loop()
{
  // This sketch displays information every time a new sentence is correctly encoded.
  while (gpsSerial.available() > 0)
    if (gps.encode(gpsSerial.read()))
      displayInfo();

  // If 5000 milliseconds pass and there are no characters coming in
  // over the software serial port, show a "No GPS detected" error
  if (millis() > 5000 && gps.charsProcessed() < 10)
  {
    Serial.println("No GPS detected");
    while(true);
  }
}

void displayInfo()
{
  if (gps.location.isValid())
  {
    Serial.print("Latitude: ");
    Serial.println(gps.location.lat(), 6);
    Serial.print("Longitude: ");
    Serial.println(gps.location.lng(), 6);
    Serial.print("Altitude: ");
    Serial.println(gps.altitude.meters());
  }
  else
  {
    Serial.println("Location: Not Available");
  }
  
  Serial.print("Date: ");
  if (gps.date.isValid())
  {
    Serial.print(gps.date.month());
    Serial.print("/");
    Serial.print(gps.date.day());
    Serial.print("/");
    Serial.println(gps.date.year());
  }
  else
  {
    Serial.println("Not Available");
  }

  Serial.print("Time: ");
  if (gps.time.isValid())
  {
    if (gps.time.hour() < 10) Serial.print(F("0"));
    Serial.print(gps.time.hour());
    Serial.print(":");
    if (gps.time.minute() < 10) Serial.print(F("0"));
    Serial.print(gps.time.minute());
    Serial.print(":");
    if (gps.time.second() < 10) Serial.print(F("0"));
    Serial.print(gps.time.second());
    Serial.print(".");
    if (gps.time.centisecond() < 10) Serial.print(F("0"));
    Serial.println(gps.time.centisecond());
  }
  else
  {
    Serial.println("Not Available");
  }

  Serial.println();
  Serial.println();
  delay(1000);
}

also here is the link if you want to read the whole article.

All lot of code written for the TinyGPS++ library, including its own examples, does not use gps.encode() in an optimum way.

A typical GPS puts out around 8 different NMEA sentences once per second. Only two of these GPGGA and GPRMC are used by the TinyGPS++ library to provide the fix information.

So why oh why do code writers assume that when gps.encode() returns true, there is new data to display or act on ?

Most of the time the GPS location data will not have changed, so why deliberatly slow the program down by printing the same data to the Serial monitor, or a display, when nothing has changed ?

Thanks, now I'm studying it, I'm a beginner with the code

Well, I have to study it again to optimize the code, but I don't understand why I can't see the gps and compass data together.

Start at the begining, its much easier to identify issues that way.

Remove all the compass and display code.

Get the GPS code working, with GPS on a software serial port. Set the baud rate for Serial to 115200. Set only the minimum stuff to print to serial monitor.

When that is working OK and reliable;

Add the display code.

Add the compass code.

Thanks for the advice, I was just trying, also thanks to ChatGPT

The fact is that if I disconnect the compass sensor the gps works, if I leave it connected (to the I2C display pins) it doesn't work.

ChatGPT gets its answers from this forum.

1 Like

I used ChatGPT to fix the code

And the fixed code is?...

starting from the working compass code I added the gps and even after correcting it with ChatGPT I don't see the GPS data on the screen or on the serial plotter

#include <Wire.h>
#include <QMC5883LCompass.h>
#include <U8g2lib.h>
#include <SoftwareSerial.h>
#include <TinyGPS++.h>

#define rxPin 5
#define txPin 4
SoftwareSerial mygps(rxPin, txPin);
TinyGPSPlus gps;


U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0);

QMC5883LCompass compass;

void setup() {

  // Initialize the serial port.
  Serial.begin(9600);

  mygps.begin(9600);

  // Initialize I2C.
  Wire.begin();
  // Initialize the Compass.
  compass.init();
  // Initialize the OLED display
  u8g2.begin();
}

void loop() {


  boolean newData = false;
  for (unsigned long start = millis(); millis() - start < 1000;)
  {
    while (mygps.available())
    {
      if (gps.encode(mygps.read()))
      {
        newData = true;
      }
    }
  }

  //If newData is true
  if (newData == true)
  {
    newData = false;

    if (gps.location.isValid() == 1)
    {
      u8g2.setFont(u8g2_font_fur11_tr);
      u8g2.setCursor(40, 350);
      u8g2.print(gps.speed.kmph());

}
{



      int x, y, z;

      // Read compass values
      compass.read();

      x = compass.getX();
      y = compass.getY();
      z = compass.getZ();

      // Calculate the heading in degrees
      float heading = atan2(y, x);
      if (heading < 0) heading += 2 * PI;
      float headingDegrees = heading * 180 / M_PI;

      Serial.print("X: ");
      Serial.print(x);
      Serial.print("   Y: ");
      Serial.print(y);
      Serial.print("   Z: ");
      Serial.print(z);
      Serial.print("   Heading: ");
      Serial.print(headingDegrees);
      Serial.println(" degrees");
      Serial.print(gps.altitude.meters());
      Serial.println(" SPD");

      // Print the heading to the OLED display
      u8g2.clearBuffer();
      u8g2.setFont(u8g2_font_fur14_tr);
      u8g2.setCursor(0, 18);
      u8g2.print(headingDegrees);
      //u8g2.print(" degrees");
      u8g2.sendBuffer();




      delay(300);
    }
  }
}

Sooooo.... what did it "fix" exactly ?

I ask myself the same question

Oh no, ChatGPT.

Bye.

1 Like

Maybe syntax ?

Why escape #srnet I just looked for help, the code is correct for both the arduino compiler and ChatGPT

You need to decide who you will ask for help - a robot or living people. Don't mix

1 Like