Skip to content


Switch branches/tags


Failed to load latest commit information.
Latest commit message
Commit time

NMEA2000 library for C++

If you are familiar with library, here is quick link to Changes.

Object oriented NMEA2000 library for Teensy, ESP, Arduino, MBED and Rasberry type Boards. These board types has been tested, but library can be used also in other systems by writing compatible CAN driver and wrapper for other hw specific functions.

Library gives you easy way to make different kind of NMEA2000 bus devices like sensor transducers (battery, temperature, wind, engine, etc.), NMEA2000 information displays, NMEA2000→PC interface (like Actisense NGT1), NMEA0183→NMEA2000 or NMEA2000→NMEA0183 converter.

Library fulfills NMEA 2000 mandatory functions and behaviour. Devices using library can pass NMEA2000 certification tests. Library has been used in several commercial certified products.

I prefer to use Teensy 3.2, 3.5, 3.6, 4.0, 4.1 or ESP32 board with either unisolated MCP2562 or isolated ISO1050 tranceiver. Those boards are "very" powerfull, small and runs with low power. See more about hardware under Hardware setup below.

With default settings library requires about 23 kB rom and 3.3 kB RAM in normal operation. So you should have at least 8 kB RAM in your chip. If you have Arduino Mega board, it is OK for testing and for small projects, but I do not prefer to buy one for new project. Arduino Due is OK, but is physically bigger and eats more power than Teensies or ESP32. If you have Arduino Uno or any board with less than 8 kB RAM, please read all issues and Memory requirements below and then forget it. If you anyway want to use it please do not set any issues, if it does not work or does unexpected crashes.

Hardware depended libraries

Take care that you use libraries under my Github, when available! Others may not work right with NMEA2000!

Teensy 4.0/4.1 boards with internal CAN

CAN library is included to the code so you do not need any extra CAN library with this. NMEA2000_Teensyx library will replace NMEA2000_teensy library in future. You can already start to use it with all Teensy boards by forcing it with define (see NMEA2000_CAN.h comment). For critical projects I prefer to use old library until this has been running under tests for a while.

Teensy 3.1/3.2 or 3.5/3.6 board with internal CAN

NMEA2000_teensy has been originally forked from NMEA2000_teensy contributed by (Thomas Sarlandie)

Note that FlexCan library is already included in Teensyduino extension. In order to use my fork, you have to remove FlexCAN library from C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\FlexCAN. Default FlexCAN library does not work right with NMEA2000.

ESP32 boards with internal CAN

ESP32 CAN driver by Thomas Barth has been implemented inside NMEA2000_esp32 so you do not need other drivers for that.

Arduino Due board with internal CAN

Boards with MCP2515 CAN bus controller (e.g. Arduino Mega, ESP8266)

You can use mcp_can with boards where you connect MCP2515 CAN bus controller with SPI. You can also use it as secondary CAN for e.g. Teensy 3.2 or ESP32.

mcp_can library is developed version of original mcp_can library. This allows also to use 8MHz clock and has been tested with Maple Mini. mcp_can library can be originally found on, but check library status has all improvements been implemented to Seeed-Studio. At least 18.09.2017 it was up to date.

avr processors with internal CAN

MBED boards

Raspberry Pi

NMEA2000_socketCAN has been originally forked from


I thank Kees Verruijt for his excellent CanBoat project and Dr Andrew Mason for OpenSkipper project. I originally started to learn NMEA 2000 via OpenSkipper project, which development I continued. PGN library on OpenSkipper and so on this library is mostly based on Kees work. Also it appeared that some code parts are probably originally from CanBoat even I have found them from other sources. Actisense message format handling I have learned from OpenSkipper project.

