Waps 61
Published © MIT

NMEA0183 Multi Function Display

Show NMEA0183 data from ships network on an Multi Function Display, including day- and sunlight, dawn and night settings

AdvancedFull instructions providedOver 7 days120
NMEA0183 Multi Function Display

Things used in this project

Hardware components

JC1060P470 1024x600 TFT display
×1
Espressif ESP32-P4
×1
logilink serial to usb adapter
×1

Software apps and online services

VS Code
Microsoft VS Code
PlatformIO IDE
PlatformIO IDE
LVGL version 9.4

Hand tools and fabrication machines

mustool MT8206 multimeter

Story

Read more

Schematics

Use cases for the application

UML diagram

Modules and their relation

Wire frame of the application

Code

Reading NMEA0183 data over hw-serial port (UART)

C/C++
To read characters from the serial port as an NMEA string.
/**
 * reads the serial port  and ckeks for valid nmea data starting with
 * character '$' only (~ and ! can be skipped as start charcter)
 * This is a state based process, where the state is determined by the nmeaStatus variable
 * Initial state is INVALID
 * When a start character is found, the state changes to RECEIVING and the nmeaBuffer is filled
 * with the incoming characters until a '*' character is found, then the state changes to CHECKSUMMING
 * and the checksum characters are read until a newline character is found, then the state changes to
 * TERMINATING and the nmeaDataReady flag is set to true, and the nmeaBuffer is processed by the
 * processNMEAData function, and then the state changes back to INVALID
 */
void NMEA_startListening()
{
  char cIn = '\0';
  while (Serial1.available() > 0 && nmeaStatus != TERMINATING)
  {
    cIn = Serial1.read();
    
    switch (cIn)
    {
    // case '~':   //skipped and don't waste time on it, because it's not used in NMEA0183 and is reserved by NMEA
    //  reserved by NMEA
    // case '!':   //skipped and don't waste time on it, because we don't use AIS data in this project
    //  for AIS info
    case '$':
      // for general NMEA info
      nmeaStatus = RECEIVING;
      nmeaIndex = 0;
      break;
    case '*':
      if (nmeaStatus == RECEIVING)
      {
        nmeaStatus = CHECKSUMMING;
      }
      break;
    case '\n':
    case '\r':
      // in old v1.5 version, NMEA Data may not be checksummed!
      if (nmeaStatus == RECEIVING || nmeaStatus == CHECKSUMMING)
      {
        nmeaDataReady = true;
        nmeaStatus = TERMINATING;
      }
      else
        nmeaStatus = INVALID;

      break;
    }
    switch (nmeaStatus)
    {
    case INVALID:
      // do nothing
      nmeaIndex = 0;
      nmeaDataReady = false;
      break;
    case RECEIVING:
    case CHECKSUMMING:
      if( cIn>=32 && cIn <=126) // filter out non-printable characters, which can cause problems in the processing of the NMEA data
      {
      nmeaBuffer[nmeaIndex] = cIn;
      nmeaIndex++;
      } else 
      {
        nmeaStatus = INVALID; // if a non-printable character is found, the NMEA data is considered invalid and the state changes back to INVALID
        nmeaIndex = 0;
        nmeaDataReady = false;
      }
      if (nmeaIndex >= NMEA_BUFFER_SIZE)
      {
        nmeaStatus = TERMINATING;
        nmeaIndex = 0;
        nmeaDataReady = false;
      }
      break;
    case TERMINATING:

      nmeaStatus = INVALID;
      if (nmeaDataReady)
      {
        nmeaDataReady = false;

        // Clear the remaining buffer content with '\0'
        for (int y = nmeaIndex + 1; y < NMEA_BUFFER_SIZE + 1; y++)
        {
          nmeaBuffer[y] = '\0';
        }
#ifdef DEBUG
        debugWrite(nmeaBuffer);
#endif

        processNMEAData(nmeaBuffer);
        
        // clear the NMEAbuffer with 0
        memset(nmeaBuffer, 0, NMEA_BUFFER_SIZE + 1);
        nmeaIndex = 0;
      }

      break;
    }
  }
}

/*
 * Initializes UART 1 for incomming NMEA0183 data from the boat network
 */
bool initializeListener()
{
  bool status = true;
  int baudrate = lv_subject_get_int(&mfd_subject_baudrate);
  Serial1.begin(baudrate, SERIAL_8N1, LISTENER_RX, LISTENER_TX, true);
  memset(nmeaBuffer, 32, NMEA_BUFFER_SIZE - 1);
  nmeaBuffer[NMEA_BUFFER_SIZE] = '\0';

  lv_log("nmeaBuffer initialized with %s\n", nmeaBuffer);

#ifdef DEBUG
  debugWrite("Listener initialized...");
#endif
  return status;
}

NMEA0183-mfd git repository

V1.0 released version with the lastes code and bin files.

Credits

Waps 61
3 projects • 9 followers
Software engineering since '83, sailing since '75 and working in Industrial Automation
Thanks to Andruid59, Bitbank2, and pixelEDI.

Comments