Go Down

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

timolappalainen

Unfortunately NMEA 2000 devices rely only manufacturer code set by last parameter of SetDeviceInformation. List of codes can be found by googling e.g. "NMEA 2000 Manufacturer Code - Product Code" So the code 2046 I have in examples is the biggest possible value. Note also that if you have old NMEA 2000 device, which can not be updated anymore, it will also show "unknown manufacturer" for newer manufacturers. This is one (of many) stupid thing on closed NMEA 2000 standard.

So you have 3 choices:
1. Do not care.
2. Use some registered code on list and it will show you that manufacturer.
3. Register youself as manufacturer and your device. The costs are only something like 9000-15000 dollars.

bwz0

Is a CAN-shield with MCP2515 & MCP2551 the recommended way to go or should I look for something else? Any opinions on which one has the best quality?

timolappalainen

If you will use my NMEA 2000 library, I prefer to system with at least 8 kB RAM. You can use Arduino Mega with CAN-shield. Arduino Due and Teensy 3.2 has more RAM to use. Also Teensy uses less power. For Teensy check issue 50 under my library. If you are handy and can make your own soldering, you can use schemas under library documentation. For easy way to use teensy there is "Teensy CAN-Bus Breakout Board Include Teensy 3.2".

seamaster

I'm just finishing new PCB with teensy 3.2, 8 analog 0-30V DC inputs and 4 temp inputs for TMP36 sensors providing GND, 3.3VDC and signal connection. It also have protected CAN interface mcp2551 and m12 n2k connector to directly plug into N2K network with or without termination. My prototype is working very well and I can't wait to get the first 3 boards. On the weekend I also added a compass module to the prototype, but did not have the properly tilt compensated board so it was just proof of concept. It worked well, at least as well as not tilt compensated compass could work. I ordered some 10 DOF boards and maybe in the future will have inexpensive rate compass with N2K output as well.
After the first boards are done I'm planing to develop different version with analog amplifier for measuring thermocouple to measure EGT.
I also need to figure out how to measure 0-1V positive as well as negative voltage to have an implementation for measuring battery shunt.
If there is an interest for these boards I will plan for larger run in the future.
If there is other ideas of what other interfaces are needed, please let me know.
Timo,
as soon as I have the hardware made, I will send you one of my first 3 populated boards as a tocken of appreciation for he hard work you've done to make that project possible.
Cheers!

bwz0

If you will use my NMEA 2000 library, I prefer to system with at least 8 kB RAM. You can use Arduino Mega with CAN-shield. Arduino Due and Teensy 3.2 has more RAM to use. Also Teensy uses less power. For Teensy check issue 50 under my library. If you are handy and can make your own soldering, you can use schemas under library documentation. For easy way to use teensy there is "Teensy CAN-Bus Breakout Board Include Teensy 3.2".
Thank you! Will your library also work with the Teensy 3.6 and the "Dual CAN-Bus adapter for Teensy 3.5, 3.6" https://www.tindie.com/products/Fusion/dual-can-bus-adapter-for-teensy-35-36/ ?

timolappalainen

Thanks. It is really nice to see that people has started to use library for real devices. Maybe we could in future have simple and cheap NMEA 2000 devices available.

I personally prefer small sized simple devices spreaded around. It is rather hard to organize centralize cabling to one point for everything. With the central cabling there is also problem with noise specially with analog signals. So instead use idea of NMEA 2000 bus so that you would have bus cable through the boat and then e.g. one "sensor device" on each tank or battery. E.g. Maretron already have small tank sensor.

Also I like more simple header connector as used in DeviceNET (see on Farnell codes 1717025 and 1717013) instead of expensive NMEA 2000 connector, which also takes a lot of space. I have made several split boxes with those for price of one "real" connector. My 5 connector splitbox requires only about 45x100x40 box.

