GPS not working with Teensy 4.1

I am trying to use multiple components with a Teensy 4.1. Those components are: Adafruit BMP280, LoRa SX, Ultimate Breakout GPS, Buzzer, as well as using a level shifter. The issue I am having is with the GPS module. When I try to use it, it doesn't return any characters. I am using the Tiny GPS ++ library.

Wiring:
(Teensy 4.1 - Gps)
- 5v - VIN
- GND - GND
- TX(01) - RX
- RX(00) - TX
(The TX and RX pins go through a level shifter from 3v to 5v)

Here is the code:

C++:
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>
#include <LoRa.h>
#include <SPI.h>
#include <TinyGPSPlus.h>
#include <SD.h>
//#include <SoftwareSerial.h>


//#define gpsSerial Serial1

// Define the LoRa frequency
const long frequency = 433E6; // Adjust according to your region's regulations


// Initialize the BMP280 sensor
Adafruit_BMP280 bmp;


// Initialize GPS
TinyGPSPlus gps;
static const int RX = 0, TX = 1;
static const uint32_t GPSBaud = 9600;
//SoftwareSerial ss(RX, TX);

// Setup LoRa with the specific CS and reset pins if needed
const int csPin = 10; // Change as per your LoRa module if not using the built-in SPI
const int resetPin = 9; // Set to your LoRa module's reset pin if any, or -1 if unused


const int buzzerPin = 2; // Buzzer connected to pin 2


File file; // Declare a File object for SD card operations


void setup() {
  Serial.begin(115200);
  Serial1.begin(GPSBaud);
 



  // BMP280 initialization
  if (!bmp.begin()) {
  Serial.println("Could not find a valid BMP280 sensor!");
  while (1);
  }


  // SD initialization using the built-in SD card slot
  if (!SD.begin(BUILTIN_SDCARD)) {
  Serial.println("SD Card Mount Failed");
  return;
  }


  // Create or open the file for logging
  file = SD.open("data.txt", FILE_WRITE);
  if (!file) {
  Serial.println("Failed to open file for writing");
  return;
  }
  file.println("Log Begin:");
  file.close();


  // LoRa initialization
  SPI.begin();
  LoRa.setPins(csPin, resetPin, 13); // Set LoRa module pins
  if (!LoRa.begin(frequency)) {
  Serial.println("Starting LoRa failed!");
  while (1);
  }


  pinMode(buzzerPin, OUTPUT); // Initialize the buzzer pin as an output
}


void loop() {
 
  logData();
  Serial.print("Chars:");
  Serial.println(gps.charsProcessed(), 6);
  Serial.print("Sent:");
  Serial.println(gps.sentencesWithFix(), 10);
  Serial.print("Err:");
  Serial.println(gps.failedChecksum(), 9);

  Serial.print("Temperature: ");
  Serial.print(bmp.readTemperature());
  Serial.println(" C");
  Serial.print("Pressure: ");
  Serial.print(bmp.readPressure() / 100.0F);
  Serial.println(" hPa");
  Serial.print("Approx. Altitude: ");
  Serial.print(bmp.readAltitude(1013.25)); // Standard sea-level pressure in hPa
  Serial.println(" m");
  Serial.print("Latitude: ");
  Serial.println(gps.location.lat(), 6);
  Serial.print("Longitude: ");
  Serial.println(gps.location.lng(), 6);
  Serial.print(", Degrees: ");
  Serial.println(gps.course.deg(), 2);
    
  delay(1000); // Adjust delay as needed
  }