I also thank for anybody who has extended library with new PGNs or processor support.



  • Possible compatibility change: tN2kGroupFunctionHandler::GetRequestGroupFunctionTransmissionOrPriorityErrorCode interface has changed. If you have used that, please update interface.

  • Possible compatibility change: Removed need of delay function on tNMEA2000::Open(). Now it opens CAN commununication and returns true, if that and other configuration succeeds. Final open, when address claiming starts, will be delayed and done by ParseMessages. There is new callback OnOpen, which will be called on initial address claiming started. See below

  • Possible compatibility change: For linux users removed default dummy tSocketStream serStream; from NMEA2000_CAN.h

  • Compatibility change: PGN129285 parameter list SetN2kPGN129285 and SetN2kRouteWPInfo has been changed. Compiler could not solve ambiguous problem between compatibility inlines, so users are forced to change to new interface.

  • Added tNMEA2000::SetOnOpen to set callback for communication open. You need this e.g., if you want to synchronize your messages with offsets. See how it has been used e.g., on exmample TemperatureMonitor.

  • New module N2kTimer to hide platform dependent millis(). Module declares scheduler classes to fix problems on simple millis() testing in case of roll over. Class tN2kSyncScheduler is for synchronizing message sending. See how it has been used e.g., on exmample TemperatureMonitor

  • Improved: Single test for pending information (tInternalDevice::HasPendingInformation) to avoid multiple tests in every loop.

  • Fix: Heartbeat problem caused by millis() roll over after 49 days.

  • Fix: Added missing const modifiers. Thanks alexg-k.

  • Fix: Limit SendRxPGNList/SendTxPGNList to avoid crash in case of error.

  • Fix: PGN 129285 Waypoint list. Thanks aydosj.

  • Added: PGN 127252 Heave. Thanks aydosj.

  • Changed some parameter order in classes to save small amount of memory.

  • Updated examples TemperatureMonitor, WindMonitor, BatteryMonitor and MessageSender to use tN2kSyncScheduler and tNMEA2000::SetOnOpen for synchronizating messages.


  • Fix: On N2kGroupFunctionDefaultHandlers.cpp tN2kGroupFunctionHandlerForPGN60928 unique number length is 3 bytes.

  • Fix: On N2kMsg.cpp changed round(v/precision) to round( (v/precision) ), since some system round macro behaved unexpectedly. Thaks to ieb.


  • Fix: use proper array delete operator in RingBuffer, thanks garaminowicz

  • Fix: PGN 127251 rate of turn type, thanks BerndCirotzki and for remind speters.

  • Fix: PGN 129794 setter.


  • Changed #include <cstring> to #include <string.h>. <cstring> is not available on all environments.

  • Fixed proprietary PGN handling on N2kGroupFunction.cpp.

  • Fixed N2kMsg.cpp:SetBuf3ByteDouble(). Thanks to mairas.

  • Add support for PGN 129041, 130323. Thanks to MattCairns.

  • Added support for PGN127237, 127233, 130577 and more detail for 129039. Thanks to aydosj.

  • Copyright update.


  • Documentation update.


  • Added manufacturer bits to engine discrete status ( PGN 127489 )

  • Added data limitation handling to tN2kMsg. Now overflow values will be sent as overflow. E.g. SetN2kTemperature(N2kMsg,0xff,0,N2kts_MainCabinTemperature,CToKelvin(800));
    will send temperature as 0xfffe, which is NMEA2000 standard way to inform that value is out of range. Library does not yet handle overflow on reading, but it is under construction.

  • Fixed PGNs 126992, 128275, 129029 time reading to UDouble

  • Added function tNMEA2000::Restart(). This is preliminary and may change. Read more info on NMEA2000.h.

  • Modified tNMEA2000::RespondGroupFunction to allow user add own common group function handler with PGN=0.

  • Fixed tNMEA2000::HandleCommandedAddress which should be accepted only by BAM TP.

  • Added tN2kGroupFunctionHandler::ChangeTransmissionOrPriorityErrorCode

  • Fixed tN2kGroupFunctionHandlerForPGN126993::HandleRequest. System must not respond to pure 126208 request for 126993. Also TransmissionInterval setting is limited to 1000 - 60000 ms.

  • Modified debug messages.


  • Fix for engine discrete status 2.


  • Added definition to NMEA2000_CAN.h to select CAN device for Arduino DUE


  • Added handlers for PGN 129540 GNSS satellites in view

  • Added new necessary types

  • Added SetByte for tN2kMsg class.

  • Added PGN 129540 handler for test example DataDisplay2

  • Redesigned example MessageSender. Now it is more usefull for testing, since each message can be individually enabled/disabled.

  • Added PGN 129540 handler for test example MessageSender


  • Added better inline ParseN2kEngineDynamicParam to N2kMessages

  • Copyright update


  • Added better engine discrete status handling to N2kMessages


  • Fix for 'memcpy' overflow for float reading on N2kMsg.cpp


  • Add support for Teensy 4.x


  • Add support for Windlass Network Messages PGN 128776, 128777 & 128778 by Paul Reeve


  • Fixed setting buffered frame length to min instead of max length on NMEA2000.cpp SendFrame

  • Added NMEA2000::IsProprietaryMessage

  • Fixed AddGroupFunctionHandler to allow to add handlers after Open

  • Added RemoveGroupFunctionHandler to allow dynamically remove handlers on runtime.

  • Added proprietary message handling to N2kGroupFunction.cpp

  • Improved N2kDeviceList HandleMsg to see devices, which has been off.

  • Added FindDeviceByProduct to N2kDeviceList

  • Extented list of fast packet messages to all known fast packet messages. This also leads to situation that all fast packet messages are known messages and may effect to setting SetHandleOnlyKnownMessages behaviour. To limit known messages, one should have provided list with SetFastPacketMessages.


  • Fixed PGN 130314 and PGN 130315 pressure type to signed.

  • Added pressure enums.


  • NOTE! Compatibility change! PGN 127506 TimeRemaining should have been in seconds as it is SI unit. If you have used that on your code, provide value in seconds. Parse function also return in seconds now.

  • Added Capacity parameter to PGN 127506. I did not made overwrite function without due to above change. So it hopefully wakes you up about the changes.

  • Fixed MaretronProprietary test on N2kMaretron.cpp

  • Some comment fixes.


  • Added support for Maretron proprietary PGNs 130823,65286, 65287. See N2kMaretron.h. Thanks to Vassilis Bourdakis.

  • Added proprietary fast packet message test as default. So now proprietary fast packet messages will be automatically parsed right without need to use ExtendFastPacketMessages

  • Fixed strings on product information. Unused characters will be filled with 0xff.


  • Fixed Rate of turn (PGN 127251) and AIS position report ROT (PGN 129038) value multiplier.

  • Separated N2k enums to own file N2kTypes.h

  • Fixed PGNs 127251, 127258, 130576 length for sending by padding with reserved. Some devices refuces to listen message, if length is wrong.


  • Fixed: PGN 127513 was accidently defined also as single frame message.


  • Added: Trip fuel consumption, engine PGN 127497.

  • Added: More PGN:s to default fast packet list.

  • Updated: Examples MessageSender and DataDisplay2, which can be used for testing messages.


  • Added: Charger status PGN 127507.

  • Added: Possibility to delay ISO address claim. Due to some devices CAN priority, it was sent too fast.

  • Added: Count for tDeviceList


  • Fix: Device list handler fix. Some tools may use source 254 and that was checked wrong.

  • Fix: Message priorities.


  • Fix: NMEA2000.h/NMEA2000.cpp, just in parameter N2kSource type change by mrbubble62


  • Added: N2kMessagesEnumToStr.h "exhaust gas" string for temperature sources by mrbubble62.


  • Fix: NMEA2000_CAN.h, make ESP32 work with ESP-IDF framework, by Sarfata


  • Fix: Handling of humidity PGN 130313.


  • Added: Support for ESP32. See also NMEA2000_esp32

  • Fix: Changed some names to avoid conflicts with some stupid define macros on some environments.


  • Fix: NextHeartbeatSentTime initial value.

  • Added: New example NMEA2000ToNMEA0183. This has been tested on RPi3B, Arduino DUE, Arduino Mega, Teensy.


  • Added: Strings for Magnetic Variation enum by mrbubble62


  • Added: PGN129033 Local offset


  • Port config ability for SockeCAN by Al Thomason


  • SetN2kSource for other devices by jpilet


  • Added: PGN130576 Small Craft Status / Trim Tab Position definition by Nicholas Agro


  • Fix: ParseN2kPGN129284, Index was not initialized to 0, which caused unpredictable read.


  • Fix: Fast packet sequence counter must be related to PGN.

  • Fix: TP message priorities.

  • Fix: On SetDeviceInformationInstances we need to send ISO address claim, not start adress claim.

  • Fix: Do not respond any queries during address claim.

  • Fix: Fixed some messages default priority.

  • Fix: Responce to Complex Group Function requests.

  • Fix: Now compiles with different compiler definitions defined on NMEA2000_CompilerDefns.h

  • Added: Support for sending messages by using Transport Protocol. This is mandatory for NMEA 2000

  • Updated: License to 2018


  • Changes effect only use of tN2kDeviceList and AttachMsgHandler callbacks.

  • Added FindDeviceByIDs to tN2kDeviceList

  • Fix: Devicelist did not handle right, if device changed its address higher.

  • Fix: PNG message handler order problem on tNMEA2000::AttachMsgHandler(tMsgHandler *_MsgHandler);

  • Fix: If there was NMEA2000 library device with same name, they handshaked both addresses to null. The problem still appears, if both devices will be started at same time. I need to add some random start delay

  • Cleaned spaces from end of lines on updated code.


  • Added PGN 128000 Leeway to N2kMessages.h/.cpp

  • Fix: Spelling WaterRefereced → WaterReferenced on N2kMessages.h/.cpp


  • Fix some build errors due to missing include statements (did not affect Arduino, only other platforms)


  • Fix: Default responces to Complex Group Function.


  • Added library.json, thanks for ronzeiller.


  • Fix: fill unused chars on fastpacket messages with 0xff

  • Fix: fill unused chars on message fixed sized strings with 0xff. One sample is e.g. PGN 126996, Product Information.


  • Changed tActisenseReader class to handle also Actisense N2k request message types. This type will be used by applications, which sends data through NGT-1.

  • Updated related examples ActisenseListener and ActisenseListenerSender.

  • Renamed Min/Max to N2kMin/N2kMax, since Due code had definitions for Min/Max


  • Added PGN validity check to the SendMsg()

  • Changed max/min → own Max/Min. max/min defines does not exist on other systems and Arduino does not have std <Algorithm> for all boards.


  • Fix: PGN 126992 TimeSource handling.

  • Fix: Added missing wind reference type.


  • Added range parameter for depth PGN 128267.

  • Added millis() time stamp to N2kMsg clear text Print.

  • Now responces also Group Function request for PGN lists PGN 126464

  • Now responces also Group Function request for Product Information PGN 126996

  • Now responces also Group Function request for Configuration Information PGN 126998

  • Fix: spelling Sertification → Certification

  • Fix: on changing SystemInstance reseted DeviceInstance

  • Fix: "Group function" responces according to tests with certified Airmar DST800

  • Fix: Address claiming could go up to 253 and did not went to "cannot claim". Now, if address cannot be claimed, goes to "cannot claim state" and prevents all message output except ISO address claim.

  • Fix: fast packet response for less than 7 data bytes caused two frames.


  • Fixed PGN 128259 parser SOG data type.

  • DataDisplay2 example update.


  • Support for changing configuration information fields InstallationDescription1 and InstallationDescription2 on runtime e.g. with NMEA Reader. Meaning of those fields is define their "installation description". So if you have two engine monitor devices, you can set e.g. InstallationDescription1 field to "Port engine" for one and "Starboard engine" for other. So it is not necessary to hardcode those setting. Of coarse your code must support parameter saving to e.g. EEPROM as with other parameters (see ReadResetInstallationDescriptionChanged, ReadResetAddressChanged and ReadResetDeviceInformationChanged). I have example under construction for handling parameter changes.

  • Changed some indexes to size_t. This may effect compatibility, if you have used those functions.



  • Fixed setting device instances on N2kGroupFunctionDefaultHandlers

  • Fixed wind PGN 130306 output with reserved field.

  • New abstract class tNEMA2000:tMsgHandler and functions AttachMsgHandler/DetachMsgHandler. With these you can have multiple handlers. It also allow PGN specific handlers. See how it has been used on example DeviceAnalyzer. Other simple example is under construction.

  • New class tN2kDeviceList. See more on library reference and on example DeviceAnalyzer.

  • Improved message type checking. This will be done for every message, so speed in important. For Arduino Mega average test time was dropped from about 90 us to 9 us and for Teensy from 3.5 us to 0.9 us.

