NMEA 2000 Shield

Could you to disable interrupt. Then it will be totally poll based. You should have on the beginning

define N2k_CAN_INT_PIN xx

Comment that so it will set interrupt as default to disabled. This is not solution, but gives a bit more information.

I use pin D1/gpio5 for the interrupt function.

Did as suggested and commented out this #Define int pin 5 line and to my surprise is works now powering up onto an active bus with a few N2K messages. Also the built-in led no longer flashes slowly as before, it's mostly always on

Thanks Ross

Try next.

Enable interrupt back. Then modify NMEA2000_mcp.cpp from line 152 or where you find line if (IsOpen && UseInterrupt() ) {

    if (IsOpen && UseInterrupt() ) {
      cli();
      N2kCAN.enableTxInterrupt();
      attachInterrupt(digitalPinToInterrupt(N2k_CAN_int_pin), Can1Interrupt, FALLING);
      InterruptHandler(); // read out possible data to clear isr bit.
      sei();
    }

The problem has something to do with enabling interrupt on wemos. So my quess here is that when there is already data on mcp, wemos does not generate interrupt on attachInterrupt, since pin is down and so does not fall.

Good news to report, tested both Actisense Listener & Listener/Sender examples and both work well starting up onto an active N2K bus or an inactive N2K bus. Works well as a Listener for Serial.printing in both plain text as well as Actisense format. Still need to test as a Sender but I suspect that it will work well as before.

I wonder if these new library changes have affected the performance for the Mega2560/Mcp2515 hardware, I can test later this week. Are you planning to release an official revision to the existing NMEA2000_MCP library which is compatible with multiple platforms or something ESP8266 (WemosD1Mini) specific ?

Many thanks Timo Ross

It should not. The last fix is only for start. It has been lucky that it has been working with other chips. Using SREG instead of cli()/sei() just prevent problem in case of concurrent calls. If you would have in your code:

cli();
NMEA2000.ParseMessages();
// do something with data shared with interrupts here
sei();

You would be in trouble, since ParseMessages() goes to check buffers and does cli() and sei() too. So when it returns, interrupts has been already enabled and the next data handling could not be done safely. If the same will be done by using SREG, library will not turn interrupts on, since it returns state of interrupts within call and that was disabled before by your cli() call.

Yes, I'll publish this and change use of SREG with define so that mega will have it. But even use cli/sei for all will only cause problem with stacked calls of cli/sei as I describe above. I think it is rather rare case.

Let me know if you would like me to do more tests

Thanks

First of all, thanks Timo for a great job with this NMEA2000 work. I am succesfull with building a datalogger for a B&G Vulcan 7, that writes data every 5 minutes to a SD card on a Teensy 3.6. Works great!!

Now my question on sending data on the N2K bus. I tried the examples WindMonitor and MessageSender, but they don’t send any data. I enabled monitoring and see after a while that the PGN’s report error. Looks to me like it takes some time to fill up a buffer?
Next i tried the ActisenseListenerSender with the NMEA_Simulator. And also here no data on the bus. When i disble the Simulator and reconnect the NMEAReader i notice a slow down. Messages like PositionRapidUpdate are no longer updated every 0.10 secs, but take much longer. Same for other messages that normale come every second.

Next i compared the ActisenseListener with the ActisenseListenerSender.
When i use ActisenseListener with NMEAReader all messages keep appearing fast and never slow down. (See attached)
When i use ActisenseListenerSender with NMEAReader all messages start slowing down after half a minute or so. (see attached)

I suspected hardware and bought a new Teensy 3.6 and new MCP2562 (and yes pin8 is connected to ground to enable transmit data)

Any ideas what might cause the slowing down? And second why the Teensy won’t transmit data?

Acti-1.jpg

acti-2.jpg

  • Missing termination resistors. This causes funny problems.
  • Tranceiver not enabled. Check seventh time that pin 8 is really connected to ground.
  • TxD pin 1 and CANTX Teensy pin 3 wire broken, not connected or connected to wrong pin. Note that you must use pin 3 on Teensy. If you use alternative pin, it requires some modifications.

Thx for your prompt response.

  • measured 60 ohms on the CAN bus
  • dubble checked ground on pin 8 of MCP2562
  • replaced wire between Teensy pin 3 (CAN0TX) and pin1 on MCP2562

Still same problem. I am running out of ideas.

Maybe try CAN1TX and CAN1RX on pin 33 and 34? But that would require some code changes, where and what?

MessageSender or WindMonitor should send data for sure. I use those for testing time to time. I normally use ActisenseListenerSender only for sending and ActisenseListener with NMEA Reader. Note that if you use NMEA Simulator, you mus be aware of addresses. Currently Simulator does not do address claiming, so devices with same address may get crazy.

I just build up MessageSender with library code and tested on Teensy 35 and there is no problem. Did you took FlexCan from my Git and deleted one which comes with Teesyduino? Check that you do not have FlexCan under C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries

Hi,

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?

TY

  • 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.

Hello,

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:

#include <NMEAGPS.h>

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

#define USE_MCP_CAN_CLOCK_SET 8
#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);

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

  Serial2.begin(9600);
  digitalWrite(sim808_status_led, HIGH);
  delay(1000);  
  while(!sim808.init()) { 
      delay(1000);      
  }
  digitalWrite(sim808_status_led, LOW);
  
  //******** Initialize sim808 module *************

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

  NMEA2000.SetForwardStream(&Serial);
  // 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
  NMEA2000.ExtendTransmitMessages(TransmitMessages);
  NMEA2000.Open();
  
}

//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);  

    SendN2kGPS();
    SendN2kTemperature();
    SendFluidLevel();
    SendCourseRapid();
    
    NMEA2000.ParseMessages();
  }
}  
//FUNCTIONS

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);
    NMEA2000.SendMsg(N2kMsg);
  } 
}

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);
    NMEA2000.SendMsg(N2kMsg);
  } 
}


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?

port3.png

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

#define USE_N2K_CAN 1

before include NMEA2000_CAN.h. Then you also need to define cs and interrupt pin definition by including

#define N2k_SPI_CS_PIN xx
#define N2k_CAN_INT_PIN xx

and possible clock set, if your 2515 clock is not default 16MHz

#define USE_MCP_CAN_CLOCK_SET 8

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:

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.

NMEA2000_mcp.cpp (10.2 KB)

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?

Sorry.

Thank you

Greg

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

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