NMEA 2000 Shield

ok, thank you so much, i have another question.
when i send pgn127489 the arduino send me an error, this is the error("no matching function for call to 'SetN2kPGN127489(tN2kMsg&, int, double).
can you explain me how to solve that?

This is basic c/c++. Check the right syntax from N2kMessages.h. You must provide parameter values at least up to EngineHours. Rest parameters has default values.

Hi, I've got my ESP32 recently and after few days of using it I am a little bit confused. Let me explain.
In addition to Nmea2000 library I should use dedicated nmea2000 library for ESP32 right? But after reviewing it I see there are different methods for sending and receiving frames. And now the confusing part. The example NMEA2000ToNMEA0183 says that it has been tested with ESP32 so I am assuming the usual nmea2000 library works fine with ESP32. Correct me if I'm wrong. The question is why would I use library for ESP32. I don't need better performance. I just wanna make it work.

ESP32 and Teensy 3.2- has been used on certified commercial devices with NMEA2000 library, so for sure they works.

Library has inherited class for each different CAN controller. Inherited classes takes care of differencies of handling sending/receiving frames between different controllers. For ESP32 you use NMEA2000_esp32 module. If you use - as in examples - #include <NMEA2000_CAN.h>, it selects right module and class according compiler definitions. NMEA2000_CAN.h also creates global NMEA2000 object. If you want to control everything by yourself, you do not include NMEA2000_CAN.h. Then you must yourself include right controller module and create proper object, which you can even name e.g. N2k

Many thanks to WildBill for pointing out my missing handler issue. After successfully compiling I spent the better part of the weekend at my boat working on a variety of changes to my code in an attempt to get it to work, but I'm still stumped.

I'm convinced that the error is how I am reading the rudder data from N2K and tried many different changes. This is the last version that I tried. Note that I removed the 5 degree correction for now and I also initialized "RudderAngleCorrect" to 40 degrees for troubleshooting purposes (I also tried 0 degrees). I can add the 5 degree correction in after figuring out the basic issue of why I am not reading the data correctly.

No matter what I tried the angle that shows up on my MFD is the value that I initialized "RudderAngleCorrect" to be. As I mentioned, I tried a variety of changes in how I am attempting to read the AngleOrder data and then saving that to the variable with no luck. Can someone please provide me some additional tips?

// Demo: NMEA2000 library. Send rudder position data to the bus.

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

//int RudderAngle{20};
int RudderAngleCorrect{40};

// Messages the device will transmit and receive.
const unsigned long TransmitMessages PROGMEM={127245L,0};
const unsigned long ReceiveMessages PROGMEM={127245UL,0};

typedef struct {
unsigned long PGN;
void (*Handler)(const tN2kMsg &N2kMsg);
} tNMEA2000Handler;

void Rudder(const tN2kMsg &N2kMsg);

tNMEA2000Handler NMEA2000Handlers={
{127245L,&Rudder},
{0,0}
};

void setup() {
// Set Product information
NMEA2000.SetProductInformation("00000002", // Manufacturer's Model serial code
100, // Manufacturer's product code
"Rudder Position", // Manufacturer's Model ID
"1.1.0.22 (2016-12-31)", // Manufacturer's Software version code
"1.1.0.0 (2016-12-31)" // Manufacturer's Model version
);
// Set device information
NMEA2000.SetDeviceInformation(1, // Unique number. Use e.g. Serial number.
155, // Device function=Atmospheric. See codes on http://www.nmea.org/Assets/20120726%20nmea%202000%20class%20&%20function%20codes%20v%202.00.pdf
40, // Device class=External Environment. See codes on http://www.nmea.org/Assets/20120726%20nmea%202000%20class%20&%20function%20codes%20v%202.00.pdf
2046 // Just choosen free from code list on http://www.nmea.org/Assets/20121020%20nmea%202000%20registration%20list.pdf
);
// Uncomment 2 rows below to see, what device will send to bus. Use e.g. OpenSkipper or Actisense NMEA Reader
//Serial.begin(115200);
//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_ListenAndNode,23);
// NMEA2000.SetDebugMode(tNMEA2000::dm_Actisense); // Uncomment this, so you can test code without CAN bus chips on Arduino Mega
NMEA2000.EnableForward(false);
NMEA2000.ExtendTransmitMessages(TransmitMessages);
NMEA2000.ExtendReceiveMessages(ReceiveMessages);
NMEA2000.SetMsgHandler(HandleNMEA2000Msg);
NMEA2000.Open();
}

void Rudder(const tN2kMsg &N2kMsg) {
unsigned char Instance;
tN2kRudderDirectionOrder RudderDirectionOrder;
double RudderPosition;
double AngleOrder;

ParseN2kRudder(N2kMsg,RudderPosition,Instance,RudderDirectionOrder,AngleOrder); {
if (Instance=1){
double ReadN2kMsgAngleOrder();
double RudderAngleCorrect=RadToDeg(AngleOrder);
}
}
}

double ReadRudderPosition() {
return DegToRad(RudderAngleCorrect); // Read here the rudder position
}

void loop() {
SendN2kRudder();
NMEA2000.ParseMessages();
}

//NMEA 2000 message handler
void HandleNMEA2000Msg(const tN2kMsg &N2kMsg) {
int iHandler;
// Find handler
for (iHandler=0; NMEA2000Handlers[iHandler].PGN!=0 && !(N2kMsg.PGN==NMEA2000Handlers[iHandler].PGN); iHandler++);
if (NMEA2000Handlers[iHandler].PGN!=0) {
NMEA2000Handlers[iHandler].Handler(N2kMsg);
}
}

#define RudderUpdatePeriod 1000

void SendN2kRudder() {
static unsigned long RudderUpdated=millis();
tN2kMsg N2kMsg;

if ( RudderUpdated+RudderUpdatePeriod<millis() ) {
SetN2kRudder(N2kMsg, ReadRudderPosition());
RudderUpdated=millis();
NMEA2000.SendMsg(N2kMsg);
}
}

It looks as though you were close but shot yourself in the foot with a couple of simple (but classic) mistakes.

This:

    if (Instance = 1)
    {
      double ReadN2kMsgAngleOrder();
      double RudderAngleCorrect = RadToDeg(AngleOrder);
    }

Should more likely be this:

    if (Instance == 1)
    {
      RudderAngleCorrect = RadToDeg(AngleOrder);
    }

It works!! Thank you so much for the help and education. I made the 5 degree error adjustment along with a few other tweaks and it works great.

Now onto phase 2, which is to do some manipulation of water temperature data. And then phase 3 where I am going to build a windlass chain counter.

Great news and just as well - if it hadn't worked I was running out of ideas :wink:

Hi. I have trouble testing my software. I'm building bidirectional nmea2000-nmea0183 converter. I wrote software similar as it is in the examples.
The flow is if a message appears on nmea0183 serial port then i prepare nmea2000 message and send it to nmea2000 serial port. Similar in opposite direction.

I'm not sure if i should do this but I dont have a way to test it on real device yet.
What i did is, I connected nmea0183 serial port's Rx and Tx pins. Then i prepared nmea0183 message and send it to nmea0183 serial port. Then using actisense nmea reader i could see nmea2000 messages were sent.

But it doesnt work the same way with nmea2000. Connecting Rx and Tx pins of nmea2000 serial port and sending prepared nmea2000 message, didnt result in sending nmea0183 message.
There comes the question should it work this way.
If it should i will post my code because i cannot find a bug.
If not then i am sure its gonna work unless i dont set up my hardware correctly.