Go Down

Topic: NMEA 2000 Shield (Read 409403 times) previous topic - next topic



I have a problem getting messages from a sketch shown on  Garmin GNX MFD. I use Arduino Due for sending messages. Some messages but not all are shown on MDF and all are shown on Actisense reader if I listen traffic with another DUE with ActisenceListener loaded on. Also the messages that are not shown on MDF from my sketch are shown when I load MessageSender to Arduino Due. Any ideas what to try to get COG, SOG, LON, LAT and System time to be shown on MFD?



- Check that you use right sending period. Some periods has been listed on NMEA2000.cpp. I have not yet published file with new comments. Here are some you need:
                                      case 129025L: // Lat/lon rapid, pri=2, period=100
                                      case 129026L: // COG SOG rapid, pri=2, period=250

- Try to send also GNSS message in every 1000 ms.

- There may be some other GPS related message, what Garmin expects. E.g. Raymarine autopilot did not work without varaiation PGN 127258


Update and solution for my problem reported earlier.

I uninstalled and re-installed Arduino 1.8.8. Then re-installed Teensyduino and unchecked the FlexCan library. Rebuild the MessageSender and tried again. Still same failure. (PGN send failed)

Then build a second set with Teensy 3.6 and MCP2562(on new print). Loaded MessageSender and it worked OK!!!

Then unsoldered my first set. While doing so, found that the printed connection to the CANH was broken. Now it became clear to me why this print would only work with the ground connected to the NMEA2000 ground.

Problem: With only ground and CANL connected, receiving N2k messages is OK. Sending however, is impossible.

Solution: Make sure CANH is connected to pin7 of MCP2562.



I'm having little bit trouble with my Arduino Due with mcp2515. In my setup i'm sending data to can bus with Arduino Mega and can-bus module (2515 and 2551). Serial monitor shows data packets correctly for some time and after around 20 secods it will start to print "Failed to send" (attached picture)

In the same bus I have also arduin Due with another 2515+2551 module. In Due I'm running default ActisenseListener. Due serial monitor indicates: "Initialize buffers" & "CAN device ready". In Can shield on Due, the RX led is constantly glowing and no data is received or shown in serial monitor.

Code in my arduino mega is shown below:
Code: [Select]
#include <NMEAGPS.h>

#include <DFRobot_sim808.h>
#include <sim808.h>
#include <Arduino.h>

#define N2k_SPI_CS_PIN 53

#include <NMEA2000_CAN.h>  // This will automatically choose right CAN library and create suitable NMEA2000 object
#include <N2kMessages.h>
#include <dht.h>

#include <GPSport.h>

#define DHT22_PIN A0
#define MESSAGE_LENGTH 160
#define phone_no "+35850xxxx"

#define TempUpdatePeriod 10000
#define GPSUpdatePeriod 1000
#define CourseUpdatePeriod 1000
#define FluidUpdatePeriod 10000

dht DHT;

// List here messages your device will transmit.
const unsigned long TransmitMessages[] PROGMEM = {130311L, 129284L, 0};

char message[MESSAGE_LENGTH];
int messageIndex = 0;

char c;
char phone[16];
char datetime[24];
double seconds;
double days;

const int sim808_status_led = 8;// the number of the LED pin
const int gps_status_led = 9;// the number of the LED pin

#define DEV_TEMP 0
#define DEV_GPS  1

DFRobot_SIM808 sim808(&Serial2);

NMEAGPS  gps; // This parses the GPS characters
gps_fix  fix; // This holds on to the latest values

