ttlappalainen / NMEA2000

NMEA2000 library for Arduino
535 stars 224 forks source link

PGN127489 turning on and off data different behaviour between Garmin and Maretron #169

Closed virtuvas closed 3 years ago

virtuvas commented 4 years ago

Timo,

optimising and finalising the code running on each engine Main PGNs sent from each teensy are Dynamic Engine Rapid Engine Transmission and the custom Maretron EGT

all's working fine but now stuck at home (not allowed to the boat!) so got both the Maretron DSM250 and a Garmin GMI10 on the same bus together with the teensy. All terminated properly and working properly. Now wanted to simulate, starting the engine, pumping values from various sensors to the bus, then turning off, all values back to zero except for Voltage in my case where I'd still like to see what the batteries show (starter or service bank). Concluded the following tests with some shocking results.

Test1 (engine off/system off): PGN127489, sent EVERYTHING (except N2kMsg and EngineInstance of course!) as N2kDoubleNA (and the last two N2kInt8NA) all presented properly (all gauges configured are empty!) in both M & G Test2 (engine on): sent Voltage, OilTemp and OilPress values, something valid. Both M & G present them fine, temps, bar, volt, coolant press, hours, etc empty. Test1 (engine off/system off): again all empty, fine Test3 (engine off/system on): sent ONLY one valid value, say Voltage 24 Garmin will show Voltage, all other gauges EMPTY Maretron will show Voltage as well, BUT will also show ALL LAST valid values I sent in Test2, so although I can check that I'm sending N2kDoubleNA for oilpressure, it will show the last valid value (for example 2.5bar) Test1: all empty, fine all gauges off on both G & M Test3: with any valid value (JUST ONE!), all others sent empty will show up. Garmin shows only the one I sent again.

Now, Maretron is a serious company, doubt it's something they do wrong, pretty sure it's my fault, but WHERE??? From your experience, any pointer before starting sending the Dynamic Engine routine as well as my setup?

thanks!

V.

ttlappalainen commented 4 years ago

Welcome to NMEA2000 standard world! It does not mean that you are not doing something wrong, but you just do not follow Maretron logic. Have you checked is there setting on Maretron "On data lost show last value".

Your could also simulate those with my NMEA Simulator easily. There you can click messages on/off and also fields valid/NA on the fly. May be easier to do this kind of comparing than with real device.

The problem may be something very stupid. It did not understood what does mean "system off"? Do you stop sending data or just send all (except voltage) as NA? If you sent NA, I would expect the right behaviour for MFD is to somehow indicate that data for that field is NA. But if Maretron does not behave in that way, you have to test is there some field you should provide valid value. So there are lot of combinations, which would be easier to test with simulator:

Also check that you are sending 127488 100 ms and 127489 500 ms period.

You could also spy bus that does Mareton send any data requests with 126208 or 59904 to your device. If yes, you have to record data and check does they point to 127488 or 127489.

virtuvas commented 4 years ago

Welcome to NMEA2000 standard world! It does not mean that you are not doing something wrong, but you just do not follow Maretron logic. Have you checked is there setting on Maretron "On data lost show last value".

thank you Timo :) Studied the Maretron Manual, no mention of anything like that! Lots of info on how to deal with own Maretron devices, no mention about generic h/w...

Also check that you are sending 127488 100 ms and 127489 500 ms period.

Checked, have a timestamp on each submission for both, maybe not exactly 100 but from 98 to 102, but it could be the Serial.print that delays that much.. Anyway, yes, periods are right.

Problem only appears with 127489. I'm wondering if this is due to the fact that both 127488 (rapid) and 127493 (transmission) are PGNs that you CANNOT sent NA to all fields! I mean 127488 you cannot sent EngineSpeed NA (I tried N2kDoubleNA, got 8100something, tried N2kInt8NA got 127 or something :) ) for 127493 you cannot sent TransmissionGear- OK you can sent unknown (3) but it's probably not the same thing.

Your could also simulate those with my NMEA Simulator easily. There you can click messages on/off and also fields valid/NA on the fly. May be easier to do this kind of comparing than with real device.

The problem may be something very stupid. It did not understood what does mean "system off"? Do you stop sending data or just send all (except voltage) as NA? If you sent NA, I would expect the right behaviour for MFD is to somehow indicate that data for that field is NA. But if Maretron does not behave in that way, you have to test is there some field you should provide valid value. So there are lot of combinations, which would be easier to test with simulator:

all except one, could be voltage, could be any other one.

Tried all combinations, as long as ONE is valid, all other fields that had at some point a valid value but are now NA will show the last valid value and not empty. This is true if I only sent oilpres, or oiltemp, or voltage, or coolantpress, or whatever, just sent one and you have the problem. If I sent NA to all fields, all fields are empty. OK, I can do that, but was hoping that the system would behave properly and only show whatever value is sent I mean I don't like sending this (serialprint of the SetN2kEngineDynamicParam):