Then if you are sailor, you may think that 10 small Teensy will take too much power. For slow data like tank and battery sensors they could measure value e.g. every minute and send it to the bus and then goto low power sleep. To arrange that one needs one master, which collects data and forwards it to bus every second or two to keep MFD happy. When I have time, I'll make sample for that.

Hopefully you got ideas of my opinions.

And I'll be happy, If I will get one board. I could replace my "Alba Combi" with it. You can send me private post for further information.

timolappalainen

Thank you! Will your library also work with the Teensy 3.6 and the "Dual CAN-Bus adapter for Teensy 3.5, 3.6" https://www.tindie.com/products/Fusion/dual-can-bus-adapter-for-teensy-35-36/ ?
It may require new class instead of old NMEA2000_Teensy. I'll try to study it.

bwz0

It may require new class instead of old NMEA2000_Teensy. I'll try to study it.
I ordered it, so I'll try to let you know when I get around to try it in a few weeks time.

seamaster

#203
Jun 16, 2017, 10:40 am Last Edit: Jun 16, 2017, 10:51 am by seamaster
Hi Timo,
I have one NSS9 Evo3 Simrad MFD and i just got from Ebay AC42 simrad autopilot computer that i interfaced to the MFD. I added Heading and Rudder Angle output from the Teensy prototype board and at first it all appears good. I can read the heading and the rudder angle on the MFD. then I tried to commission the autopilot and as a part to the there is a sequence that one needs to perform to set the hard over to hard over limits. With my little cheat board with potentiometer on one of the analog inputs i could perfectly simulate rudder movement. the MFD shows me the rudder going to port and then to Starboard, then I center it as the calibration routine for the AP requires, but unfortunately the rudder calibration never completes, therefore I cant continue with the AP commissioning. Im sure you are wondering why i am asking you that, as you probably don't have the same AP and the chances are you don't know what the issue is, but I wanted to pick your brain on rudder PGN.
I did some digging and i found out that the MFD that controls the AP could be seeing the rudder angle but the PGN overall is not what it expects to see, and that's why the rudder calibration fails.
The way I understand your code, for rudder angle in N2kMessages.h you have:

Code: [Select]

// Rudder
// Input:
// - RudderPosition         Current rudder postion in radians.
// - Instance               Rudder instance.
// - RudderDirectionOrder   See tN2kRudderDirectionOrder. Direction, where rudder should be turned.
// - AngleOrder             In radians angle where rudder should be turned.
// Output:
//  - N2kMsg                NMEA2000 message ready to be send.
void SetN2kPGN127245(tN2kMsg &N2kMsg, double RudderPosition, unsigned char Instance=0,
                     tN2kRudderDirectionOrder RudderDirectionOrder=N2kRDO_NoDirectioOrder, double AngleOrder=N2kDoubleNA);

inline void SetN2kRudder(tN2kMsg &N2kMsg, double RudderPosition, unsigned char Instance=0,
                     tN2kRudderDirectionOrder RudderDirectionOrder=N2kRDO_NoDirectioOrder, double AngleOrder=N2kDoubleNA) {
  SetN2kPGN127245(N2kMsg,RudderPosition,Instance,RudderDirectionOrder,Angle Order);
}



so my conclusion was to write something like:

Code: [Select]



void SendN2KRudder() {
#define rudderUpdatePeriod 100
  static unsigned long RudderUpdated = millis();
  tN2kMsg N2kMsg;

  if ( RudderUpdated + rudderUpdatePeriod < millis() ) {
    RudderUpdated = millis();


    SetN2kRudder(N2kMsg, (avg2 / 2 - 280) / 3.14 / 18), 0); //avg2 is just function to read the pot and some random math to get my reading convert to rad angle that represents -40 to +40 deg


    NMEA2000.SendMsg(N2kMsg);
    delay (10);

  }
}


as I mentioned earlier it kind of works but can't complete the rudder calibration sequence. I called simrad tech support and they ask me to reset the AP settings and the MFD setting which i did later on, but it did not help.