void setup() {
  pinMode(sim808_status_led, OUTPUT);
  pinMode(gps_status_led, OUTPUT);
  // Set Product information
  NMEA2000.SetDeviceCount(2); //device count

  NMEA2000.SetProductInformation("100", 100, "Temperature", DEV_TEMP);
  NMEA2000.SetProductInformation("101", 100, "GPS", DEV_GPS);
  // Set device information
  NMEA2000.SetDeviceInformation(100, 130, 75, 2040, DEV_TEMP);
  NMEA2000.SetDeviceInformation(101, 145, 60, 2041, DEV_GPS);

  while (!Serial)
  Serial.print( F("Tiiulii_V2.ini: started\n") );

  digitalWrite(sim808_status_led, HIGH);
  while(!sim808.init()) {
  digitalWrite(sim808_status_led, LOW);
  //******** Initialize sim808 module *************

   if( sim808.attachGPS()){
        Serial.println("Open the GPS power success");
        digitalWrite(gps_status_led, HIGH);
        Serial.println("Open the GPS power failure");

  // If you want to use simple ascii monitor like Arduino Serial Monitor, uncomment next line
  NMEA2000.SetForwardType(tNMEA2000::fwdt_Text); // Show in clear text. Leave uncommented for default Actisense format.

  // If you also want to see all traffic on the bus use N2km_ListenAndNode instead of N2km_NodeOnly below
  NMEA2000.SetMode(tNMEA2000::N2km_NodeOnly, 22);
  //NMEA2000.SetDebugMode(tNMEA2000::dm_Actisense); // Uncomment this, so you can test code without CAN bus chips on Arduino Mega
  //NMEA2000.EnableForward(false); // Disable all msg forwarding to USB (=Serial)
  // Here we tell library, which PGNs we transmit

//beginning of loop
void loop() {
  while (gps.available(Serial2)) {
    fix = gps.read();

    days = parseTimeDate();
    seconds = parseTimeSeconds(fix.dateTime.hours, fix.dateTime.minutes, fix.dateTime.seconds); 



double ReadCabinTemp() {
  int readData = DHT.read22(DHT22_PIN);
  return CToKelvin(DHT.temperature); // Read here the true temperature e.g. from analog input

double ReadCabinHumidity() {
  return DHT.humidity;

void SendN2kTemperature() {
  static unsigned long TempUpdated = millis();
  tN2kMsg N2kMsg;
  if ( TempUpdated + TempUpdatePeriod < millis() ) { 
    TempUpdated = millis();
    SetN2kEnvironmentalParameters(N2kMsg, 2, N2kts_MainCabinTemperature, ReadCabinTemp(), N2khs_InsideHumidity, ReadCabinHumidity());
    NMEA2000.SendMsg(N2kMsg, DEV_TEMP);

void SendN2kGPS() {
  static unsigned long TempUpdated = millis();
  tN2kMsg N2kMsg;
  if ( TempUpdated + GPSUpdatePeriod < millis() ) {
    TempUpdated = millis();
    SetN2kGNSS(N2kMsg, 1, days, seconds, fix.latitude(), fix.longitude(), fix.altitude(), 0, 0, fix.satellites, fix.hdop, 0, 0);
    NMEA2000.SendMsg(N2kMsg, DEV_GPS);

void SendFluidLevel() {
  static unsigned long FluidUpdated = millis();
  tN2kMsg N2kMsg;
  if ( FluidUpdated + FluidUpdatePeriod < millis() ) {
    FluidUpdated = millis();
    SetN2kFluidLevel(N2kMsg, 3, 1, 66, 300);

void SendCourseRapid(){
  static unsigned long CourseUpdated = millis();
  tN2kMsg N2kMsg;
  if ( CourseUpdated + CourseUpdatePeriod < millis() ) {
    CourseUpdated = millis();
    SetN2kCOGSOGRapid(N2kMsg, 1, 0, fix.heading(), fix.speed_kph()/3.6);

void SendSMS() {
  Serial.print("Sending sms");
  //sim808.sendSMS(phone_no, "test");

double parseTimeDate(){
  uint32_t timestamp = (NeoGPS::clock_t) fix.dateTime;
  timestamp = timestamp + 946684800;
  return (timestamp/3600/24);

double parseTimeSeconds(uint8_t d_hour, uint8_t d_minute, uint8_t d_second){
  uint32_t temp2;
  temp2 = ((d_hour+2)*3600L) + (d_minute * 60) + d_second;
  return temp2;

Is there something I'm doing wrong with Arduino Due or perhaps with Arduino Mega? Shouldn't Due show all the data Mega is sending to the bus?


First. Why do you use 2515+2551 pair for DUE? Due has internal CAN, which I prefere to use with MCP2562. On documents there is picture for wireing.

If you anyway want to use 2515+2551 pair with due, you have to force library to use mcp_can instead of default due_can. This you do by adding
Code: [Select]
#define USE_N2K_CAN 1
before include NMEA2000_CAN.h. Then you also need to define cs and interrupt pin definition by including
Code: [Select]
#define N2k_SPI_CS_PIN xx
#define N2k_CAN_INT_PIN xx

and possible clock set, if your 2515 clock is not default 16MHz
Code: [Select]
All before include.

If you see message "Initialize buffers" & "CAN device ready", it means that library has managed to initialize CAN device. Anyway in your case it has initialized DUEs internal CAN, not your 2515+2551.

As I have mentioned in some other post that you get "Failed to send", when device can send data to the bus. Library has internal buffer for messages, and when that gets full you get "Failed to send". So if you get that continuously after some time, you have problem with bus connection. This can be caused by forgetting terminal resistors, mixing CANH/CANL, burned tranceiver, invalid wireing CANTx (as in previous post by Pim57).

Finally note that you can not use what ever period you like for sending. It works between your own devices, but MFDs often expect standard periods and if they do not receive message within period, they may give up and give warning:
129026UL // SOG COG rapid, pri=2, period=250
127505UL // Fluid Level, pri=6, period=2500
130311UL // Environmental parameters, pri=5, period=500
Note also that other devices may have funny relations between messages. So with GPS you may need to send also:
129025UL: // Lat/lon rapid, pri=2, period=100


Hi Timo,

Thank you for your help. Use of 2515 and 2551 with Arduino Due is fully because lack of 2562 chip. Already ordered 2562 but not yet received.

I implemented changed you suggested to Ardino Due. However, when compiling, next error appears:

Code: [Select]
C:\Users\Hirppa\Documents\Arduino\libraries\NMEA2000_mcp-master\NMEA2000_mcp.cpp: In member function 'virtual bool tNMEA2000_mcp::CANSendFrame(long unsigned int, unsigned char, const unsigned char*, bool)':

C:\Users\Hirppa\Documents\Arduino\libraries\NMEA2000_mcp-master\NMEA2000_mcp.cpp:98:24: error: 'SREG' was not declared in this scope

     uint8_t SaveSREG = SREG;   // save interrupt flag


C:\Users\Hirppa\Documents\Arduino\libraries\NMEA2000_mcp-master\NMEA2000_mcp.cpp:101:11: error: 'cli' was not declared in this scope

       cli();   // disable interrupts


C:\Users\Hirppa\Documents\Arduino\libraries\NMEA2000_mcp-master\NMEA2000_mcp.cpp: In member function 'virtual bool tNMEA2000_mcp::CANGetFrame(long unsigned int&, unsigned char&, unsigned char*)':

C:\Users\Hirppa\Documents\Arduino\libraries\NMEA2000_mcp-master\NMEA2000_mcp.cpp:167:26: error: 'SREG' was not declared in this scope

       uint8_t SaveSREG = SREG;   // save interrupt flag


C:\Users\Hirppa\Documents\Arduino\libraries\NMEA2000_mcp-master\NMEA2000_mcp.cpp:168:11: error: 'cli' was not declared in this scope

       cli();   // disable interrupts


exit status 1
Error compiling for board Arduino Due (Programming Port).


Please replace file NMEA2000_mcp.cpp in directory libraries/NMEA2000_mcp with attached file. I have not published it, since I currently have no way to test modifications. It should work, since only use of SREG and cli/sti has been replaced.


Hi Timolappalainen,

I'm a noobs.

I have a rpi 3 and a module MCP2515/TJA1050 (mod for 3.3/5v).

I saw the guide to prepare the raspberry, but I didn't understand in step 2 when you talk about the drivers in step 1.

Would you explain the procedure it step by step for read from nmea 2000?


Thank you



Taht document was written by someone else. But did you check the documents pointed on step 1? E.g. http://www.skpang.co.uk/catalog/images/raspberrypi/pi_2/PICAN2_jessie_2016-05-10.pdf


Mar 24, 2019, 08:46 am Last Edit: Mar 24, 2019, 08:48 am by Bsense
Dear NMEA2000 experts and demigods (Timo) out there,

I am trying to develop my first electronic module for N2K. I have it ready with an esp32 wemos r32 module. I attached to it a galvanic isolator max12931 and a 2562. A few spare parts were also needed to adjust the power for the can transceiver stage as a result of the isolation.

Anyway the doubt i have is about the n2k simulator. Reading the docs the gratest of us all (yes, Timo) has published it seems that in order to have a full simulator we need two physical serial ports. One for Nmeareader (actisense's) and another one for Kvaser n2k sender. However, when i do check the code it seems that it might be feasible with a single port. In the case i still needed both i even thought that instead of a polulu usb board i could use the bluetooth serial service that esp32 has available.

So. How do I debug my gadget with n2k reader and sender at the "same" time? Are two serial (usb comm) ports required or a single suffices?

Thank you so much!

PS: Hopefully i will not be charged for the use of  NMEA... at the beginning


I wrote simulator originally only for sending and have only as plans to extent it. But before that you need two different ports.

There is also virtual com splitter hub4com, which I use for other purposes. I have not tested could that be used with ActisenseListenerSender so that example reads and writes to same port, which would be then splitted with hub4com for Actisense Reader and Simulator. It should, since my use is pretty similar. That may also depend of hw, since when I started some years a ago with Mega and Due, I had problems to get ports reliably working both directions with lot of traffic.

During developing I have several Teensys on same bus - one listening with Actisense Reader, one sending with simulator, one filling up bus traffic as standalone, one just for proofing address claiming and naturally the devie under development, some devices (MFD, log) from boat in winter time. So the bus is pretty full of traffic to test that library and other code works. In this way do cross checking for devices and library code.

For real testing I prefer to use separate devices.

By the way, where you got the name Kvaser? I have never used those devices and simulator supports only Actisense format on sending.


Hi Timo,
I try the library with an arduino mega and works ok with my raymarine a98 mfd, but when I do a scan device on the mfd the arduino didn't appear ,I try also with raymarine manufacturer code.
I notice with Nmea reader the Product Information is not tx as you can see in attached screenshot,only device information are sent
Maybe the 2 problem are connected?
Any solution?


In principle every MFD should see request product information, when any device informs itself on the bus. I have noticed that all devices does not do that. You could try to send product information in every 2 sec with command
Code: [Select]
NMEA2000.SendProductInformation to see does that make any difference. If it works it may still mean that there is something wrong, but we get a bit more information.

If you have real Actisense NGT-1, that is very strich and request information from all devices.


In principle every MFD should see request product information, when any device informs itself on the bus. I have noticed that all devices does not do that. You could try to send product information in every 2 sec with command
Code: [Select]
NMEA2000.SendProductInformation to see does that make any difference. If it works it may still mean that there is something wrong, but we get a bit more information.

If you have real Actisense NGT-1, that is very strich and request information from all devices.
Hi Timo,
when try to add the command NMEA2000.SendProductInformation; I have an error "Arduino: 1.8.5 (Windows XP), Board: "Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"



exit status 1
statement cannot resolve address of overloaded function



Go Up