GPS T/Rx Or Gnd Noise

Ok guys im a little stumped this time.

So im using a nano to encode APRS packets, which at its basic is just sound transmitting data. So the board i designed uses a Ebay Ublox Neo 6m to get GPS data. But when i try to transmit the encoding get mess up. Now i have taken off the gps module and the encoding is perfect. So this rules out anything else but the GPS right?

With that train of though, i added 1k pulldown resistors to hopefully pull the the tx and rx pins to gnd when the gps moudle is transmitting. And no luck. Not sure what to do from here.

Any ideas

thanks.

Schematic? Picture? Code?

Without seeing any of those, I'll guess that it's a level-shifting or power problem...

Ok sorry, forgot to add that. Below is the code and schematic

#include <LibAPRS.h>
#define ADC_REFERENCE REF_5V
#define OPEN_SQUELCH false
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
TinyGPSPlus gps;

static const int RXPin = 12, TXPin = 13; // 11=tx 12=rx on board
static const uint32_t GPSBaud = 9600;
SoftwareSerial GPS_ss(RXPin, TXPin);

static char lat_gps_char[15];
static char lon_gps_char[15];
static char Alt_gps_char[5];

boolean gotPacket = false;
AX25Msg incomingPacket;
uint8_t *packetData;
void aprs_msg_callback(struct AX25Msg *msg) {
  // If we already have a packet waiting to be
  // processed, we must drop the new one.
  if (!gotPacket) {
    // Set flag to indicate we got a packet
    gotPacket = true;

    // The memory referenced as *msg is volatile
    // and we need to copy all the data to a
    // local variable for later processing.
    memcpy(&incomingPacket, msg, sizeof(AX25Msg));

    // We need to allocate a new buffer for the
    // data payload of the packet. First we check
    // if there is enough free RAM.
    if (freeMemory() > msg->len) {
      packetData = (uint8_t*)malloc(msg->len);
      memcpy(packetData, msg->info, msg->len);
      incomingPacket.info = packetData;
    } else {
      // We did not have enough free RAM to receive
      // this packet, so we drop it.
      gotPacket = false;
    }
  }
}

void setup () {
  GPS_ss.begin(GPSBaud);
  Serial.begin(115200);
   while (!Serial) {
  }


  APRS_init(ADC_REFERENCE, OPEN_SQUELCH);
  APRS_setCallsign("KE8CPD", 1);

  APRS_printSettings();
  Serial.print(F("Free RAM:     ")); Serial.println(freeMemory());
    Serial.println("1 for GPS check");
  Serial.print("2 for location update");
  }
  
  void locationUpdateExample() {
    
  APRS_setPower(2);
  APRS_setHeight(4);
  APRS_setGain(7);
  APRS_setDirectivity(0);
  
  // We'll define a comment string
  char *comment = "LibAPRS location update";
    
  // And send the update
  APRS_sendLoc(comment, strlen(comment));

}

void processPacket() {
  if (gotPacket) {
    gotPacket = false;
    
    Serial.print(F("Received APRS packet. SRC: "));
    Serial.print(incomingPacket.src.call);
    Serial.print(F("-"));
    Serial.print(incomingPacket.src.ssid);
    Serial.print(F(". DST: "));
    Serial.print(incomingPacket.dst.call);
    Serial.print(F("-"));
    Serial.print(incomingPacket.dst.ssid);
    Serial.print(F(". Data: "));

    for (int i = 0; i < incomingPacket.len; i++) {
      Serial.write(incomingPacket.info[i]);
    }
    Serial.println("");

    // Remeber to free memory for our buffer!
    free(packetData);

    // You can print out the amount of free
    // RAM to check you don't have any memory
    // leaks
    // Serial.print(F("Free RAM: ")); Serial.println(freeMemory());
  }
}

void GPS_update(){
dtostrf((gps.location.lat()),15,8,lat_gps_char);
APRS_setLat(lat_gps_char);
Serial.println(lat_gps_char);
dtostrf((gps.location.lng()),15,8,lon_gps_char);
APRS_setLon(lon_gps_char);
Serial.println(lon_gps_char);
dtostrf((gps.altitude.feet()),5,2,Alt_gps_char);
Serial.println(Alt_gps_char);
smartDelay(1000);
}

