NEMA input commands

Hi @rgsparber ,

Please tell us which M10 document you are looking at. I couldn’t find Table 2-4 that you mentioned.

Please also tell us which Pro Micro board you are using. There are several. Most are 3.3V, but some older ones are 5V. Please be careful. The u-blox MAX-M10S is 3.3V. You may hit problems if you are using a 5V Pro Micro.

I’ve put together a generic NMEA polling example (see below). It will set the rate of the standard NMEA messages to zero, using the UBX VALSET configuration interface. Then it polls GNGGA using the xxGNQ message. All of the bits you need are in there; there is code to calculate both the UBX and NMEA checksums (they are different).

I hope this helps,
Paul

// Communicate with the u-blox MAX-M10S over Serial (UART)
// Set the rate of the standard NMEA messages to zero
// Poll individual NMEA messages

#define myConsole Serial // Change to e.g. SerialUSB if needed
#define mySerial Serial1 // Change this if needed

void ubxWriteByteUpdateChecksum(uint8_t *csum1, uint8_t *csum2, uint8_t b)
{
  // Send a single UBX byte and update the checksums
  
  mySerial.write(b);
  *csum1 = *csum1 + b;
  *csum2 = *csum2 + *csum1;
}

void ubxValset(uint32_t key, uint8_t val_8)
{
  // Send a UBX CFG VALSET message with a 32-bit key and an 8-bit value
  
  uint8_t csum1 = 0;
  uint8_t csum2 = 0;
  
  mySerial.write(0xb5); // UBX sync character 1 - not in checksum
  mySerial.write(0x62); // UBX sync character 2 - not in checksum
  
  ubxWriteByteUpdateChecksum(&csum1, &csum2, 0x06); // Class CFG
  ubxWriteByteUpdateChecksum(&csum1, &csum2, 0x8a); // ID VALSET

  ubxWriteByteUpdateChecksum(&csum1, &csum2, 0x09); // Length LSB
  ubxWriteByteUpdateChecksum(&csum1, &csum2, 0x00); // Length MSB

  ubxWriteByteUpdateChecksum(&csum1, &csum2, 0x00); // Version 0x00
  ubxWriteByteUpdateChecksum(&csum1, &csum2, 0x01); // Layers : update configuration in RAM layer only
  ubxWriteByteUpdateChecksum(&csum1, &csum2, 0x00); // Reserved
  ubxWriteByteUpdateChecksum(&csum1, &csum2, 0x00); // Reserved

  ubxWriteByteUpdateChecksum(&csum1, &csum2, (key >>  0) & 0xFF); // key LSB
  ubxWriteByteUpdateChecksum(&csum1, &csum2, (key >>  8) & 0xFF); // key
  ubxWriteByteUpdateChecksum(&csum1, &csum2, (key >> 16) & 0xFF); // key
  ubxWriteByteUpdateChecksum(&csum1, &csum2, (key >> 24) & 0xFF); // key MSB
  
  ubxWriteByteUpdateChecksum(&csum1, &csum2, val_8); // value (8-bit)

  mySerial.write(csum1); // Checksum CK_A - not included in length
  mySerial.write(csum2); // Checksum CK_B - not included in length
}

void nmeaWriteByteUpdateChecksum(uint8_t *csum, uint8_t b)
{
  // Send a single NMEA byte and update the checksum
  
  mySerial.write(b);
  *csum = *csum ^ b;
}

void nmeaWriteBytesUpdateChecksum(uint8_t *csum, const char *b)
{
  // Loop through NMEA text, send each byte and update checksum
  
  for (int i = 0; i < strlen(b); i++)
  {
    nmeaWriteByteUpdateChecksum(csum, b[i]);
  }
}

void nmeaWriteChecksumCRLF(uint8_t csum)
{
  // Send the NMEA checksum as two ASCII characters, plus CR and LF
  
  uint8_t nibble = csum >> 4; // Get 4 MS bits
  nibble += 0x30; // Convert to ASCII 0-9
  if (nibble >= 0x3A)
    nibble += 0x41 - 0x3A; // Convert to ASCII A-F
  mySerial.write(nibble);
  
  nibble = csum & 0xF; // Get 4 LS bits
  nibble += 0x30; // Convert to ASCII 0-9
  if (nibble >= 0x3A)
    nibble += 0x41 - 0x3A; // Convert to ASCII A-F
  mySerial.write(nibble);

  mySerial.write(0x0D); // CR
  mySerial.write(0x0A); // LF
}

void pollNMEA(const char *msgID)
{
  // Poll a single standard NMEA message

  uint8_t csum = 0;

  mySerial.write('$'); // Dollar - not in checksum  
  nmeaWriteBytesUpdateChecksum(&csum, "EIGNQ"); // Poll a standard message (Talker ID GN)
  nmeaWriteByteUpdateChecksum(&csum, ','); // Comma
  nmeaWriteBytesUpdateChecksum(&csum, msgID); // message ID
  mySerial.write('*'); // Asterix - not in checksum
  nmeaWriteChecksumCRLF(csum); // Write 2-byte ASCII checksum and CR, LF
}

void setup()
{
  delay(1000);

  myConsole.begin(115200); // Begin Serial at 115200 baud
  myConsole.println("SparkFun MAX-M10S NMEA Example");

  mySerial.begin(9600); // Communicate with the GNSS at 9600 baud. Change this to 38400 if needed

  // Set the rate of NMEA GGA, GLL, GSA, GSV, RMC, VTG on UART1 to zero
  ubxValset(0x209100bb, 0); // CFG-MSGOUT-NMEA_ID_GGA_UART1
  ubxValset(0x209100ca, 0); // CFG-MSGOUT-NMEA_ID_GLL_UART1
  ubxValset(0x209100c0, 0); // CFG-MSGOUT-NMEA_ID_GSA_UART1
  ubxValset(0x209100c5, 0); // CFG-MSGOUT-NMEA_ID_GSV_UART1
  ubxValset(0x209100ac, 0); // CFG-MSGOUT-NMEA_ID_RMC_UART1
  ubxValset(0x209100b1, 0); // CFG-MSGOUT-NMEA_ID_VTG_UART1

  // Read and discard the acknowledgements for the UBX CFG VALSET messages
  delay(1000);
  while (mySerial.available())
  {
    mySerial.read();
  }
}

void loop()
{

  // Poll GNGGA
  
  pollNMEA("GGA");

  // NMEA could take a full second to arrive (if the navigation rate is 1Hz).
  // Echo everything from mySerial to myConsole until a LF (0x0A) is received
  // or two seconds have elapsed.
  
  unsigned long startTime = millis();
  uint8_t c = 0;
  while ((c != 0x0A) && (millis() < (startTime + 2000)))
  {
    if (mySerial.available())
    {
      c = mySerial.read();
      myConsole.write(c);
    }
  }

}