then I start doubting the validity of the PGN I was  outputting and experimented with passing more to the function (as you see fro my code I am passing only the rudder angle in rad and the instance number). once i added more then these two parameters, I got en error compiling.  Regardless I continued digging and found something that really got me to write you this message. In your code the first parameter  to output is the rudder angle followed by the instance number, etc, ets,
I did find the string for PGN127245 here:
http://www.nmea.org/Assets/july%202010%20nmea2000_v1-301_app_b_pgn_field_list.pdf

and at least to me looks that it has different order the definition in your code:

PGN 127245   Field Field Description
Rudder order command in direction or angle with current rudder angle reading.
1 Rudder Instance
2 Direction Order
3 Reserved Bits
4 Angle Order
5 Position
6 Reserved Bits

Do you have an example outputting
PGN 127245, while passing all parameters such as RudderDirectionOrder and RudderDirectionOrder?
just in case here is the link to the AP manual http://www.simrad-yachting.com/Root/Installation%20Manual/SimradYachting/English/AC12_AC42_IM_EN_20222568_E_w.pdf

timolappalainen

First do not compare order of c++ function parameter list and the order of PGN definition. The point is that since you normally do not need all parameters, why you should have them in that order on function? If you want to compare, you have to goto look into the function code. But I think you do not need to, since I have tested rudder PGN against Actisense NMEA Reader as I allways do with new PGNs. Also, if data would be wrong, you would not see any rudder angle on your MFD.

Then about calibration. There are two possibilities:
1. AP expects also direction order (and order angle) parameter set right.
2. AP expects specific Simrad rudder sensor and tries to calibrate that with proprietary command, which we do not have any information.

Case 1 you can test, if you calculate from changes right value for the direction order and put some value for direction angle.

Case 2 is complicate, since you should do reverse engineering with full Simrad system. Can be time consuming.

It is also possible that AP uses standard Group Function commands to set direction order fields for you Teensy. If you have latest library version, it will automatically respond for that command with "no support". But it may be that AP is not either happy for that. You can listen data with some device - even with your Teensy by using mode N2km_ListenAndNode and enable forwarding. Then you look does AP send any 126208 PGN:s (Group Function PGN) to your device.

Offset you can easily program to your Teensy, but can you manually set hard limits. If you can, then you could forget automatic calibration.

seamaster

#205
Jun 17, 2017, 11:59 am Last Edit: Jun 17, 2017, 12:51 pm by seamaster
Hi Timo,
thanks for the reply.
I did spend all night again looking at the possible solution
I noticed that the the new library required me to change 
Code: [Select]


const tProductInformation BatteryMonitorProductInformation PROGMEM={
                                       1300,                        // N2kVersion
                                       192,                         // Manufacturer's product code
                                       "SeaWitch_Monitor",    // Manufacturer's Model ID
                                       "1.0.0.13 (2016-09-19)",     // Manufacturer's Software version code
                                       "1.0.0.0 (2015-08-03)",      // Manufacturer's Model version
                                       "12340002",                  // Manufacturer's Model serial code
                                       1,                           // SertificationLevel
                                       1                            // LoadEquivalency
                                      };                       

to
Code: [Select]

const tNMEA2000::tProductInformation BatteryMonitorProductInformation PROGMEM={
                                       1300,                        // N2kVersion
                                       192,                         // Manufacturer's product code
                                       "SeaWitch_Monitor",    // Manufacturer's Model ID
                                       "1.0.0.13 (2016-09-19)",     // Manufacturer's Software version code
                                       "1.0.0.0 (2015-08-03)",      // Manufacturer's Model version
                                       "12340002",                  // Manufacturer's Model serial code
                                       1,                           // SertificationLevel
                                       1                            // LoadEquivalency
                                      };                       


and

Code: [Select]

const tNMEA2000::tProgmemConfigurationInformation BatteryMonitorConfigurationInformation PROGMEM={
                                       "SeaNav, john.doe@unknown.com", // Manufacturer information
                                       "First attempt", // Installation description1
                                       "No real information send to bus" // Installation description2
                                      };


