Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

purpose of SetProductInformation and SetDeviceInformation #22

Open
usauerbrey opened this issue Sep 11, 2016 · 25 comments
Open

purpose of SetProductInformation and SetDeviceInformation #22

usauerbrey opened this issue Sep 11, 2016 · 25 comments

Comments

@usauerbrey
Copy link

Hi Timo

I think I have some problems in understanding the functions SetProductInformation and SetDeviceInformation. I using a teensy with CAN-Bus driver and have connected it to my SeaTalk NG. Using for example the BatteryMonitor with N2km_ListenAndNode is can see all the N2K-Messages on the bus using NMEA Reader and also see my own messages (Voltages etc.) . But I never saw any messages with the infos of SetProductInformation and SetDeviceInformation. I would expect, that the PGN 126996 Product information would be transmitted for this purpose. On my other N2K devices the 126996 is either send periodically or - true for the raymarine device - on request from a MFD.

please clerify
Best Regards Uwe

@ttlappalainen
Copy link
Owner

Hi Uwe,

Device information is critical for Nodes. Each Node will start address claiming automatically and it uses device information for calculating priority. If you add several own devices, you should also remember to program unic _UniqueNumber for each device on SetDeviceInformation. With SetDeviceInformation you also tell to other devices the type of your device (DeviceClass and DeviceFunction).

Product information is informative to the bus. You should see this information on MFD bus devices list.

I have tested both with Garmin GMI20 and they works. GMI20 asks library device to send 126996 and it will respond. I can see my devices on GMI20 list.

Can you see any requests for 126996? It seems that library device does not respond to broadcasted 126996 request.

Timo

@usauerbrey
Copy link
Author

Hi Timo

Yes I see ISO request (59904) with requested PGN = 126996 from the MFD (Raymarine i70) to addr 255 and no answer from library device. The other devices answer with 126996 to addr 255.

BTW would it make sense to send 126996 periodically?

Best Regards Uwe

@ttlappalainen
Copy link
Owner

Hi,

I am fixing the error that it does not respond to broadcast. Then it should work. I'll try to do it for tomorrow.

I do not prefer to send it periodically - at least with my current knowledge.

@usauerbrey
Copy link
Author

Hi Timo

thanks, I will test it, when you are ready. Concerning the periodical sending of product information, on my boat, 4 devices (different, non-Raymarine) do it, 5 Raymarine does not. So it seems that the manufactrers decide about it

@ttlappalainen
Copy link
Owner

Hi,

I just updated the sources. Hopefully I tested all.

Unfortunately I do not have information about what standard says for sending information periodically. Since I have Garmin GMI20 and some other devices on the bus and they seem to work so that they respond to others requests. I would think that this is better way. If you have problems on your system, you can anyway add some periodic sending by calling command NMEA2000.SendProductInformation or NMEA2000.SendIsoAddressClaim. But please test new changes first.

@usauerbrey
Copy link
Author

Hi timo

I have tested it, but nothing has changed. Just the ISO ack ist transmitted as response to the ISO address claim from the MFD. But no Productinformation.
I am relative sure, that I have updated the files in the NMEA2000-lib correctly, but I will doublecheck the next days.

Best Regards Uwe

@ttlappalainen
Copy link
Owner

Hi,

Did you deleted (or moved) old NMEA2000 library files under libraries first and then installed new library? Check that you have new protected member function RespondISORequest on NMEA2000.h and .cpp!

@usauerbrey
Copy link
Author

Hi Timo

First, yes I have updated the library files correctly. But no Product info comes out. Then I added - just for debugging - in the default clause of the RespondISORequest two lines:
SendIsoAddressClaim(0xff,iDev);
SendProductInformation(iDev);

Now I see the IsoAddressClaim and the ProductInformation, together with the ISOAcknowledgement when the i70-MFD is pulling a list of devices.

Second, my library device is not listed on the MFD, even so I checked all fields in the ProductInformation with the NMEAReader. So I have no idea ho to get the library device to the list.

Best Regards Uwe

@ttlappalainen
Copy link
Owner

I think I found the problem.
First remove you test code SendIsoAddressClaim(0xff,iDev);...