void logData() {
  // Open the file for appending
  file = SD.open("data.txt", FILE_WRITE);
  if (!file) {
  Serial.println("Failed to open file for appending");
  return;
  }
  // Log temperature, pressure, and altitude from BMP280
  file.print("Temperature: ");
  file.print(bmp.readTemperature());
  file.println(" C");


  file.print("Pressure: ");
  file.print(bmp.readPressure() / 100.0F);
  file.println(" hPa");


  file.print("Approx. Altitude: ");
  file.print(bmp.readAltitude(1013.25)); // Standard sea-level pressure in hPa
  file.println(" m");


  // Log GPS data
  file.print("Latitude: ");
  file.println(gps.location.lat(), 6);
  file.print("Longitude: ");
  file.println(gps.location.lng(), 6);
  file.print(", Degrees: ");
  file.println(gps.course.deg(), 2);
  file.close();


  // Send data over LoRa
  LoRa.beginPacket();
  LoRa.print("Temperature: ");
  LoRa.print(bmp.readTemperature());
  LoRa.print(", Pressure: ");
  LoRa.print(bmp.readPressure() / 100.0F);
  LoRa.print(", Altitude: ");
  LoRa.print(bmp.readAltitude(1013.25));
  LoRa.print(", Latitude: ");
  LoRa.print(gps.location.lat(), 6);
  LoRa.print(", Longitude: ");
  LoRa.print(gps.location.lng(), 6);
  LoRa.print(", Degrees: ");
  LoRa.print(gps.course.deg(), 2);
  LoRa.endPacket();


  //Debugging
 


  // Close the file


  // Beep for 200 milliseconds at 1000 Hz
  tone(buzzerPin, 1000, 200);
}

I couldn't find any different Wiring configurations, what could I be doing wrong?

Thanks!
Shadycrisp
 
I haven't used it, but the Ultimate Breakout GPS looks to be a 3.3V device with 5V tolerant inputs.

https://www.adafruit.com/product/746

You can power it from 5V as it has a 3.3V regulator built-in, but you don't need to level shift the signals, you can connect directly. I would remove the level shifters as a first step to troubleshooting in case they are causing any issues and to reduce the complexity of your setup.
 
I haven't used it, but the Ultimate Breakout GPS looks to be a 3.3V device with 5V tolerant inputs.

https://www.adafruit.com/product/746

You can power it from 5V as it has a 3.3V regulator built-in, but you don't need to level shift the signals, you can connect directly. I would remove the level shifters as a first step to troubleshooting in case they are causing any issues and to reduce the complexity of your setup.
That doesn't seem to fix the issue, but thanks for pointing that out!
 
Where in your code do you actually read out the data from the GPS module?
From this page:

Feeding the Hungry Object​

To get TinyGPS++ to work, you have to repeatedly funnel the characters to it from the GPS module using the encode() method. For example, if your GPS module is attached to pins 4(RX) and 3(TX), you might write code like this:

