Go Down

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

timolappalainen

You just set other information to NA
    SetN2kEngineDynamicParam(N2kMsg,0,N2kDoubleNA,N2kDoubleNA,N2kDoubleNA,N2kDoubleNA,FuelRate,N2kDoubleNA);
NMEA2000.SendMsg(N2kMsg);

Interrupts should be short, so it should not effect too much to other routines. Anyway I prefer to use external or internal counters for calculations. I made my own fuel monitor with external counters with latches and even with that getting good results were tricky. You will also need dampers on fuel line. See e.g. http://www.floscan.com/html/blue/accessorydetail.php?aid=69

autopilotNOR

ok, thank you Timo.

regarding pulsation damper. I have a water absorber inside the fuel line. The sensor shall be mounted right after the tank and before the absorber. Do you think I still need this damper? The absorber holds approx half a liter of diesel and the fuel line is made of gummy with 12mm diameter.

timolappalainen

If your pump is pusation pump, you will need it. If it is rotation pump (very rare), it may work without.

It does not need to be those, but idea is important. They must be between engine and sensor on both input and return lines.

autopilotNOR

Hello,

may a stupid question, but kind of datatype I have to use for FluidType in:
   
Code: [Select]
SetN2kFluidLevel(N2kMsg, Instance, FluidType, Level, Capacity);

I get the hole time whatever I tried the message error: invalid conversion from 'WHATEVER' to 'tN2kFluidType' [-fpermissive]

timolappalainen

You must use tN2kFluidType type define in N2kMessages.h. E.g.

Code: [Select]
SetN2kFluidLevel(N2kMsg, Instance, N2kft_Water, Level, Capacity);

or

Code: [Select]
tN2kFluidType FluidType=N2kft_Water;
SetN2kFluidLevel(N2kMsg, Instance, FluidType, Level, Capacity);

autopilotNOR

Hey Timo,

got it! I just forgot that. Had a break of some month.

Another question, RapidEngineData how often do this need to be send? Is once or twice a second enough? When I think about RPM, for example, it needs to be updated a lot to get a smooth result?

autopilotNOR

#501
Aug 19, 2018, 12:32 pm Last Edit: Aug 19, 2018, 04:07 pm by autopilotNOR
Hi,

I just got the sketch for fuel rate and fuel tank finished but can not test it.

Do anybody have a couple of minutes to look through if this would work? I don´t mean to fix everything or show every the best way. Since I am not that genius in arduino programming I would already be happy if that will work before I start to optimize everything.

EDIT
" I just found some things,I would need smoothing for the tank volume as thoose are moving a lot when the boat is rolling and so on!"

Thanks a lot!

Code: [Select]
// Get tankvolume (pin 20 Teensy3.2) and fuelrate (pin 19), calculate and send through NMEA2K CAN

#include <Arduino.h>
#include <NMEA2000.h>
#include <N2kMessages.h>
#include <NMEA2000_teensy.h>
tNMEA2000_teensy NMEA2000;

// *********************************************
// NMEA2K related setup
// *********************************************

// List here messages your device will transmit.
const unsigned long TransmitMessages[] PROGMEM = {130306L, 127505L, 0};

// *********************************************
// Variables to setup function reading fuelrate
// *********************************************

volatile int pulsCountValue; // Storage for counted pulses through interupt function
unsigned int FuelRate; // Calculated litres/hour
unsigned char flowsensor = 19; // Sensor Input
unsigned long currentTime;
unsigned long startTime;
#define FuelRateUpdatePeriod 1000


// *********************************************
// Variables to setup function reading fuel tank level
// *********************************************

unsigned char tankVolumeSens = A20;
#define FuelLevelUpdatePeriod 1000

// *********************************************
// Variables to setup sending of NMEA2K message
// *********************************************


double Instance = 0;
double Level;
int Capacity;
tN2kFluidType FluidType = N2kft_Fuel;