Eng #:1, ClntTemp: -1000000000.00, OilPres: -1000000000.00, OilTemp: 353.15, S/w Press: -1000000000.00, Volt: -1000000000.00

and getting from Maretron oiltemp of 80 (which is fine) plus all values filed with last used values on screen!

You could also spy bus that does Mareton send any data requests with 126208 or 59904 to your device. If yes, you have to record data and check does they point to 127488 or 127489.

I'll try and do the spying tonight and report back.

In the meantime and just in case I'm sending the relevant setup code (I doubt I have something seriously wrong there, as it's working on the Garmins just fine):

void setup() {

  analogReadResolution(12);

  NMEA2000.SetN2kCANSendFrameBufSize(800);
    NMEA2000.SetProductInformation("1212136",  
                                  1210,                           
                                  "GVD ECU-STBRD",          
                                  SWVER,
                                  MANMODEL,               
                                  0x02,                           
                                  0xffff,                        
                                  0xff                            
                                 );
    NMEA2000.SetDeviceInformation(1212136,  
                                 160,       
                                 50,        
                                 1210,    
                                 4           
                                );
//    NMEA2000.SetMode(tNMEA2000::N2km_NodeOnly, 136);
    NMEA2000.SetMode(tNMEA2000::N2km_ListenAndNode, 136);
  }

  NMEA2000.EnableForward(false); // Disable all msg forwarding to USB (=Serial)
  // Here we tell, which PGNs we transmit for each device
  NMEA2000.ExtendTransmitMessages(TransmitMessages);
  NMEA2000.ExtendFastPacketMessages(ExtendedFastPacketMessage);
  NMEA2000.SetMsgHandler(HandleNMEA2000Msg);
  NMEA2000.Open();
}

and a stripped down version of the routine sending dynamic engine data

const int EngineDynamicParamsUpdatePeriod = 500;    //must be 500

////////////////////////////
void EngineDynamicParams() {

  static unsigned long EngineDynamicParamsNextUpdate = millis();
  tN2kMsg N2kMsg;

  if ( EngineDynamicParamsNextUpdate < millis() ) {
    EngineDynamicParamsNextUpdate  += EngineDynamicParamsUpdatePeriod;
  EngineInst = 1;

  OilPressureB = mBarToPascal(4000);
  EngineOilTempB = N2kDoubleNA;
  CoolantTempB = CToKelvin(70);
  AltVoltB = 24.5;
  EngineHoursB = 300;
  SeawaterPressureB = N2kDoubleNA;
// ...

      SetN2kEngineDynamicParam(N2kMsg, EngineInst, OilPressureB, EngineOilTempB, CoolantTempB, AltVoltB, N2kDoubleNA, 
                               EngineHoursB, SeawaterPressureB, N2kDoubleNA, N2kInt8NA, N2kInt8NA);
//    }
    NMEA2000.SendMsg(N2kMsg);
  }
}

final question, how often should we be sending NMEA2000.ParseMessages()? once at the end of the loop function is enough?

cheers

V.

ttlappalainen commented 4 years ago

There seem to be bug in library for SetN2kPGN127488. It should have N2kMsg.Add2ByteUDouble(EngineSpeed,0.25); Then N2kDoubleNA should generate NA to bus.

For 127493 discrete status you have to send 0, if all is OK.

It may be some Maretron logic to keep last value, if new value is unknow. Garmin does it right.

It is enough to call NMEA2000.ParseMessages() once in loop, but you should take care that any other call in your loop does not use delay and stay long in that procedure. If some call in your loop need long delay, you should rewrite that part so that it is kind of state machine and for each delay state you check from timer when has it delayed enough. Unfortunately this does not work for strict delays specially for delaymicroseconds like OneWire needs.

On the other hand with Teensy you have fully buffered receive and transmit, so it is not so critical to call it in every ms. You can receive 2.5 frames/s so if you expect you may have 10 ms of time, 25 frame receive buffer should be enough. For 60 ms off time you should have 150 frame receive buffer. Transmit buffer you have to calculate according data you may buffer once.

virtuvas commented 4 years ago

Corrected the bug, does generate NA so gauge disappears (that was my plan) so one done!

Now, could it be that on 127489 AlteratorVoltage and FuelRate should also be: Add2ByteUDouble() ?? can you go negative or what? BTW, tried changing them didn't seem to improve anything...

Done async my OneWire, this improved all my routine's speed immensely, so should be OK with once per loop for the NMEA2000.ParseMessages() Looks like my:

NMEA2000.SetN2kCANSendFrameBufSize(800);

is pointless then? remove it altogether?

will report again when I do the N2K bus spying

cheers

V.

ttlappalainen commented 4 years ago

Alternator potential and fuel rate are right - they are signed and can be negative in point of NMEA 2000. I do not know how they can be negative physically. They have also temperature signed - negative or even 0 Kelvins is difficult to reach.

100-150 send frame buffer size should be OK.