26.06.2017 Example updates

  • ActisenseListenerSender can be used to listen and send data to NMEA 2000 bus. This is almost same as TeensyActisenseListenerSender, but read and forward ports can be chosen with #define.

  • ActisenseListener uses now SetN2kCANReceiveFrameBufSize.

  • Removed FromPCToN2k. ActisenseListenerSender replaces this.

25.06.2017 Fix and cosmetic changes

  • ForwardStream initialization was accidentaly deleted

  • Clean code and more debug options.

22.06.2017 Fixes and cosmetic changes

  • Crashed, if ForwardStream was not defined. I accidentaly forgot to comment some debug code.

  • Definition of tDeviceInformation changed to fixed sized data so that compiler can not mix them.

  • Added debug definitions to avoid first bug.

  • Some cosmetic changes and tests.

19.06.2017 Changes due to different revisions of FlexCAN library for Teeansy boards. NOTE! You must update NMEA2000_Teensy library. I also forked and developed FlexCAN library from collin80 and also send pull request for him. Until updated there my fork has more features for use with NMEA2000 library.

13.06.2017 NOTE! Some compatibility changes.

  • !NOTE compatibility change. tProductInformation has been moved inside tNMEA2000 class. If you have defined tProductInformation to PROGMEM as in example BatteryMonitor, you need to change definition const tProductInformation…​ to const tNMEA2000::tProductInformation…​ See example BatteryMonitor.

  • Multi device support should work now. So you can show several devices on bus with single hw. See example MultiDevice.

  • !NOTE compatibility change. tDeviceInformation has been moved inside tNMEA2000 class. This was used only internally until 11.06.2017 release.