void setup() {
  // Set Product information
  NMEA2000.SetProductInformation("00000010", // Manufacturer's Model serial code
                                 100, // Manufacturer's product code
                                 "Fuel Information System",  // Manufacturer's Model ID
                                 "1.1.0.22 (2016-12-31)",  // Manufacturer's Software version code
                                 "1.1.0.0 (2016-12-31)" // Manufacturer's Model version
                                );
  // Set device information
  NMEA2000.SetDeviceInformation(10, // Unique number. Use e.g. Serial number.
                                150, // Device function=Atmospheric. See codes on http://www.nmea.org/Assets/20120726%20nmea%202000%20class%20&%20function%20codes%20v%202.00.pdf
                                75, // Device class=External Environment. See codes on  http://www.nmea.org/Assets/20120726%20nmea%202000%20class%20&%20function%20codes%20v%202.00.pdf
                                2046 // Just choosen free from code list on http://www.nmea.org/Assets/20121020%20nmea%202000%20registration%20list.pdf
                               );
  // Uncomment 2 rows below to see, what device will send to bus. Use e.g. OpenSkipper or Actisense NMEA Reader
  //Serial.begin(115200);
  //NMEA2000.SetForwardStream(&Serial);
  // If you want to use simple ascii monitor like Arduino Serial Monitor, uncomment next line
  //NMEA2000.SetForwardType(tNMEA2000::fwdt_Text); // Show in clear text. Leave uncommented for default Actisense format.

  // If you also want to see all traffic on the bus use N2km_ListenAndNode instead of N2km_NodeOnly below
  NMEA2000.SetMode(tNMEA2000::N2km_NodeOnly, 23);
  // NMEA2000.SetDebugMode(tNMEA2000::dm_Actisense); // Uncomment this, so you can test code without CAN bus chips on Arduino Mega
  NMEA2000.EnableForward(false);
  NMEA2000.ExtendTransmitMessages(TransmitMessages);
  NMEA2000.Open();

  // Void Setup for Fuel Rate
  pinMode(flowsensor, INPUT_PULLDOWN);
  digitalWrite(flowsensor, LOW); // Optional Internal Pull-Up

  attachInterrupt(0, pulsCounter, RISING); // Setup Interrupt

  sei(); // Enable interrupts
  currentTime = millis();
  startTime = currentTime;

  Serial.begin(9600);

  // Setup for Fuel Rate END
}

void loop() {

  // *****************************************************************************
  // Call the looping functions
  // *****************************************************************************

  SendN2kFuelRate();
  SendN2kFuelLevel();
  NMEA2000.ParseMessages();
}



// *****************************************************************************
// Double replacement for standard map function
// *****************************************************************************

