ttlappalainen / NMEA0183

Library for handling NMEA0183 messages
69 stars 44 forks source link

Timing of sending Messages unclear #12

Closed ronzeiller closed 4 years ago

ronzeiller commented 4 years ago

Hi Timo, in the example https://github.com/ttlappalainen/NMEA0183/tree/master/Examples/NMEA2000ToNMEA0183 you have:

void tN2kDataToNMEA0183::Update() {
  SendRMC();
  if ( LastHeadingTime+2000<millis() ) Heading=N2kDoubleNA;
  if ( LastCOGSOGTime+2000<millis() ) { COG=N2kDoubleNA; SOG=N2kDoubleNA; }
  if ( LastPositionTime+4000<millis() ) { Latitude=N2kDoubleNA; Longitude=N2kDoubleNA; }
}

Could you please help me to get me on the right trail, how this is doing the timing of message sending? And why those values are set to N2kDoubleNA ?

Especially with building NMEA0183 which are built on more of one PGNs (e.g. calculating Leeway or VHW where heading is needed, not coming with ParseN2kBoatSpeed() and so on) I need those "old" values.

What do I miss out here? Thank you in advance for spending time on this, Ronnie

ttlappalainen commented 4 years ago
void tN2kDataToNMEA0183::SendRMC() {
    if ( NextRMCSend<=millis() && !N2kIsNA(Latitude) ) {

Above takes care of SendRMC() timing. Write similar for each message.

The other tests just disables data by setting them to NA after timeout, if you do not receive them. After e.g. Latitude has been disabled, SendRMC does not send it anymore. Without disabling values your system would just continue to send old data for coming future, if you loss e.g. Lat/Lon. That would not be safe.

By the way. The Update will called in loop with high speed so to save some calculations on loop every time I use in my projects setting timeout insteat of Last... value: ... PositionTimeout=millis()+4000; ... if ( PositionTimeout<millis() ) { Latitude=N2kDoubleNA; Longitude=N2kDoubleNA; } ... Then you save that summing on all tests.

ronzeiller commented 4 years ago

Thank you Timo, that you took care and helped me to get on the right track again.

In deed I got confused with the < millis() and the resulting logic!

And I got confused by an example code from somebody else, based on the NMEA2000ToWiFiAsSeaSmart example, where suddenly NMEA0183DoubleNA values where shown..... But this is clear to me now. And then I also had a closer look at the NMEA0183setXXX()functions in NMEA0183Messages.cpp, where you always test if a value!=NMEA0183DoubleNA too.

It is an example of course showing principles, but would it be wise in production code to even parse N2k GNSS if I do not want to send? In other words: would it be not better to do the timing in the incoming HandleMsg() part for example?

ttlappalainen commented 4 years ago

N2k messages will be parsed, when they arrives. That is set on main.cpp with NMEA2000.AttachMsgHandler(&N2kDataToNMEA0183); Then library calls tN2kDataToNMEA0183::HandleMsg(const tN2kMsg &N2kMsg) on NMEA2000.ParseMessages() when message arrives. GNSS lat/long will be then parsed, even you will not forward them to NMEA0183. Naturally also other values could be kept global as I do in other system.

As you see some of the messages like HDT will be forwarded directly from HandleMsg.

One note about mixed data on NMEA2000. You may easily have several GNSS or HDT messages on your system. Due to small inaccuracy between devices, you should also have possiblity to select priority for those and use highest priority device data as far it is available. This simple example does not handle that and if you have e.g. GPS, Airmar weather station and Transmitting AIS on your bus, NMEA0183 data will be mixed by those. For handling devices you need to use N2kDeviceList module.

ronzeiller commented 4 years ago

Thank you Timo and also thanks for the hint about the mixed devices, I will take care, but have to read more about this in your great library and examples!