11.06.2017 Added NMEA 2000 mandatory features. Some bug fixes.

  • !NOTE compatibility change. PROGMEM configuration information did not work and actually wasted RAM. You should define each configuration information string alone as PROGMEM and call changed SetProgmemConfigurationInformation. See sample BatteryMonitor

  • Due to new mandatory features library requires more RAM and program memory. It is possible to squeeze requirements with compiler options. See more info on NMEA2000_CompilerDefns.h.

  • Added new class tN2kGroupFunctionHandler (N2kGroupFunction.h/.cpp) for NMEA 2000 group function (PGN 126208) handling. Group function can be used to e.g. to set "temperature instance" or "set temperature" fields on PGN 130316.

  • Added automatic Heartbeat, which is mandatory for certified NMEA 2000 devices. If you do not want it to be sent, you have to set heartbeat interval to 0. Added also function SetHeartbeatInterval, GetHeartbeatInterval and SendHeartbeat.

  • Added group function handling for PGN 60928 (ISO Address) and PGN 126993 (Heartbeat). Handlers can be found on N2kGroupFunctionDefaultHandlers module.

  • Added functions ReadResetDeviceInformationChanged, SetDeviceInformationInstances, GetDeviceInformation for checking, setting and reading device instance changes. See more info on document.

  • Added ISO Multi-packet handling. Changed logic on SetN2kCANBufMsg due this.


  • Added PGN 130314 by sarfata.

  • Added PGN 127245 rudder parser

  • Fixed Device Information, last bit must be set to 1

  • Fixed response to ISO Address Claim request. Seems that all new devices respond allways with broadcast instead of caller address.


  • Changed default NMEA2000 variable definition in NMEA2000_CAN.h to reference. So now it is possible to refer it in other modules with definition: extern tNMEA2000 &NMEA2000;


  • Added Binary status report (PGN 127501) handling. See updated examples MessageSender and DataDisplay2.


  • Added PGN 129539 support and PGN 129283, 129284 parsers by denravonska.


  • Debug mode check for DeviceReady and ParseMessages.


  • RPi socketCAN auto selection and MBED compiler portability fix by thomasonw.


  • Fixed Heading PGN 127250 parsing


  • Replace pointer casting with memcpy to avoid unaligned access, and add endian support. Thanks to denravonska.

  • Handle for PGN 65240 "Commanded address". E.g. diagnostic device may command your device to change address.


  • Document and some example fixes to match library portability changes.


  • Added support for PGN 126464L, PGN List (Transmit and Receive). Library will automatically respond to this message. You need only add message lists and call to methods ExtendTransmitMessages and/or ExtendReceiveMessages. See e.g. example TemperatureMonitor.


  • Fixes to avoid compiler warnings


  • Portability fixes. Thanks to denravonska and thomasonw!

  • NOTE! compatibility issue! There is no more default stream set on library constuctor. So in case you are using forwarding, you need to setup it (like in examples) NMEA2000.SetForwardStream(&Serial);

  • This reduces the Arduino dependency, allowing the library to more easily be used on other platforms. Check all changes under #35


  • License change to MIT for more permissive

  • Also some started to remove platform dependent code.


  • PGN129025 parser added and some fixes by KimBP


  • Added support for PGN 127258 - magnetic variation by adwuk.


  • Added parsing for PGN 130311 by adwuk. Typo fix for system date comment by sarfata.


  • Lot of testing behind - hopefully works now better.

  • NOTE! New method SetN2kCANSendFrameBufSize. Added buffer for frames to be sent. This takes more RAM and may be critical for low RAM systems.

  • If frame sending fails, system now buffers frames to be sent automatically and tries to resend them on next call for ParseMessages. With this feature it solved my problem that time to time my MFD could not receive important GNSS or SOG/GOG messages and informed error.

  • System now also has more reliable response to the Product Information ISO request (PGN 126998). Unfortunately if your system does not poll often enough incoming messages (ParseMessages), you still may loose the request itself. This is specially the case if you system spends some time reading sensors like 1-wire system. Even with 1-wire asynchronous read, it may spend 10 ms interrupts disabled. Within 10 ms there may be about 30 messages on bus.

  • New methods SetConfigurationInformation and SetProgmemConfigurationInformation. System can now also handle Configuration Information ISO request to (PGN 126998). Default configuration information is saved to PROGMEM.

  • NOTE! Reload also NMEA2000_due!


  • Temporary fix for problem to respond product information ISO request.


  • Thanks for people (usauerbrey, OzOns), who noted below problems

  • NOTE! If you are using NMEA2000_can, remember to update that too!

  • Fix for ISORequest handling. Now responds allways also for broadcasts.

  • Some fixes to avoid compiler warnings.

  • Fix for parsing PGN 127257/Attitude


  • NOTE! Fixed PGN 130310, PGN 130311 and added SetHandleOnlyKnownMessages(), which effects backward compatibility. See below.

  • NOTE! On PGN 130310 and PGN 130311 description says that "Atmospheric pressure in Pascals. Use function mBarToPascal". There was scaling error and now they works like description. After update you have to provide value on Pascals and really use mBarToPascal, if you have your value in mBar.

  • NOTE! Added SetHandleOnlyKnownMessages(). If you have called SetForwardOnlyKnownMessages(true), library did not handle unknown messages. After update, this effects only message forwarding - as it should have been. So call also SetHandleOnlyKnownMessages(true), if you want to disable any handling for unknown messages.

  • NMEA 2000 Library reference update.

  • Added ExtendSingleFrameMessages and ExtendFastPacketMessages. With these one can own list of known messages so that it is not necessary to duplicate message list as, if used only SetSingleFrameMessages and SetFastPacketMessages.

  • Added discrete status flags for transmission parameters (PGN 127493), thanks for testing Jason.


  • Added SetISORqstHandler for setting handler for ISO requests. Thanks thomasonw.


  • NMEA 2000 Library reference update.

  • Added example TeensyActisenseListenerSender. Example contains code, schematics and document.


  • Fixed discrete status on engine dynamic parameters (PGN 127489), thanks Jason.

  • Added new PGN 127257, vessel attitude. Only sending has been tested with NMEA Reader


  • Added to API — Optional message lists by thomasonw


  • Corrected Battery Current in ParseN2kPGN127508 by thomasonw.


  • Additional PGN 129038, PGN 129039, PGN 129285, PGN 130074 support by adwuk.


  • Fix of using PROGMEM. Now also product information defined to PROGMEM works right.


  • Fix of using PROGMEM. Still does not work right with product information in PROGMEM. So all changes after 09.03 are still under validation.


  • More memory optimization - thanks for thomasonw. Constant message strings has been marked with F(…​) moving them to flash instead of RAM.