double dMap(double x, double in_min, double in_max, double out_min, double out_max) {
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

// *****************************************************************************
// Interupt function. Count pulses from interupt.
// *****************************************************************************

void pulsCounter() {
  pulsCountValue++;
}

// *****************************************************************************
// Read and calculate fuelrate based on pulses from pin 19
// *****************************************************************************

double ReadFuelRate() {

  currentTime = millis();
  // Every 3 second, calculate and print litres/hour
  if (currentTime >= (startTime + 3000))
  {
    startTime = currentTime; // Updates startTime
   
    FuelRate = (pulsCountValue * 3.6); // (Pulse frequency x "3600/1000" 3.6 = flowrate in L/hour

    //    Serial.print(FuelRate, DEC); // Print litres/hour
    //    Serial.println(" L/hour");
  }
  return FuelRate;
}

// *****************************************************************************
// Read and map current fuel tank volume based on pin 20
// *****************************************************************************

double ReadTankVolume() {
  double Level= dMap(analogRead(tankVolumeSens), 60, 900, 0, 100);
  return Level;
}

// *****************************************************************************
// Send NMEA2K message for Fuel rate
// *****************************************************************************

void SendN2kFuelRate() {
  static unsigned long FuelRateUpdated = millis();
  tN2kMsg N2kMsg;

  if ( FuelRateUpdated + FuelRateUpdatePeriod < millis() ) {
    SetN2kEngineDynamicParam(N2kMsg, Instance, N2kDoubleNA, N2kDoubleNA, N2kDoubleNA, N2kDoubleNA, FuelRate, N2kDoubleNA);
    FuelRateUpdated = millis();
    NMEA2000.SendMsg(N2kMsg);
    pulsCountValue = 0;
  }
}

// *****************************************************************************
// Send NMEA2K message for fuel tank level
// *****************************************************************************

void SendN2kFuelLevel() {
  static unsigned long FuelLevelUpdated = millis();
  tN2kMsg N2kMsg;

   if ( FuelLevelUpdated + FuelLevelUpdatePeriod < millis() ) {
    SetN2kFluidLevel(N2kMsg, Instance, FluidType, Level, Capacity);
    FuelLevelUpdated = millis();
    NMEA2000.SendMsg(N2kMsg);
  }
}


timolappalainen

NMEA2000 defination for RapidEngineData is 10 times/second.

If you are not sending WindSpeed PGN, you should not list it on TransmitMessages. If you are sending EngineDynamic parameters, you should list that on TransmitMessages.

Set the SetProductInformation and SetDeviceInformation right.

What kind of sensor (pulses/litre) you have and how much you expect to burn fuel in hour? As quick calculation your code accuracy can not be very good.

For analog read you can increase accuracy by increasing avaraging with analogReadAveraging(32); and/or putting readings to ring buffer and averaging that. Fuel level does not need to be very quick, so you could have e.g. 60 readings long ring buffer where you update reading every second. Then you have 1 minute averaging value.

autopilotNOR

Hello Timo,

Thx.

The sensor for fuel rate is a G12 OF 201. I tested it out and it gives 7.13 ml/puls. I let 2 liters flow 20 times through the sensor and measured & calculated the average with result 7.13ml/puls.


If I am right then fuel rate is a rapid date, right? So it will be sent every 100 msec. I do not think it is a problem at full rate but if I average the value lets say for 2 or 3 seconds I would send values from the past? This is not a problem I know.
Other more important rapid data like rpm, in one-second huge changes can happen here. What is here a better solution then count the pulses and average them?

I have seen a couple of status "flags" in the n2kmessages.h like flagOverTemp, flagLowOilPress, flagLowOilLevel and so on. I have some sensors on that engine which are not connected anywhere like for example right under the RTC for the coolant temp. I think these are alert "switches" / sensors to give an overheat signal for example. If I am right with this sensor then those flags are for this unconnected sensors right? If not, they could be calculated and set when the temp is going over a fixed defined limit? Its just a thought, I do not know yet if mayAxiom have some functions regarding this flags.

Are you using this flags? I mean it is very cool to create a complete digital engine control panel for older engine for example.

timolappalainen

How much your engine is eating fuel/h?

So if you have 8 ml/pulse you will have 1000 / 8 pulse/l = 125 pulse/liter. If your engine takes 40 l/h, it means 5000 pulse/h = 1.39 pulse/s This means that you can not calculate pulses with 1 s period. Not even with 3 s - as you do in ReadFuelRate - giving you sometimes 3 pulses and sometime 4 pulses causing 33% changes. And by the way you newer call ReadFuelRate and do not update FuelRate variable. On idle engine takes so little fuel, that you can not measure it.

If the fuel stream is steady, you can get some results by measuring distance of each pulse in microseconds. But even that value you have average e.g. by using ring buffer.

Fuel rate is not on rapid PGN. It is on Engine Dynamic Parameters PGN, which you update once per second.

I have not used flags under engine dynamic parameters. Some MFD:s can show alarm according to them.

autopilotNOR

#505
Aug 21, 2018, 03:22 pm Last Edit: Aug 22, 2018, 12:25 pm by autopilotNOR
Hi Timo,

of course, you are right if I think about this now! I also saw this type of calculation/measurement where the time between the pulses is base for the calculation. I couldn´t figure out how that person who wrote that code came on the value of 7.5 puls per liter per hour.

the other errors.. before I posted this code I had sent you a PM a couple of days before. May you didn´t saw that. I don´t want to spam the thread with my code full of failures because I am not able yet ( or maybe never) to get this correct done.

EDIT: I jus realized what you have mentointed that fuel rate is not rapid data. So the next part is not right.

/ wrong

Regarding SetProductInformation and SetDeviceInformation, I am sure I didn´t think the whole thing to the end before I started with this device(s). EngineRapid data like FuelRate and Fluid level are different classes and functions. So this will then by a multidevice, right?
If so I will remove the fuel rate and put that first into its own device and may later with into the main device for the engine where all rapid- & dynamic data shall be generated.

wrong /

I will try to correct all you mentioned. Can I send it to you by PM or shell I post it here again?
I am sure you have better things to do than teaching me all this and correct all I try to create. Unfortunately, I have no idea where to post or ask somewhere else since this is tight together with your nmea2k library.

Regards & thanks

autopilotNOR

Just found a good fitting flow sensor for an affordable price (about 100 €).

It is the GEMS FT-210 made of Polyamid which is gasoline and diesel nonreacting.

This sensor delivers 22.000 puls / liter and goes official according to the specs from 0.1L/min to 2.5L/min which are from 6L/hr to 150L/hr. But I guess if accuracy do not count as much under 6L/hr then it would deliver 367 puls/sec at 1L/hr.

This would be great for the flow meter application.

Here is the link to the manufacturer if somebody is interested: GEMS FT-210 0.1 to 2.5 L/min 22.000 puls/L

I think with a so high puls rate simple smoothing would be enough to update the flow rate once per 2-3 seconds?

timolappalainen

I will try to correct all you mentioned. Can I send it to you by PM or shell I post it here again?
I am sure you have better things to do than teaching me all this and correct all I try to create. Unfortunately, I have no idea where to post or ask somewhere else since this is tight together with your nmea2k library.

Regards & thanks
Sorry, I did not notice PM. I had marked it read somehow. Yes you can send me PM.

You do not need to use MultiDevice. The Class and Function are informative and does not effect for device functionality.

I can do some guiding with coding, but currently I have reasonably big project under coding.

timolappalainen

About other sensor. The problem with counting is syncronizating system. I used external counter chip, but actually still better may be just measure time between pulses. GEMS FT-210 provides maximum 150 * 22000 /3600 = 917 p/s, which is not much - 1 ms / p ans so could be measured by using us timer. There is also FreqCounter and FreqMeasure libraries for Teensy.

You still have not answered how much your engine will take fuel / hour. Also it is important that does it have only one fuel line or like I have 2 - one for in and one for return. So I need two sensors and need to calculate difference.

autopilotNOR

About other sensor. The problem with counting is syncronizating system. I used external counter chip, but actually still better may be just measure time between pulses. GEMS FT-210 provides maximum 150 * 22000 /3600 = 917 p/s, which is not much - 1 ms / p ans so could be measured by using us timer. There is also FreqCounter and FreqMeasure libraries for Teensy.

You still have not answered how much your engine will take fuel / hour. Also it is important that does it have only one fuel line or like I have 2 - one for in and one for return. So I need two sensors and need to calculate difference.

I figured out now how this would work with using the time between the pulses instead. That`s why  I came to the conclusion that the flow sensor I have do not fit at all since it would need about 25 seconds to get a puls at a rate of 1L/hr.
I was thinking about to block all counting until it reaches about 4-5 L/hr, but this wouldn`t be effective since I wanted this sensor data because I would like to use the calculation functions of my MFD when it comes for example to if I would have enough fuel to come to the next waypoint and so on. So it wouldn`t make sense if I do not have the data down to the minimum of use of fuel from the engine.

However, I will start over again and take out the fuel tank level, for now, just to have more overview and it is better to get one by one working before I start combining everything. The new sensor should arrive may tomorrow so I can test a bit.

I also need to get the heading data out of a Bosch BNO055. This looks complicated for me so I even didn`t try it yet. I bought that sensor once to create a DIY automatic control for the trimtabs. I understood fast to drop that completely for a longer period. :-)

Go Up