to
Code: [Select]

const char BatteryMonitorManufacturerInformation [] PROGMEM = "John Doe, john.doe@unknown.com";
const char BatteryMonitorInstallationDescription1 [] PROGMEM = "Just for sample";
const char BatteryMonitorInstallationDescription2 [] PROGMEM = "No real information send to bus";



in order to compile properly. I'm not saying that's wrong :) I'm just beginner in programing and i have no idea most of the time why I'm making changes. I just compare the new examples to my code and try to make it work :)

Once it start working I also noticed that the device name is not showing up anymore on my MFD but rather show "???". I bet this is a result of my attempt to get my code running with the new library and the changes I did above.






Then I noticed something else -  the "rudder angle" is shown as (Simrad) group, while the "commanded rudder direction" is shown as (Global) group. All the rest of the devices on the bus are part of the Simrad group. I have no idea why "commanded rudder direction" is shown as (Global) group and it can't be changed as there is no Simrad selection in the dropdown menu as there is on the "rudder angle" (see the first picture).





Then I tried to change the instance from 000 to 001 and the device will not take it. I don't think this was something I was successful of doing before upgrading the library either.




Let's go back to the problem at hand. My rudder angle simulator is not being liked by Simrad AP calibration procedures so im trying to understand why and possibly fix it. I did read your email carefully and some parts I understood, but for other parts my programing experience is not enough to make the right conclusions from your email.
I did program another Teensy as listener and captured the bus during my attempt to calibrate the rudder angle on the AP from the MFD. Then I searched for PGN 126208  but it wasn't there. I have attached the capture to this post. Just for clarification, I have the following devices on the N2K bus: Simrad NSS EVO3 MFD, Teensy rudder angle simulator, Simrad AC42 AP computer and another Teensy that is setup with the listener only code. I see more devices showing up in the log file, but I believe that the MFD separates the chart-ploter, the depth-sounder, the AP controller, etc.etc.

One think I would really like if you can help me with is what is the syntax of the parameters of the rudder message. I could make it compile only with passing 2 parameters. if I attempted to pass more than 2 i got errors compiling (from looking at your code i think they should be 4). Very frustrating as my abilities to understand the code are not that great. can you tell me what  parameters I pass to the rudder function, what is the syntax and what each one does?

I see "SetN2kPGN127245(N2kMsg,RudderPosition,Instance,RudderDirectionOrder,AngleOrder)" in your library
and I tried many different combinations in my code, but again it was only successful with 2 parameters
e.i.
Code: [Select]

SetN2kRudder(N2kMsg,((avg2-512)/3.1415926535897932384626433832795/180),1);
    //avg2 is just function to read the pot and some random math to get my reading convert to rad angle that represents -40 to +40 deg



Thanks in advance for spending time to look at my problems.


PS
I just received email that they are parting the big production PCB boards and my PCBs will be send in the mail to me in 48hrs! How exciting! I will post some pic immediately when I get them.

timolappalainen

Have you noticed that on the library main page, if you scroll down there is "Changes" section, where specially compitibility changes has been notified. Time to time I unfortunately find something, which is not good for some reason, so I have to change library compatibility. So please read "Changes" section allways carefully.

I also prefer not to copy from examples totally as they are. So. e.g. change name BatteryMonitorProductInformation for e.g. SeaSwitchRudderAngleProductInformation. Also change contents like versions, dates, etc. to match your code. Also remember to define LoadEquivalency to right value. This is n on formula n * 0.050 mA, which tells how much power your device takes from the bus.

You can not change instance of "Rudder Angle"-device, because currently it requires to write specific "Command Group Function" handler for rudder PGN. Currently default handler responds that change is not supported.

You can call it e.g.:
SetN2kRudder(N2kMsg,DegToRad(RudderAngle),1,N2kRDO_MoveToStarboard,DegToRad(RudderCommandedAngle));

Note that you can use library function DegToRad() for conversion.

I'll recheck that product information should be send right to the bus. I'll inform later.

