Skip to content

a lightweight NMEA 2000 parser library in pure C

License

Notifications You must be signed in to change notification settings

raccoman/minmea2k

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

minmea2k, a lightweight NMEA 2000 PGN parser library

minmea2k is a minimalistic parser library written in C for decoding NMEA 2000 (CAN-based) PGNs. It is designed for embedded systems and resource-constrained environments, such as microcontrollers.

Features

  • No dynamic memory allocation.
  • Designed for low memory usage and portability.
  • Lightweight and simple to integrate (single source and header file).
  • Fast packet support included.
  • Easy to extend with new PGN decoders.
  • Suitable for real-time CAN applications on boats, vehicles, and embedded devices.

Supported PGNs

Currently supported NMEA 2000 PGNs:

PGN (Decimal) PGN (Hex) Description
60928 0x00EE00 ISO Address Claim
127488 0x01F200 Engine Parameters, Rapid Update
127489 0x01F201 Engine Parameters, Dynamic
127493 0x01F205 Transmission Parameters, Dynamic
129026 0x1F802 COG & SOG, Rapid Update
129025 0x1F801 Position, Rapid Update
129028 0x1F804 GNSS Delta Altitude
127250 0x1F112 Vessel Heading
127251 0x1F113 Rate of Turn
127257 0x1F119 Attitude
127505 0x1F211 Fluid Level

More PGNs will be added in future. You can contribute by adding them via pull requests.

Usage Example

Here's a minimal example of how to use minmea2k in a typical Linux environment with a CAN interface. It opens a socket on can0, reads messages in a loop, and prints decoded fluid level data.

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include "minmea2k.h"

int main(void) {
    const char *iface = "can0";
    int s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    if (s < 0) {
        perror("socket");
        return 1;
    }

    struct ifreq ifr;
    strcpy(ifr.ifr_name, iface);
    if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
        perror("ioctl");
        return 1;
    }

    struct sockaddr_can addr = {
        .can_family = AF_CAN,
        .can_ifindex = ifr.ifr_ifindex,
    };

    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
        perror("bind");
        return 1;
    }

    struct can_frame frame;

    while (1) {
        ssize_t nbytes = read(s, &frame, sizeof(frame));
        if (nbytes <= 0) continue;

        uint8_t src, dest, pri;
        uint32_t pgn = minmea2k_can_id_to_pgn(frame.can_id, &src, &dest, &pri);
        if (dest != 0xFF) continue;

        switch (pgn) {
            case PGN_ID_FLUID_LEVEL: {
                t_minmea2k_fluid_level fluid_level;
                if (minmea2k_unpack_fluid_level(&fluid_level, frame.data, frame.can_dlc) == 0) {
                    printf("%d,%d,%.2f,%.1f\n",
                        fluid_level.instance,
                        fluid_level.type,
                        fluid_level.level,
                        fluid_level.capacity
                    );
                }
                break;
            }
        }
    }

    close(s);
    return 0;
}

You can adapt the switch statement to decode other PGNs using the corresponding minmea2k_unpack_* functions.

Integration with your project

Simply add minmea2k.[ch] to your project and #include "minmea2k.h" in your source. No external dependencies required.

Contributing

  1. Open an issue or submit a pull request via GitHub.

Licensing

minmea2k is open source software. See the COPYING file for details. If licensing is an issue, contact the author for alternatives.

Author

minmea2k is maintained by Riccardo Accomando riccardoaccoma@gmail.com Based on concepts from the original minmea library by Kosma Moczek and Patryk Szymczak.

About

a lightweight NMEA 2000 parser library in pure C

Resources

License

Stars

Watchers

Forks