Note also that there is new function void tNMEA2000::SetProductInformation(const tProductInformation *_ProductInformation); So one can save memory by defining product information to flash by using syntax:

const tProductInformation BatteryMonitorProductInformation PROGMEM={
1300,               // N2kVersion

See example BatteryMonitor.ino


  • Memory tuning. Currently multi device and user definable message filters has not been implemented, so I changed buffer sizes to minimum.

  • There is also new function void tNMEA2000::SetN2kCANMsgBufSize(const unsigned char _MaxN2kCANMsgs); to define buffer size for received N2k messages. Note that library has to collect fast packet frames, which may arrive fragmented from different devices, so as default this buffer size has been set to 5. If your device is only sending some data (mode is tNMEA2000::N2km_NodeOnly), you do not need to catch all fast packet messages (if any), so you can set buffer size smaller.


  • Additional PGN 127250, PGN 128275 Support by adwuk.


  • AVR CAN support by thomasonw.


  • NOTE! Updates, which effects backward compatibility. See list below.

  • PGN 127489, SetN2kPGN127489 EngineOilTemp and EngineCoolantTemp is in Kelvins as in other temperature functions. So add for call to this function CToKelvin(…​)

  • Some function names withing N2kMessages have been changed. Change function names listed below!
    SetN2kPGNSystemTime → SetN2kSystemTime
    ParseN2kPGNSystemTime → ParseN2kSystemTime
    SetN2kPGNTrueHeading → SetN2kTrueHeading
    SetN2kPGNMagneticHeading → SetN2kMagneticHeading

  • Variable types has been changed on some functions in N2kMessages. So when you get an compiler error about functions in N2kMessages, check carefully all parameter definitions for function from N2kMessages.h.

  • If you do not have value for some parameter for functions in N2kMessages, use related N2kxxxxNA constant defined in N2kMsg.h. So e.g. if you only have wind speed, call
    SetN2kWindSpeed(N2kMsg, 1, ReadWindSpeed(),N2kDoubleNA,N2kWind_Apprent);

  • If you are reading values from N2k bus, you can now check does some value exist by using function N2kIsNA. So if you e.g. call
    then check pressure value with
    if ( !N2kIsNA(AtmosphericPressure) ) { // It is available, so we can show it!

  • Added reference document to the documents, which hopefully helps to get started.


  • Added PGN 127493 support. NMEA2000_mcp has now interrupt support. Some other fixes.


  • Added some comments to samples and several new message readers. Also added support for 130316 extended temperature. Added new include N2kMessagesEnumToStr.h for translating library enums to clear text. This is now just for preliminary so I may changes texts in coming future. Added also new examples DataDisplay2.ini and MessageSender.ino. They are extended versions of DataDisplay.ino and TemperatureMonitor.ino.


  • Added NMEA2000_CAN.h and some fixes. Library has been originally developed with Arduino Software 1.6.5 On Arduino Software 1.6.6 it is possible to include libraries within included files, so now it is possible to just include one file NMEA2000_CAN.h, which automatically selects right CAN library according. So you can have same code for different hw. Currently supported CAN libraries are mcp_can, due_can and teensy. Note! NMEA2000_CAN.h is now used on examples TemperatureMonitor and WindMonitor!

Memory requirements

I have tried to measure memory used by library, but it is not so simple, since there are some automated operations. With version 11.06.2017 I got results:

  • Approximate ROM 26.9 kB

  • Approximate RAM 3.4 kB

This is with simple TemperatureMonitor example. This can be squeezed by setting:

  • Add below to setup() before NMEA2000.Open();

  • Defining ProductInformation to PROGMEM as in BatteryMonitor example.

  • Disabling all extra features. See NMEA2000_CompilerDefns.h

  • Disable interrupt receiving.

With those setting you can go down to appr. 19 kB ROM and 1.9 kB RAM. So for 2 kB devices like Arduino Uno, there is not much for your own code.

Note! By squeezing memory, library can not fullfill certification requirements anymore.

Hardware setup

NMEA2000 is inherited from CAN. Many MCUs like Teensy >3.1, ESP32, Arduino Due has already CAN controller inside. If your MCU does not have CAN controller inside or you need second external CAN controller, you can use e.g. MCP2515 CAN controller, which is supported by library (mcp_can).

For final connection to the bus you need CAN bus_transceiver chip. Devices on NMEA2000 bus should be isolated to avoid ground loops. So if you take power from NMEA2000 bus and your device is not connected to ground enywhere else, you can use unisolated tranceiver like MCP2551, MCP2562 or SN65HVD234. If you instead feed power to your device directly or e.g. use engine own sensors for measuring, you have to use isolated tranceivers like ISO1050. Remember also use isolated power supply, if you take power from bus and have any unisolated connection to anywhere on your whole system.

Easiest for connecting to NMEA2000 bus is to use some ready shield.

In case you build your tranceiver connection by yourself there are some connection examples under documents.

Library has been also used with Maple Mini board.

Software setup

You need at least Arduino Software 1.6.6 for this sample. I’ll expect you are familiar with Arduino and using libraries. When your Arduino environment is ready,

  • Download NMEA2000 library zip.

  • Depending of your board download libraries as zip:

  • Install all libraries to your Arduino IDE (Sketch-Include Library-Add .ZIP library).

  • Open NMEA2000\Examples\TemperatureMonitor.

  • Connect you board to USB and NMEA2000 bus.

  • Send sketch to your board.

  • If you have Multi Function Display (e.g. Garmin GMI-20) on your NMEA2000 bus, you should see on it’s NMEA2000 bus devices new device "Simple temp monitor" on the list.

Now you are ready to play with your own device. Check also the NMEA2000\Examples\ActisenseListener, which reads all data from NMEA2000 bus and sends it to PC. NMEA2000/Examples/ArduinoGateway allows you to mimic Actisense NGT-1 and connect e.g. a Raspberry Pi running Signal-K to the NMEA2000 bus with an Arduino or Teensy.

Forcing CAN "driver" (was using Arduino Software older than 1.6.6)

In examples there are simple includes:
#include <Arduino.h>
#include <NMEA2000_CAN.h> // This will automatically choose right CAN library and create suitable NMEA2000 object

If that can not be used (like with Arduino IDE older than 1.6.6) or you would like to control naming and used "driver", you can manually include necessary files. Specially if you want to use secondary CAN bus on your system.

For use with Teensy 4.x (also with 3.1/3.2/3.5/3.6)

#include <N2kMsg.h>
#include <NMEA2000.h>
#include <NMEA2000_Teensyx.h> //
tNMEA2000_Teensyx NMEA2000;

For use with Teensy 3.1/3.2/3.5/3.6 board and FlexCan

#include <N2kMsg.h>
#include <NMEA2000.h>
#include <FlexCAN.h>
#include <NMEA2000_teensy.h> //
tNMEA2000_teensy NMEA2000;

For use with ESP32

#include <N2kMsg.h>
#include <NMEA2000.h>
#include <NMEA2000_esp32.h> //
tNMEA2000_esp32 NMEA2000;

For use board with MCP2515 SPI can bus tranceiver and mcp_can library

#include <N2kMsg.h>
#include <NMEA2000.h>
#include <SPI.h>
#include <mcp_can.h> //
#include <NMEA2000_mcp.h>
#define N2k_CAN_INT_PIN 21 // Pin, where interrupt line has been connected
#define N2k_SPI_CS_PIN 53  // Pin for SPI Can Select
tNMEA2000_mcp NMEA2000(N2k_SPI_CS_PIN,MCP_16MHz,N2k_CAN_INT_PIN);

For use with Arduino due and due_can library

#include <N2kMsg.h>
#include <NMEA2000.h>
#include <due_can.h>  //
#include <NMEA2000_due.h>
tNMEA2000_due NMEA2000;

For use with Atmel AVR processors internal CAN controller

#include <N2kMsg.h>
#include <NMEA2000.h>
#include <avr_can.h>            //
#include <NMEA2000_avr.h>       //
tNMEA2000_avr NMEA2000;


MIT license

Copyright (c) 2015-2022 Timo Lappalainen, Kave Oy,

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.



NMEA2000 library for Arduino






No releases published


No packages published