timolappalainen

I tested product information sending and it seem to work. But I have to test it also with MFD. Your MFD should query product information from your device. I have to check could support for Comand Group Function cause that some MFD:s could query product information by using it instead of ISO request.

seamaster

#208
Jun 18, 2017, 10:43 am Last Edit: Jun 18, 2017, 10:57 am by seamaster
Hi Timo,
Thank you for your instructions. After I received your reply I managed to output completely
PGN127245 string, I think... and read the compatibility section in your library so now I see the proper name, but stiill struggling outputting rudder angle on the top of the other two with your multi  device sample.
Back to the problem on hand: On the Simrad display I still see difference in the groups. The rudder angle Bellingham nags to the simrad group and the rudder commanded angle belongs to the global group. The AP rudder angle calibration still does not work. :( at this point I am almost positive that maybe the AP needs some response from the Rudder angle sensor, but not too sure as I couldnt not find anything like that in my data capture during an attempt to calibrate the rudder portion of the AP dock setup.
The datasheet for the Simrad N2K rudder angle sensor refers output only PGN127245.
http://www.simrad-yachting.com/Root/Simrad-Documents/RF25_Instruction_Rev.A.pdf
So I will still try to concentrate providing the proper output from my simulated sensor. With your help I got the sintax ok, but the data I put in it is still bogus... I output proper rudder angle from -35 to 35 deg, that incontrol with potentiometer, but the rest of the data is static. I just plugged some direction and random number for commanded angle DegToRad(19)
I would like to understand little better how this works, so I do have few questions about the paremeters.
setN2kRudder(N2kMsg,DegToRad(RudderAngle),1,N2kRDO_MoveToStarboard,DegToRad(RudderCommandedAngle);
1. What is the second parameter "1"? Is that the instance?
2. What is the "MoveToStarboard" how and when you change it to "MoveToPort"? In your function I see 0 is unknown, 1 starboard, 2 port(if I remember correct...) so it surprised me that I needed to put in the string rather than the un. char 0, 1, or 2 which of course I was trying without success before your explanation. Do I have to create a function to compare the readings and then based on the fact that they get larger or smaller one replaces MoveToPort with MoveToStarboard and vice versa?
3. How you calculate "RudderCommandedAngle"?
4. Why are these parameters required? If they are what I think they are, why are they not calculated by the AP or by AP controller? Why rudder indicator should tell ap in which direction is moving? The APis the one issuing the commands to the steering to move so it should know already...

timolappalainen

1. It is instance value. If you would have 2 rudder sensors, they all should have different instance value.

2. N2kRDO_MoveToStarboard is not a string. Strings will be marked on code with "...". N2kRDO_MoveToStarboard is a value of enumerated type tN2kRudderDirectionOrder. The point for enumerated types is to limit values only to allowed group and also make code readable. If that would be define as uchar, you should comment you code e.g. ...1 /* move starboard */... and also you could set value to e.g. 75, which is not allowed for that setting.

I think normally this PGN comes from AP, which uses integrated sensor. So then AP can say "Current Rudder Angle is 5, I am moving rudder To Starboard and the goal is 15" with this PGN. When you have standalone sensor, it should not use other than angle and instance values. For rest values it should give defaults as I have in function (N2kRDO_NoDirectionOrder,N2kDoubleNA). I was just guessing that may be that during calibration your AP will expect those commaned values. Can be wrong. But if you want to try, you should provide delta of angle.

3. Partially answered on 2. Also here you can ted delta angle.

4. Also answered on 2. Stand alone sensor should not provide these values.

What manufacturer code you have used for you Rudder sensor? If you have used 1875 (Simrad), then your AP may think that is manufactured by Simrad and may try to use their proprietary calibration system. I do not know any std sensor calibration system, so it is best to mfg code, which is not know (=registered) - e.g. 2046.

From your log I can see that probably your AP (source 0) is providing Rudder PGN with all fields as "unavailable" value.

Go Up