Open usauerbrey opened 7 years ago
Hi,
If you have my library devices, ensure that they have different Unique number (set by SetDeviceInformation) and different Model serial code (set by SetProductInformation). Then MFD should show these as separate device so that you can define, what source to use. My Garmin GMI 20 can do that. But unfortunately this depends also MFD.
You can also try to use different instance number on different devices.
Timo
Now there is a new version, which hopefully is much better.
Hi Timo
I have the following roblem. My log (wheel) gets dirty often and then it gives a STW of 0 kn. This is not a problem as such, I have my SOG an this is ok. But the True Wind is calculated by the wind instrument using the STW and I cannot set it to use SOG instead. So I would like to wirte a program for the libray device, which reads STW and SOG and if STW is 0 but SOG not, I would send a STW-information with the SOG value. But how can I make the wind instrument take my STW value and not the value of 0 from the log. The MFD (Raymarine does not give me the seection of sources) at all.
So my question is, how does the N2K standard defines which souce is used. Or is it just up to the manufacturer of a device which source it takes?
Best Regards Uwe
Sorry for delay,
I do not know is there any stndard for that. I think some devices just use PGN information. This is very problematic, if you have e.g. two heading sensor having 1 degree difference, so value will be jumping all the time. I had this case with my autopilot so I had to leave my spare sensor disconnected.
How are you devices constructed? Is your log N2k or NMEA0183 device? The point is that could you connect the log directly to your own device and make that as gateway? If the log is N2k log, then you would need to use Arduino due or add second cab bus to the system.
Timo
Hi Timo
What delay, you are really fast ;-) The log device is n2k, but your proposal making a gateway sounds interesting, even so I had expected, that there is some kind of selection mechanism on the bus. But maybe there is one, but it is not really known.
Best Regards Uwe
Hi,
The selection mechnism exist. Each device has unique ID and they will get some source number on bus. So the device, which should select data should record unique ID, which you select on configuration. Then they can send ISO address claim query and see that device source number. Then they will use that information. Garmin GMI20 seem to work like that. I think I tested system by feeding cabin temperature from two sources and I could select, which one to show. If Raymarine does not offer that, then you can not do much.
So in principle you could have gateway, where all sensors are on one N2k bus and others on other bus. Then in your code you just pass all traffic directly from one bus to other except STW, which you check and replace with SOG in case of problem with log information.
I think it would be cheaper to buy a new log than spend several hours writing reliable code, but of coarse it is not so fun. Like if I convert the time I have spend with NMEA2000 library to money, I could have bought several converters and MFD:s etc.
Hi Timo
concerning the fun, I absolutely agree with you. But in this case, it is not a question of buying a new log. The log is relatively new and the situation of blocking the wheel by seagrass, small mussels, or so come regularly.
Best Regards Uwe
OK. I think I need to do some development for library to check that there is no restriction to have two tNMEA2000 objects. There should not, but I have not tested. Also I need to check that all messages, which will not be handled, will be passed to gateway handler.
Hi Timo
It is not urgent. First I have to get the HW. In summer I live on my boat, so it it difficut to get the HW. I think this will be a project for the winter, when I live in germany. So take your time ;-)
Best Regards Uwe
Hi,
Within 3 weeks I have to take my boat up for winter, so I can take my Arduino Due for test bed. It has two can internally, so I can make ready gw code.
Timo
Hi, I am in the mediteranian, I will be sailing till mid of Nov. ;-)
Hi, I have Arduino due with nmea2000 working however I am not able to have two Address Claims on one Arduino program for two devices. Anybody can give me a hint how to send two Address Claims to the NMEA2000 network ?
Thanks
Fred
Hi, I am sorry I di not understood your question? Normally address claiming will be done automatically by library. As in examples in setup you only need to define your node type and optional default address: NMEA2000.SetMode(tNMEA2000::N2km_NodeOnly,22); Then in your loop you call periodically: NMEA2000.ParseMessages(); With those library will automatically respond to ISO Address requests and do address claiming if necessary.
Or are you thinking about having two devices - e.g. temperature monitor and wind monitor with different device information - on one same program? If yes, you currently can not. I have option for that, it is still under construction, since it is very rarely needed.
Hi Timo,
Thank you for the very fast reply ! Yes I want to have two devices : speed sensor and engine tilt on one same program. I want to have two devices in one Arduino due program that is connected to the n2k network. Currently those two devices are on the network and work OK but I can only claim one address. Sorry for the confusion. Newbie here with little programming knowledge.
Fred
Hi,
Still question is that do you actually need two different device address? On the bus sight it is only important that each device providing any type of data has unic ID, created from device information. Then they would work right on bus. Other devices as far as I have experienced are not much interested about device class and device function codes, which in principle defines the type of device. So even you define your device as class 60 (Navigation) and function 135 (Depth/Speed), you can still send tilt information and MFD:s should show both. So currently having two devices on same code is more just informative.
I'll do the mutidevice code readey on some day, but you have to wait some weeks for that.
Hi Timo,
The Garmin GPSMap 740 does not see the device if the Address Claim is not sent once. Then it cannot be configured. The data is on the bus. The Arduino program always does the Address Claim for one device automatic so the Garmin only sees this one and the other cannot be configured. Both devices are sending the device class and function codes when I look with NMEA reader on the bus, There are 2 Tilt devices for 2 engines and they need to be configured to the engines. No problem if it takes several weeks. The holiday season is here..... Thanks for looking at it.
Fred
I think you only mean that address claiming should be resent. Normally devices should request ISO address claim from other devices. We have noticed that some devices expect that device will send it periodically. So try this: void SendIsoAddressClaim() { static unsigned long LastSent=millis();
if ( LastSent+2000<millis() ) { LastSent=millist(); NMEA2000.SendIsoAddressClaim(); } } ... void loop() { ... NMEA2000.ParseMessages(); SendIsoAddressClaim(); }
Hi Timo,
Thanks for the tip to resend the Address Claiming on a regular basis. This is not what my problem is. However it does solve the common problem if some devices need a regular claiming. ( for those that want to test it, just remove the "t" in millist !) My problem only needs Address Claiming once for each device at the start of each device. I found however a quick and dirty solution if I send the Address Claiming for the second device later. I need to clean up my code and then it should be OK. Your solution would also help to delay the Address Claiming at the start of each device. This often is needed if devices do switch on before the bus is active. So thank you for the tip. I hope others can use it too. I intend to look at the bus in short time to look at the traffic as I still need to understand what devices are sending. Wish you a good holiday season !
Fred
In principle it should not matter when bus becomes active. Lets say you turn on one device, so it will do address claiming and start to send data to the bus. Then you turn on other and it does same. If the addresses are same, then one of those devices may reclaim its address. Next you turn on MFD. MFD should send ISO Address request for PGN 60928 (=ISO Address claim) with broadcast to find out what devices are on the bus. Other devices would again respond to this with their information. Normally MFD would then send ISO request for 126992 (Product information) for each device one by one. So now it knows alldevices on the bus. OK, then you turn on new device. It will again send address claiming. Now again MFD should then see this and query product information for new device. Also at least my GMI 20 MFD sends address claiming priodically (e.g. 20 sec) to check that which devices are still available on the bus. If some device does not respond, it drops it out from the list. So some devices does not do not send periodical request. Instead they expect others to send address claim in every 2-5 sec.
You are right. But I noticed the Garmin GPSMAP740 lost two engine devices on the bus and did not reclaim them even after a long period. Those devices have fuel consumption information and so the Garmin did not update. They are removed from the NMEA2000 list of devices. There must be a protocol problem. This is one of the problems I would like to see when watching the bus traffic.
Thanks Timo your expertise is of great help.
Fred
Sorry but I am still curious about your construction. So do you have those two engine devices on same Arduino? And speed also? So are we actually talking about 2 engine instances + speed, which can be send from one N2k bus device?
Yes exactly. In fact there are 2 engine devices not on the Arduino that provide fuel and RPM and on the Arduino are just two engine Tilt devices + paddle speed sensor ( waterspeed ). I would include some temperature sensors maybe later. If it is not time critical you could include a lot more devices. As the engine fuel and RPM devices are in the back of the boat it makes no sense to include them in the Arduino as that box is near the helm The engine Tilt use the ADC's on the Arduino.
OK. But still I do not see the real requirement for address claiming for two devices. You just do periodically e.g. 100 ms: NMEA2000.SetN2kEngineParamRapid(N2kMsg,0,N2kDoubleNA,N2kDoubleNA,Engine0Tilt); NMEA2000.SendMsg(N2kMsg); NMEA2000.SetN2kEngineParamRapid(N2kMsg,1,N2kDoubleNA,N2kDoubleNA,Engine1Tilt); NMEA2000.SendMsg(N2kMsg);
and also speed with 1000 ms period. Also you may need to send ISO Address claim 2000 ms period as discusssed earlier.
MFD should be happy to see your system as one device, which just send data from different sources. As far as I know there is no limitation on NMEA2000 how much different type of data one device can send.
Yes, I would like to try this. But there is no need to send Address Claim periodically. Once the Garmin has seen the device it can be configured and I do not think it looses the Address like the external engine interfaces do. However full test and looking at the bus with NMEAreader I need to wait until my friend is back after Christmas. With two devices I mean not the two engine Tilt devices but two different devices like speed and engine Tilt. The two enigine Tilt devices are working OK when I can configure them after they claimed address. They do not need to be configured as separate devices. So once they have been seen by the Garmin there is no problem.
OK. I think I need to do some development for library to check that there is no restriction to have two tNMEA2000 objects. There should not, but I have not tested. Also I need to check that all messages, which will not be handled, will be passed to gateway handler.
I thought I'd raise this ancient discussion from the depths of the Github servers instead of creating a new issue since it exactly fits my use-case:
I'm having the following simplified starting scenario:
[KUS NS-5 fluid sensor (Diesel)] <-------> [NMEA2k bus] <------> [SIMRAD Plotter]
My issue is that due to a special construction where and how the fluid sensor is attached to the tank, it always reports with some offset (e.g. tank in reality has 15% remaining while reporting 24%).
So my approach is to create a Gateway which simply looks for PGN127505 messages from the fluid sensor side on a first CAN interface, corrects the reported fluid level and sends the message on to the actual bus (out on a second CAN interface). I slightly patched your NMEA- and teensyx-libs for that to support two devices.
The setup now looks like:
[KUS NS-5 fluid sensor (Diesel)] <-------> [(CAN1) MY GATEWAY DEVICE (CAN2)] <-----> [NMEA2k bus] <------> [SIMRAD Plotter]
BTW: I took care of the "second bus" I now opened towards the fluid sensor (termination, power supply) - I created a custom PCB/circuitry.
Due to lack in understanding NMEA2000, I first did NOT forward any other communication between the fluid sensor and the bus, I thought I just need to manipulate the actual PGN127505 messages. The SIMRAD then reported some unknown network device with fuel level information, but couldn't reliably list it nor detect it when the SIMRAD plotters were powered off and back on. From the discussion here I now get the understanding that the Fluid sensor likely sends ISO address claims onto the bus and the SIMRAD plotters somehow either acknowledge those (or they actually don't send any reply to this, but use the information from the ISO address claim to list the fluid sensor correctly?)
So, I'm now figuring that I need to set my Gateway device into a mode where (in addition to manipulating the PGN127505 messages) I simply forward all other messages from the fluid sensor onto the bus and - if not even more important - I have to forward messages from the bus back to the fluid sensor (maybe I could find out which ones specifically, but I can simply gateway everything I guess). For this, I now set both of my tNMEA2000_Teensyx objects to tNMEA2000::N2km_ListenAndSend and added code to forward all messages besides the one I'm manipulating.
@ttlappalainen: I would really appreciate if you could confirm or correct my understanding/approach. Also: Did you ever continue investigation in supporting instantiating multiple tNMEA2000 objects and maybe adding example code for a simple "Gateway" functionality?
Thanks & BR Daniel
First: There is no limitation to have two instances of tNMEA2000.
Second: In principle in N2km_ListenAndSend mode it may work. You should relay all messages from Simrad side to sensor side and opposite and then modify only tank level message. Instead of using #include
#include <N2kMsg.h>
#include <NMEA2000.h>
#include <NMEA2000_teexnsyx.h>
#include <N2kMessages.h>
...
tNMEA2000 &NMEA2000_sensor=*(new tNMEA2000_Teensyx(tNMEA2000_Teensyx::CAN1));
tNMEA2000 &NMEA2000_bus=*(new tNMEA2000_Teensyx(tNMEA2000_Teensyx::CAN2));
...
void SensorMsgHandler(const tN2kMsg &N2kMsg);
void BusMsgHandler(const tN2kMsg &N2kMsg);
// *****************************************************************************
void setup() {
...
NMEA2000_sensor.SetN2kCANMsgBufSize(10); // Should be enough
NMEA2000_bus.SetN2kCANMsgBufSize(10);
NMEA2000_sensor.SetN2kCANReceiveFrameBufSize(100); // probably not even necessary. I think teensyx driver had big buffers as default
NMEA2000_bus.SetN2kCANReceiveFrameBufSize(100);
NMEA2000_sensor.SetMode(N2km_ListenAndSend,255);
NMEA2000_bus.SetMode(N2km_ListenAndSend,255);
NMEA2000_sensor.SetMsgHandler(SensorMsgHandler);
NMEA2000_bus.SetMsgHandler(BusMsgHandler);
...
}
// *****************************************************************************
void loop() {
NMEA2000_sensor.ParseMessages();
NMEA2000_bus.ParseMessages();
}
// *****************************************************************************
double FixFluidLevel(double FluidLevel) {
// do something with it
return FluidLevel;
}
// *****************************************************************************
void SensorMsgHandler(const tN2kMsg &N2kMsg) {
double FluidLevel,Capacity;
unsigned char Instance;
tN2kFluidType FluidType;
if ( ParseN2kFluidLevel(N2kMsg,Instance,FluidType,FluidLevel, Capacity) ) {
tN2kMsg N2kMsgFwd(N2kMsg.Source);
N2kMsgFwd.Destination=N2kMsg.Destination;
SetN2kFluidLevel(N2kMsgFwd,Instance,FluidType,FixFluidLevel(FluidLevel), Capacity);
NMEA2000_bus.SendMsg(N2kMsgFwd,-1);
} else {
NMEA2000_bus.SendMsg(N2kMsg,-1);
}
}
// *****************************************************************************
void BusMsgHandler(const tN2kMsg &N2kMsg) {
NMEA2000_sensor.SendMsg(N2kMsg,-1);
}
Have not tested above code.
It should also work with single bus.
Solution 1. Just do normal device (like on example BatteryMonitor) with your own product and device information. This should show up on Simrad with your device information. Manufacturer will be unknown, if you do not use some predefined MfgCode. Then catch fluid level from your sensor, modify it and send it as your own device fluid message.
Solution 2. Spy your sensor product and device information. Increment unique ID with one and use those information for your device. Then do the same as above. Now your own device should be visible on SIMRAD as second fluid sensor and same manufacture as other.
Actually above solutions are bit more complex, since you have to follow your fluid sensor source address so that you handle right sensor. For that you need to know your sensor NAME, which is 8 byte data provided by ISO address claim message. So you need to catch also ISO address claim message (60928) and if its data matches to your sensor NAME, you take source address and listen 127505 messages from that source. Library N2kDeviceList module does that for all devices and you can request source by name.
Wow, that's perfect support @ttlappalainen! Thank you! I expected a sentence but not complete example code (which I also wrote myself, but it differed from your suggestion in some places, so I made sure to use your approach).
Unfortunately I will not be able to get on said boat before May timeframe.
One more question though: When testing with OpenSkipper I noticed that it already showed my fluid/tank level when I simply sent out my own (or manipulated) messages. I didn't have to do ISO address claim etc.
Is there a possibility in OpenSkipper (or another [free] simulation software) to mimic behaviour like SIMRAD or other plotters where I can list further details of the device (MfgCode, ID, NAME ...)?
OpenSkipper does not care of devices and so shows device data without knowing anything about devices..
If library device is in node mode, it does address claiming automatically and you do not need to care of that. If you do it with my gateway way, address claiming will be done by devices automatically since all messages will be transfered to both sides.
My NMEA Simulator simulates devices and you can analyze bus messages. Unfortunately free version parses only first 100 messages and message console has been limited to 5000 messages. You can find it from http://www.kave.fi/Apps/
Hi Timo
hopefully you can help me in unstanding the behaivior of N2K devices. How selects a receiving device the "correct" source, if more than one device on the bus are sendind the same type of information. Is there a selection mechanism or so?
Best Regards Uwe