void gpscheck(){
dtostrf((gps.location.lat()),15,8,lat_gps_char);
Serial.println(lat_gps_char);
dtostrf((gps.location.lng()),15,8,lon_gps_char);
Serial.println(lon_gps_char);
dtostrf((gps.altitude.feet()),5,2,Alt_gps_char);
Serial.println(Alt_gps_char);
smartDelay(1000);
}

//boolean whichExample = false;
void loop() {
if (Serial.available())
  {
    char bark = Serial.read();
    if (bark == '1'){
      gpscheck();
       delay(10);
      processPacket();
      return;}
   if ( bark == '2'){
    GPS_update();
    processPacket();
    delay(10);
    locationUpdateExample();
    Serial.print(F("Free RAM:     ")); Serial.println(freeMemory());
      return;}
    }
  }
//----------------------------------------------------------------------------------------------------
//Custom functions for gps

static void printFloat(float val, bool valid, int len, int prec){
  if (!valid){
    while (len-- > 1)
      Serial.println('*');
    Serial.println(' ');
  }
  else{
    Serial.println(val, prec);
    int vi = abs((int)val);
    int flen = prec + (val < 0.0 ? 2 : 1); // . and -
    flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
    for (int i=flen; i<len; ++i)
      Serial.print(' ');
  }
  smartDelay(0);
}

static void smartDelay(unsigned long ms){
  unsigned long start = millis();
  do 
  {
    while (GPS_ss.available())
      gps.encode(GPS_ss.read());
  } while (millis() - start < ms);
}

What is the power supply? Have you checked the current requirements of all modules?

The GPS module is a 3.3V device, although the VCC can use 5V for the on-board regulator. You should probably do a little level-shifting for the RX and TX pins. Here's a recent post of mine on the subject.

Maybe the voltage sags a little and the GPS TX voltage drops below the Arduino RX min voltage? The GPS module needs up to 68mA during acquisition.

Here's a few comments regarding the code:

In general, the usage of malloc/free is strongly discouraged in this environment. Using freeMemory() to decide if you can allocate a new packet isn't safe, because the stack might extend into the heap when you least expect it. It would be better to pick a maximum packetData size. This would avoid calling freeMemory to traverse the heap, and then calling malloc, which searches the heap. malloc can still return 0. :stuck_out_tongue:

I've attached an INO that uses a static packetData array of 128 bytes. There's room to use 256, if you think that's really necessary. There's lots of room for similar improvements in LibAPRS, perhaps another 2K program space could be eliminated. This would provide better long-term stability.

Also, the attached INO uses my libraries, NeoGPS and NeoSWSerial. They are much more efficient than TinyGPS++ and SoftwareSerial. The NeoGPS library can also be configured to only parse the lat, lon, and alt from a GGA sentence. Everything else is ignored, which saves even more program space and RAM.

Original sketch used 17064 bytes program space and 1435 bytes RAM.
Attached sketch uses 16376 bytes program space and 1354 bytes RAM.

You will also see that the main loop is structured a little differently. A key concept in this environment is to never block, not even with a delay. Instead, check everything quickly and move on. This is more forgiving of delays in other parts of your sketch (or in libraries), and it will be more responsive. If you find that you are still losing GPS data, there is an easy change that lets it get parsed in the background (during the RX character interrupt) instead of loop().

If you'd like to try it, you can install NeoGPS from the Library Manager. NeoSWSerial is on github.

Cheers,
/dev

hsojhcoom.ino (3.47 KB)

libAPRS makes heavy use of Timer1 interrupts, which will interfere with anything that depends on delay loops for timing, and, for that matter, anything else that wants to use Timer1.

libAPRS makes heavy use of Timer1

Well, AltSoftSerial is out, then.

That leaves NeoSWSerial and SoftwareSerial (neither use timer 1), unless the GPS TX could go on the Serial RX pin 0. That would prevent receiving commands from the Serial Monitor Window. How about a button press instead? That might make more sense if this is going to operate without a PC attached.

How long do packet transmissions/receptions take? If it's a long time (>64ms), then GPS characters will be lost. But maybe it doesn't matter if it takes a second to get good GPS data before sending a location update.

Interesting problem!

Cheers,
/dev

/dev:
What is the power supply? Have you checked the current requirements of all modules?