1
2
3
4
5
6
SoftwareSerial ss(4, 3);
void loop()
{
while (ss.available() > 0)
gps.encode(ss.read);
Perhaps it's a good idea to get the DeviceExample.ino [using SoftwareSerial and your pins] operational first and then move to HardwareSerial.

Paul
 
Where in your code do you actually read out the data from the GPS module?
From this page:

Perhaps it's a good idea to get the DeviceExample.ino [using SoftwareSerial and your pins] operational first and then move to HardwareSerial.

Paul
I can't get the example to work, it says No GPS detected: check wiring. Also, the light labelled FIX on the gps is not on or blinking.
 
Strangely enough, I couldn't get DeviceExample.ino to work with SoftwareSerial also.
So I tried using hardware serial on pins 0 & 1 instead. That works!
Mind you: I had to connect Teensy TX1 to module pin RX [green wire] and Teensy RX1 to module pin TX [yellow wire]:

1710687542347.png


The serial monitor output:

1710687629970.png


Here is the modified, working code:
C++:
#include <TinyGPSPlus.h>
#include <SoftwareSerial.h>
/*
   This sample sketch demonstrates the normal use of a TinyGPSPlus (TinyGPSPlus) object.
   It requires the use of SoftwareSerial, and assumes that you have a
   4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
*/
static const int RXPin = 0, TXPin = 1;
static const uint32_t GPSBaud = 9600;

// The TinyGPSPlus object
TinyGPSPlus gps;

// The serial connection to the GPS device
//SoftwareSerial ss(RXPin, TXPin);

void setup()
{
  Serial.begin(115200);
  Serial1.begin(GPSBaud);

  Serial.println(F("DeviceExample.ino"));
  Serial.println(F("A simple demonstration of TinyGPSPlus with an attached GPS module"));
  Serial.print(F("Testing TinyGPSPlus library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
  Serial.println(F("by Mikal Hart"));
  Serial.println();
}

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

  if (millis() > 5000 && gps.charsProcessed() < 10)
  {
    Serial.println(F("No GPS detected: check wiring."));
    while(true);
  }
}

void displayInfo()
{
  Serial.print(F("Location: "));
  if (gps.location.isValid())
  {
    Serial.print(gps.location.lat(), 6);
    Serial.print(F(","));
    Serial.print(gps.location.lng(), 6);
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F("  Date/Time: "));
  if (gps.date.isValid())
  {
    Serial.print(gps.date.month());
    Serial.print(F("/"));
    Serial.print(gps.date.day());
    Serial.print(F("/"));
    Serial.print(gps.date.year());
  }
  else
  {
    Serial.print(F("INVALID"));
  }

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

  Serial.println();
}

About the FIX LED: here it took about a minute for the module to establish a GPS fix, the LED is flashing now.

Hope this helps,
Paul
 
Last edited:
Strangely enough, I couldn't get DeviceExample.ino to work with SoftwareSerial also.
So I tried using hardware serial on pins 0 & 1 instead. That works!
Mind you: I had to to connect Teensy TX1 to module pin RX [green wire] and Teensy RX1 to module pin TX [yellow wire]:

View attachment 33710

The serial monitor output:

View attachment 33712

Here is the modified code:
C++:
#include <TinyGPSPlus.h>
#include <SoftwareSerial.h>
/*
   This sample sketch demonstrates the normal use of a TinyGPSPlus (TinyGPSPlus) object.
   It requires the use of SoftwareSerial, and assumes that you have a
   4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
*/
static const int RXPin = 0, TXPin = 1;
static const uint32_t GPSBaud = 9600;

// The TinyGPSPlus object
TinyGPSPlus gps;

// The serial connection to the GPS device
//SoftwareSerial ss(RXPin, TXPin);

void setup()
{
  Serial.begin(115200);
  Serial1.begin(GPSBaud);

  Serial.println(F("DeviceExample.ino"));
  Serial.println(F("A simple demonstration of TinyGPSPlus with an attached GPS module"));
  Serial.print(F("Testing TinyGPSPlus library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
  Serial.println(F("by Mikal Hart"));
  Serial.println();
}

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

  if (millis() > 5000 && gps.charsProcessed() < 10)
  {
    Serial.println(F("No GPS detected: check wiring."));
    while(true);
  }
}

void displayInfo()
{
  Serial.print(F("Location: "));
  if (gps.location.isValid())
  {
    Serial.print(gps.location.lat(), 6);
    Serial.print(F(","));
    Serial.print(gps.location.lng(), 6);
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F("  Date/Time: "));
  if (gps.date.isValid())
  {
    Serial.print(gps.date.month());
    Serial.print(F("/"));
    Serial.print(gps.date.day());
    Serial.print(F("/"));
    Serial.print(gps.date.year());
  }
  else
  {
    Serial.print(F("INVALID"));
  }

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

  Serial.println();
}

About the FIX LED: here it took about a minute for the module to establish a GPS fix, the LED is flashing now.

Hope this helps,
Paul
The issue is that this example code just prints "No GPS Detected: check wiring", because even in my previous debugging, I have found that the GPS doesn't return any chars.
 
The wiring is jumbled up with a bunch of other components so I doubt a picture would be very useful. The wiring for the GPS that I am using is:
(Teensy 4.1 - GPS)
5V - VIN
GND - GND
01 - TX
00 - RX
 
On Teensy pin 0 is RX and pin 1 is TX.
If you have them wired as you state above you have RX going to RX and TX going to TX.
RX should go to TX and TX should go to RX.
 
On Teensy pin 0 is RX and pin 1 is TX.
If you have them wired as you state above you have RX going to RX and TX going to TX.
RX should go to TX and TX should go to RX.
Thanks for pointing that out! The example now works, but the code above still does not work when I modify it:
Also, when the GPS catches a fix, will the while loop repeat forever?
C++:
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>
#include <LoRa.h>
#include <SPI.h>
#include <TinyGPSPlus.h>
#include <SD.h>
//#include <SoftwareSerial.h>


//#define gpsSerial Serial1

// Define the LoRa frequency
const long frequency = 433E6; // Adjust according to your region's regulations


// Initialize the BMP280 sensor
Adafruit_BMP280 bmp;


// Initialize GPS
TinyGPSPlus gps;
static const int RX = 0, TX = 1;
static const uint32_t GPSBaud = 9600;
//SoftwareSerial ss(RX, TX);

// Setup LoRa with the specific CS and reset pins if needed
const int csPin = 10; // Change as per your LoRa module if not using the built-in SPI
const int resetPin = 9; // Set to your LoRa module's reset pin if any, or -1 if unused


const int buzzerPin = 2; // Buzzer connected to pin 2


File file; // Declare a File object for SD card operations


void setup() {
  Serial.begin(115200);
  Serial1.begin(GPSBaud);
 



  // BMP280 initialization
  if (!bmp.begin()) {
  Serial.println("Could not find a valid BMP280 sensor!");
  while (1);
  }


  // SD initialization using the built-in SD card slot
  if (!SD.begin(BUILTIN_SDCARD)) {
  Serial.println("SD Card Mount Failed");
  return;
  }


  // Create or open the file for logging
  file = SD.open("data.txt", FILE_WRITE);
  if (!file) {
  Serial.println("Failed to open file for writing");
  return;
  }
  file.println("Log Begin:");
  file.close();


  // LoRa initialization
  SPI.begin();
  LoRa.setPins(csPin, resetPin, 13); // Set LoRa module pins
  if (!LoRa.begin(frequency)) {
  Serial.println("Starting LoRa failed!");
  while (1);
  }


  pinMode(buzzerPin, OUTPUT); // Initialize the buzzer pin as an output
}


void loop() {
 
  while (Serial1.available() > 0)
    if (gps.encode(Serial1.read()))
      logData(true);

  if (millis() > 5000 && gps.charsProcessed() < 10)
  {
    Serial.println(F("No GPS detected: check wiring."));
    delay(1000);
  }
 
 
    
  delay(1000); // Adjust delay as needed
}






void logData(bool fix) {
  // Open the file for appending
  float lat = 0;
  float lon = 0;
  float deg = 0;
  file = SD.open("data.txt", FILE_WRITE);
  if (!file) {
  Serial.println("Failed to open file for appending");
  return;
  }
  if (gps.location.isValid())
  {
    lat = gps.location.lat();
    lon = gps.location.lng();
    
  }
  if (gps.course.isValid())
  {
    deg = gps.course.deg();
  }
  Serial.print("Temperature: ");
  Serial.print(bmp.readTemperature());
  Serial.println(" C");
  Serial.print("Pressure: ");
  Serial.print(bmp.readPressure() / 100.0F);
  Serial.println(" hPa");
  Serial.print("Approx. Altitude: ");
  Serial.print(bmp.readAltitude(1013.25)); // Standard sea-level pressure in hPa
  Serial.println(" m");
  Serial.print("Latitude: ");
  Serial.println(lat);
  Serial.print("Longitude: ");
  Serial.println(lon);
  Serial.print(", Degrees: ");
  Serial.println(deg);
 
  // Log temperature, pressure, and altitude from BMP280
  file.print("Temperature: ");
  file.print( bmp.readTemperature());
  file.println(" C");
  file.print("Pressure: ");
  file.print(bmp.readPressure() / 100.0F);
  file.println(" hPa");
  file.print("Approx. Altitude: ");
  file.print(bmp.readAltitude(1013.25)); // Standard sea-level pressure in hPa
  file.println(" m");
  file.print("Latitude: ");
  file.println(lat);
  file.print("Longitude: ");
  file.println(lon);
  file.print(", Degrees: ");
  file.println(deg);

 
  file.close();


  // Send data over LoRa
  LoRa.beginPacket();
  LoRa.print("Temperature: ");
  LoRa.print(bmp.readTemperature());
  LoRa.print(", Pressure: ");
  LoRa.print(bmp.readPressure() / 100.0F);
  LoRa.print(", Altitude: ");
  LoRa.print(bmp.readAltitude(1013.25));
  LoRa.print(", Latitude: ");
  LoRa.print(lat);
  LoRa.print(", Longitude: ");
  LoRa.print(lon);
  LoRa.print(", Degrees: ");
  LoRa.print(deg);

 
  LoRa.endPacket();


  //Debugging
 


 


  // Beep for 200 milliseconds at 1000 Hz
  tone(buzzerPin, 1000, 200);
}
 
Back
Top