Then on NMEA2000.cpp / bool ParseN2kPGN59904(... there is line
int result=(N2kMsg.DataLen==3);
change that to
int result=((N2kMsg.DataLen>=3) && (N2kMsg.DataLen<=8));

Timo

@usauerbrey
Copy link
Author

Hi Timo

Thanks for the fix, it solved my first problem, e.g. I now see the productinformation in NMEAreader.

But the second issue (my library device is not listed on the MFD) was still open. So I play around with the SW and switched to plain text output. Now I saw a couple of "send failed" messages. So the product information did not go out to the N2K-Bus, even so they where shown on NMEAreader. I saw the commented line 338 in NMEA2000.ccp , delay(3). So I actived the delay, played with the value and with delay(30) no "send failed" occured and the i70 shows the library device.

But to be honest, this is not a real solution. When using delay(30) after checking the device list from the i70 the output of the library device to USB stopped, the rest e.g. showing battery voltage and also the list of devices works fine.
BTW. the stopping of the output occurs only when using the actisense format. When using plain text, no stop in output occurs.
I hope this will help to improve it.

Best Regards Uwe

@ttlappalainen
Copy link
Owner

Hi,

First you have to remember that if you have Teensy board sending something to the bus and same board is working as gateway for NMEA reader, all data board sends does not actually go through the bus at all. So that is why you will see data right on NMEA reader, but it may be failed on bus.

When I make the tests, I use at least two boards so that one is sending and other is listening the bus with NMEA reader. In this way I avoid above problem. And I tested Teensy with example MessageSender and I see send failed only about every 20 sec.

@ttlappalainen
Copy link
Owner

Hi,

I could simulate your problem, so I'll try to find the reason.

@ttlappalainen
Copy link
Owner

Hi,

Now there is at least temporary fix. The problem has something to do with device priorities. If I set my device number to 2, it can send product inforrmation for request without delays. When my device has number 22, it required 100 ms delay. Now this is fixed so that library just "pools" request (quick-dirty way) and sends it on ParseMessage call after enough time has gone.

Timo

@usauerbrey
Copy link
Author

Hi Timo

I tested it and for me your q&d fix works fine. But of cause I will check again, if you make it less q&d ;-)

Best Regards Uwe

@ttlappalainen
Copy link
Owner

Hi,

I have new solution under tests. It fixed me also problem that system did not send time to time some message, which caused alarm on MFD. I'll think tests are ready tomorrow.

@usauerbrey
Copy link
Author

Hi Timo

The new version with better handling of sending frame work here good, no complains (yet ;-)

Best Regards Uwe

@virtuvas
Copy link

Hello Timo,

following your quick visit to the ybw forum where I post, just a note and question on this product and device information.
I use a MEGA and a MCP2515 NoRen board for testing. Keeping my teensy for exhaust gas temps and other dirty jobs on the engine bay later on...
Boat system includes a lot of Garmin kit (GPSMAP4008, GPSMAP751, GMR24HD, 3XGMI10, AIS600, VHF200, GHC10) and a NoLandEngineering analogue data monitor which all show up on both plotters and the GMIs with no problem.
I've had great success running all sorts of things and I'm really greatful to all you guys!
However no matter what throughout the summer, the MEGA wouldn't appear on the bus.

So now back at home with the MEGA and one GMI10, doing some tests and tried to follow the discussion in this issue with limited success. I have setup a tiny N2K bus three tees and two terminators, so all should be OK termination wise.

I have:

`void setup() {

tN2kMsg N2kMsg;
// Set Product information
NMEA2000.SetProductInformation(
1300, // N2kVersion
100, // Manufacturer's product code
"Vas Helm Box", // Manufacturer's Model ID
"1.0.0.12 (2016-09-09)", // Manufacturer's Software (Firmware for GMI) version
"1.0.0.0 (2015-08-03)", // Manufacturer's Model version
"00000002", // Manufacturer's Model serial code
0, // CertificationLevel
1 // LoadEquivalency
);
// Set device information
NMEA2000.SetDeviceInformation(2, // Unique number. Use e.g. Serial number.
130, // Device function=Atmospheric
25, // Device class=External Environment
2075 // Just choosen free from code list on
);
NMEA2000.SetMode(tNMEA2000::N2km_NodeOnly,2);
NMEA2000.EnableForward(false);
NMEA2000.Open();
NMEA2000.SendMsg(N2kMsg);
}

void loop() {
SendN2kWind(); //convert NMEA0183 from NASA wind instrument to N2K
SendN2kTemperature();
SendN2kDieselFluidLevel();
SendN2kFreshWaterFluidLevel();
SendN2kBlackWaterFluidLevel();
SendN2kRudderAngle();

NMEA2000.ParseMessages();

NMEA2000.SendProductInformation();
NMEA2000.SendIsoAddressClaim();
}
`