The power is being supplied via the on board 5v pin. I looked it up it should be able to handle 400mA. And the normal I/O pins can handle 40 mA per pin. So im assuming the 4 bit sound card is well under that current ceiling.

/dev:
Also, the attached INO uses my libraries, NeoGPS and NeoSWSerial. They are much more efficient than TinyGPS++ and SoftwareSerial. The NeoGPS library can also be configured to only parse the lat, lon, and alt from a GGA sentence. Everything else is ignored, which saves even more program space and RAM.

Thanks a bunch for this for the most part it cleared up the issue. So when the GPS module is attached and powered and without a fix, it encodes and decodes just fine. This was not the case with the other code i was using. BUT when it the GPS does have fix, and when the packet is being sent to the it stops mid way though the packet transmission. About the same spot ever time (from what i can hear). So im not sure why that does that. I have an transmit LED and when it stops it continues to lit. OR when i check for a fix and it has one and then i try to send an update (ie. 2) it just continues to transmit, its just a noise, not sure what it is. And to get it to stop i have to powercycle to board/ upload a new sketch.

jremington:
libAPRS makes heavy use of Timer1 interrupts, which will interfere with anything that depends on delay loops for timing, and, for that matter, anything else that wants to use Timer1.

Being new the coding in general im still learning but dont know what Timer1 are but ill being doing some research on it

/dev:
How about a button press instead?

The goal is to have the system in a vehicle, and i would like to eventually write a function to send an update when its so far from the last update. This is a link to a commercial product, they have what they call smart beaconing, similar idea of what i want to do.

/dev:
How long do packet transmissions/receptions take? If it's a long time (>64ms), then GPS characters will be lost. But maybe it doesn't matter if it takes a second to get good GPS data before sending a location update.

The packet transmission does take a long time to transmit, probably like 2 seconds, so im not sure if this is what is causing the freeze in the program.

@ /dev Thanks for taking the time to help me a noob out :slight_smile:

The power is being supplied via the on board 5v pin.

But what is supplying power to the board? Is it the USB cable? A battery? A wall wart? Does the radio transmitter have a separate power supply? Do you have a schematic/drawing for the entire system?

it should be able to handle 400mA... the normal I/O pins can handle 40 mA per pin.

That is the Absolute Maximum current that can pass through the Arduino board or a single pin, not the capacity of your power supply. If you allow any more than that, you'll let the magic smoke out. :smiley:

I'm assuming the 4 bit sound card is well under that current ceiling.

Not necessarily. Is the sound card in a PC or is it a stand-alone module? If it's inside a PC, it's using the PC's power supply. The capacitors on the AUDIO and MIC lines prevent the Arduino from drawing any power over those pins (mostly).

If it's not in a PC, and the sound card is connected to the same power source as the Arduino board, look at the specs for the sound card to get the power requirements. Or tell us which sound card you're using.

If you have speakers and an amplifier using the same power source, you need to include that in your power calculations, too.

BUT when the GPS does have fix, and when the packet is being sent to the [radio?] it stops mid way though the packet transmission. About the same spot every time

That still sounds like a power problem, but it could be an electrical noise problem. How close is the transmitting antenna to the board? This is why we need a complete description and/or pictures.

Have you tried level-shifting the GPS RX/TX pins yet?

It could be a code problem, but I've tested the sketch with commands and GPS. I have assumed that LibAPRS is ok, so maybe I should look a little closer. Just to be sure, from where did you download LibAPRS?

I would like to eventually write a function to send an update when its so far from the last update.

That is good to know. It means that, in the final system, you can put the GPS TX on the Arduino Serial RX pin 0, avoiding a whole bunch of issues with software serial libraries, Timer1, and interrupts.

For now, you can leave the GPS on pins 12 & 13 and use NeoSWSerial. When everything is working (mostly), you can move the GPS TX to the Serial RX pin 0. Uploading a new sketch in that configuration will require either disconnecting the GPS from pin 0 or disconnecting power from the GPS module. I mention that so that you can plan to have a switch inline or a jumper/wire you can disconnect.

Thanks

Glad to help! Now I've got to look at LibAPRS a little more...

Cheers,
/dev


Here are the current requirements I can identify:

Arduino UNO: 50mA
GPS: 70mA
RX/TX LEDs: 20mA
DAC Resistor ladder: ~3mA (assumes R0 is 1K)