Now, with
NMEA2000.SendProductInformation();
NMEA2000.SendIsoAddressClaim();

commented out, GMI10 doesn't know a thing about the MEGA+MCP

With the first line uncommented I get Vas Helm Box listed and Model and Firmware populated.
I don't get serial number showing though.
Further, mid button on the GMI10 (Done) does nothing, I have to use the back button (far left on the GMI10) in order to go back to previous screen where list of devices are shown.

I do have latest libs properly loaded on my PC.

One Q I have is what is this NMEA2000.SetMode and how all these numbers match and where do I define the serial number for the device as it's all a bit confusing.
Another Q is what should be the LEN number for a box like that. The current supply is constant 13.3V from a 20A dropper (boat is 24V) and feeds a few odd things like an ultrasound depth gauge for the blackwater tank, a NMEA0183 NASA wind instrument, an old 12V analogue rudder sensor, you name it I've got all my old kit converted to N2K :-)

cheers

Vassilis

@ttlappalainen
Copy link
Owner

First you should not call NMEA2000.SendProductInformation(); NMEA2000.SendIsoAddressClaim(); on loop every time. This will fill up the bus with your data. You have to limit calls with timer like in my example WindMonitor function SendN2kWind(). Normally you do not need to call this at all. My GMI20 requests automatically information about all devices on bus. I have been told about some MFD:s, which does not do that, so they need to call NMEA2000.SendIsoAddressClaim(); periodically in every e.g. 2 sec. But even with those call to NMEA2000.SendProductInformation(); has been unnecessary, since MFD then requests it.

With SetMode you define your device behaviour and set the default address on the bus as described on the document. Note that each device (also called node) has own address (0-254) on the bus. So with SetMode you can define the default address. This address may be anyway changed due to address claiming, but in your point of view you do not need to care about it. For this it is important to use SetDeviceInformation so that address claiming will work. This is also on document. One thing, what is missing is that 2046 is the max value for manufacturer code and you have 2075, which translates to 27.

So on SetDeviceInformation you need to define unique number for the address claiming. With SetProductInformation you can define serial number for your device, which should be shown on MFD. Serial number can be a string version for unique number, but it does not need to.

But again I wonder you setup:

  • Why you have there
    tN2kMsg N2kMsg;
    ...
    NMEA2000.SendMsg(N2kMsg);
    You do not initialize the N2kMsg with any data and normally this is not needed on setup()
  • How your code can ever compile:
    NMEA2000.SetProductInformation(
    1300, // N2kVersion
    ...
    If you look any example, function should have string (Manufacturer's Model serial code) as first parameter. Note that library parameters are not necessarily in same order as data is send to bus. In library there are some values filled with defaults, so they are moved to the on variable list. Please check the usage for member functions.

And finally do you mean "Load Equivalency" with LEN? If yes, that is simply the maximum power your device takes power from bus. If you just have Teensy board, which reads data from other devices, but does not power them, then 1 (50mA) is OK. I think Mega need 4 (200mA). I expect that you are not powering other instruments from N2k bus power lines. Or if you do so, you have to calculate their total power and devide it with 50mA. For old devices I prefer to power them directly from battery instead from N2k bus, since their power comsumption is rather high and bus has normally only 0.5 mm2 wires.

@virtuvas
Copy link

Timo, that WAS quick!

You are absolutely right on the SetProductInformation being wrongly setup. I'd just moved from the header the definition without paying attention to the hierarchy. Just checked on NMEA2000.h and all fixed, thanks! BTW, it WAS compiling! Now serial number shows fine on the GMI10.
Also removed the tN2kMsg N2kMsg; and NMEA2000.SendMsg(N2kMsg); lines, had left them from previous experiments.
Yes, I meant Load Equivalency, I'll follow your instructions and add a normal 12V supply to my box to feed all these devices as I'm not sure they are not going to be creating problems with my overall bus, thanks.

Now, to actual problem. You say:

First you should not call NMEA2000.SendProductInformation(); NMEA2000.SendIsoAddressClaim(); on loop every time. This will fill up the bus with your data. You have to limit calls with timer like in my example WindMonitor function SendN2kWind(). Normally you do not need to call this at all. My GMI20 requests automatically information about all devices on bus. I have been told about some MFD:s, which does not do that, so they need to call NMEA2000.SendIsoAddressClaim(); periodically in every e.g. 2 sec. But even with those call to NMEA2000.SendProductInformation(); has been unnecessary, since MFD then requests it.

OK, I understand that my approach is not right, let me describe the symptoms:

If I compile without NMEA2000.SendProductInformation(); NMEA2000.SendIsoAddressClaim(); on the loop and fire up the bus, My "Vas Helm Box" is not listed on the GMI10.

If I compile with the NMEA2000.SendIsoAddressClaim(); on a 5second loop off one of the functions run by the main loop, I get a Uncallibrated title and Unknown Device with "invalid" in the serial field. This appears and disappears every 5 or so secs on the GMI10.

If I compile with the NMEA2000.SendProductInformation(); on a 5second loop off one of the functions run by the main loop, I get initially a proper registration of the device, which then promptly disappears.

If I compile with both lines on the same 5sec loop, I get a proper display with the right registration, serial number, etc. All fine, I can even hit Done on the GMI10 and come out of that and back in device list.

The interesting observation is that while running if I compile again with the two lines commented out (and not appearing anywhere else in the code) the GMI10 STILL has the right registration serial, name for the device. However, IF I power down the bus and power back on, device disappears for good from the GMI10 and I need to uncomment both lines on a loop to get it to show again.

So somehow it seems that I need to have it on a loader loop sort of thing? Or am I missing something else?

I'm happy to keep both lines on a low priority loop, but I'm wondering if that's ok or something else can be done for it.

cheers

V.

@ttlappalainen
Copy link
Owner

There is some thing with Mega and MCP2515. For reliable communication it need interrupt enabled. So you should have interrupt wire and then you need to have:
#define N2k_CAN_INT_PIN 21
before any library header on you ino as in DataDisplay2 example. One possibility is that it misses request frame time to time if interrupt is not in use.

You could also email your code, so I could test it with my Mega/MCP2515 on my test bed. Unfortunately I have only GMI20, but anyway then we know is it something with library, your code, Mega or GMI10.

@virtuvas
Copy link

Timo,
I had interrupt disabled, but I had the cable from the 2515 to pin21 installed, so added it on my ino.
No luck, does the same.
However, I did some very detailed tests and eventually I got somewhere:
If I start them both (GMI10 and MEGA) MEGA doesn't show on the GMI10 list, just flashes as unknown device for a couple of seconds and gone for good.
Same if I have the GMI10 up first and the MEGA is second.
However, if I powerup the MEGA first wait for 5-10secs and THEN fireup the GMI10, it shows up nicely.

Makes sense???

Happy to sent my code over. Just added it to this post.
And coming to think of it, please note that your automated loading of libs/headers incorporated in NMEA2000_CAN.h didn't quite work on my combo when I was using the Due with the MCP2515 hence I've just dissected it and only used the bits I felt were needed. It does work, I may have done some mistakes there though...
Problem is that all this work was mainly done before the summer and although I'm commenting all my code, I don't exactly remember what and why was done to solve what problem.

again thanks!

V.

MiToS_MEGA_MCP_v1.64.ino.zip

@ttlappalainen
Copy link
Owner

I have to investigate this a bit more, but some notes about your code:

  • You could also use automatic #include <NMEA2000_CAN.h> as in samples
  • Why you have #define MCP_CAN_CLOCK_SET MCP_8MHz? 8MHz is for compatibility for Maple. MCP2515 can run with 16MHz, which is default for it
  • You have tNMEA2000_mcp NMEA2000(N2k_SPI_CS_PIN,MCP_CAN_CLOCK_SET); Note that this causes not to use interrupt at all, since if you look NMEA2000_mcp.h constructor will use default 0xff for int pin meaning no interrupt. You should have tNMEA2000_mcp NMEA2000(N2k_SPI_CS_PIN,MCP_CAN_CLOCK_SET,N2k_CAN_INT_PIN);
  • You have definition #define MCP_CAN_RX_BUFFER_SIZE 200, which just causes compiler warning. Definition should be before #include <NMEA2000_mcp.h> so that it would have any effect.
  • Note that it is not good programming if compiler generates lot of warning. There are also critical warnings, which you then easily miss. If you would have read warnings carefully, you would have noticed above. This time this is not critical since library will use default 50.
  • You call in your loop e.g. SendN2kWind(); And within that you first call Serial.println("start NMEA0183 wind data read..."); Meaning that your code actually calls that print on every loop and so spending a lot of time for printing data.

If I put return; (fo passing rest of initialization) immediately after NMEA2000.Open(); system works. But I did not yet found the problem.

@virtuvas
Copy link

virtuvas commented Nov 1, 2016

again Timo, grateful for your help, my comments below:

You could also use automatic #include as in samples

didn't work with the Due, and didn't work with the combo of the Mega with the 2515, so picked up the bits I wanted.

Why you have #define MCP_CAN_CLOCK_SET MCP_8MHz? 8MHz is for compatibility for Maple. MCP2515 can run with 16MHz, which is default for it

because my chinese board has a 8MHz crystal (at least that's what is printed on top) Tried with 16_MHz doesn't work, so stuck with 8

You have tNMEA2000_mcp NMEA2000(N2k_SPI_CS_PIN,MCP_CAN_CLOCK_SET); Note that this causes not to use interrupt at all, since if you look NMEA2000_mcp.h constructor will use default 0xff for int pin meaning no interrupt. You should have tNMEA2000_mcp NMEA2000(N2k_SPI_CS_PIN,MCP_CAN_CLOCK_SET,N2k_CAN_INT_PIN);

correct, guilty as charged, again leftover from the Due tests. Changed it to the right one. Unfortunately doesn't help in showing up on the GMI10...

You have definition #define MCP_CAN_RX_BUFFER_SIZE 200, which just causes compiler warning. Definition should be before #include so that it would have any effect.

No idea why I have that, commented it out, and moved the definitions before the includes!

Note that it is not good programming if compiler generates lot of warning. There are also critical warnings, which you then easily miss. If you would have read warnings carefully, you would have noticed above. This time this is not critical since library will use default 50.

again apologies, wasn't seen any warnings at all so was assuming that compiling is all perfect. Following your comment, I search and found that I have to go and enable warnings on the IDE, doh! Fixed all warnings this way, only an SD lib warning is still on. Thanks!

You call in your loop e.g. SendN2kWind(); And within that you first call Serial.println("start NMEA0183 wind data read..."); Meaning that your code actually calls that print on every loop and so spending a lot of time for printing data.

I know, just testing code, not final, all serial prints (except for the NMEA0183 related to the AutoAnchor) will be removed before proper use.

To conclude, again with no call for NMEA2000.SendProductInformation(); anywhere, IF I start the MEGA 10-15secs before firing up the GMI10 for the first time, all's fine, GMI10 sees it properly.
Otherwise, GMI10 shows for 3-4secs and only ONCE a uncalibrated unknown device in the list of N2K devices and that's all.

still working on my subroutines, so plenty of time to workout such minor issues

cheers

V.

@ttlappalainen
Copy link
Owner

You could have:
#define N2k_CAN_INT_PIN 21
#define USE_MCP_CAN_CLOCK_SET 8
#define MCP_CAN_RX_BUFFER_SIZE 200
#include <Arduino.h>
#include <NMEA2000_CAN.h>
#include <N2kMessages.h>

then it uses 8Mhz clock for Mega.

Due has internal, which library uses as default. This is why #include <N2kMessages.h> does not work with due and MCP2515. I prefer for Due use internal CAN and MCP2562 driver as in my sample drawing.

You could also try pass all extra on on setup() by putting return; just after NMEA2000.Open(); and write to loop only:
void loop() {
SendN2kWind(); //convert NMEA0183 from NASA wind instrument to N2K
NMEA2000.ParseMessages();
}

On SendN2kWind(); pass everything elese but sending wind info. So then you actually have my WindMonitor example. But then you can check how it behves with GMI10. My WindMonitor sample shows on GMI20 how ever I start devices.

@virtuvas
Copy link

virtuvas commented Nov 2, 2016

Timo,

quick note, tried your windmonitor with the suggested define for the 8MHz clock, compiles, works, GMI10 has exactly the same behaviour.
Is it safe to assume it's the 2515 and not your or mine code to blame???

I've just ordered a few 2562s so once I receive them, I'll try again with all three Mega, Due and teensy and report back!

cheers

V.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants