NMEA 2000 Shield

EEPROM has been guaranteed to work with 100000 write cycles. If you save rarely enough, it is not problem. With 5 s priod you will reach that less than week.

If you have battery on Teensy, you can use VBAT registers.

struct tNvRamData {
   uint32_t EngineRunTime;  // Seconds
};

#define NVRAM_BASE 0x4003E000

tNvRamData *pNvRamData=(tNvRamData *)(NVRAM_BASE); 
...
  pNvRamData->EngineRunTime+=...;
...

tNvRamData has been defined as struct, so you can easily add there more data.

There are totally 32 VBAT registers, but I read somewhere that 0x4003E01C has been used by Teensy code, so there is 28 byte available. This means max. 7 uint32_t.

When you save to SD card, other than interrupts will be stopped.

Very good Timo, thx!

Yesterday I was checking the signal of RPM, that was really strange!
According to the documentation, the signal for rpm should come from an explicit sensor and not from the generator. But I got frequencies from 500 hz to over 1 khz ( see picture attached).
I am not sure, is this frequency normal if this signal comes from the generator?
The results are not hundred % correct.
RPM Hz
1000 520
1100 560
1200 640
1300 690
1400 725
1500 800
2000 1080
2500 1350

See the picture of the oscilloscope at 1000 rpm attached.

So is that normal?

rpm.png

Hey Timo,

I was testing the whole stuff yesterday in the boat. I can't see anything on the MFD at all? Strange is that I can see all traffic coming from the MFD through the NMEAReader on the teensy.

Do you any hint what could cause that the display does not see the devices at all?

All traffic forwarding is enabled in the config, I tested with enabled serial output and without and forward(false) is commented out.

Regards..

What mode you have set to library? Should be N2km_ListenAndNode so that it would act as normal bus device.

Forwarding affects only for message forwarding to ForwardStream - normally USB. So even you have frowarding disabled bus communication works normally.

All devices are set to N2km_ListenAndNode . I checked also the documentation of the Axiom. The PGN's are supported. Engine Instance is set to 0. Can speed I tested the standard 250.000 up to 1.000.000, also lower than 250.000. Now I have all set back to 250.000 as I couldn't find out what the speed of the Axiom is (or if this is auto-sense). This drives me crazy, all the work and now nothing is working. The device under itself can see each other. Will say the rudder position device can see the engine and visa vi. The strange thing is that I can see the GPS data and all other stuff coming from the axiom on the devices?! Updated the Axiom also to latest Lighthouse as there where some bugs NMEA2k related in the past. I remember when I have begun with all this I used an Arduino due, With that and the MCP 2562 I got them connected. I use now the SN65HVD234D with Teensy 3.2 & 3.5. FlexCan and all other libraries like NMEA2000 , NMEA2000_teensy, N2KMessages are included. Do I have to set something Flexcan related?

I guess it must have something to do with the SN65HVD234D, even the default sketches like Battery monitor or message sender are shown on the display. But why can the self-made devices see each other then?

NMEA2000 is fixed to 250 kb.

Use FlexCan only from my git and delete the one under Teensy libraries.

Can you receive bus data with same Teensy? If yes, then you have problem with tranceiver.

Why did you changed MCP2562? I have not had any problems with it. Have you connected pin 5 to 3.3V? How did you connect RS pin 8?

I found out the problem..

It is the SN65HVD234D ! Just not working! I changed to the SN65 because it had some better values like more bandwith, lower power (not that this is prio) and it didn't needed 5V.

The SN65 worked perfectly all in lab, all devices could communicate and everything looked fine. It is a bt more expensive the SN65.

Now I have 16SN65 laying around here without any use.. What do you think what can be the reason, any idea?

The MCP2562 worked now immediately. Again thrown 2 days..

Hi all,

Some questions to those who might know.

I was reading trough Timos NMEA0183ToN2k.ino. How it is defined where/ in which serial GPS receiver is connected?

Would this be ok receiver to get GPS data to Arduino to be transmitted to NMEA2000: https://www.sparkfun.com/products/13740 ?

If I had two of those would they make a GPS compass when installed 6 m apart from each others? Like in this example: https://learn.sparkfun.com/tutorials/gps-differential-vector-pointer ?_ga=2.111597508.1910172968.1538324202-1706626596.1503061770

Is there a way to transmit roll and pitch rates in NMEA 2000? Would it be benefical to use that data to compensate mast head movement in wind measurements? Or is wind data too filtered for that? I have roll and pitch rates on one arduino and have been thinking if I want to buy wind instruments and make VMG and true wind calculations should those calculations be made at the same arduino where I have the sensor for autopilot.

Is rate of turn supported in Timos work?

What is the unit for speed in NMEA2000? m/s I suppose.

On line 67 NMEA0183_3.SetMessageStream(&Serial3);

Check N2kMessages.h SetN2kAttitude

N2kMessages.h should have in function description required unit. Normally they are SI.

If you provide wind data to the bus, it would be best that it would have all conpensations.

Heikkif: If I had two of those would they make a GPS compass when installed 6 m apart from each others? Like in this example: https://learn.sparkfun.com/tutorials/gps-differential-vector-pointer ?_ga=2.111597508.1910172968.1538324202-1706626596.1503061770

I read a bit more about that GPS pointer. I can not say for sure how accurately that would work. With 20 cm error in position on 6 m base you would get about 2 deg. error.

The one problem is that you do not have control to synchronize those receivers. Also they send position data in 1 Hz, which is very slow for making any filtering in moving boat. Real GPS compasses has antennas directly connected to the device, so they can follow satellites fast enough to also filter calculated position information. I have GPS compass with 50 cm antenna separation, but there both antennas are directly connected to the compass unit. That provides <1 deg. accuracy all the time and it sends HDT information to other systems with 10 Hz.

If you would add accurate movement sensor to the system, you could get fast movement infomation from it. Then you could probably have some filtering on both GPS position to calculate better heading. But still the problem would be that when you get position information from GSP, it is allready 1 sec. late.

Hey Timo,

I have some trouble with temperatures. In this case with the coolant temperature.

I measure the value through a voltage divider in parallel to the existing analog gauge.

My Axiom can show Fahrenheit and Celsius. So far so good. I get a value shown on the display of -271 C and according to the messages.h Kelvin is to be sent right?

I could not find out yet what the correct form is, I tried some conversion functions you predefined and they worked fine but still, I can´t figure out what is wrong here.

How do I have to map the temp, is there any definition out there which tells me the temperature range? What I mean is how do I map the 0-3.3 V. For example from -20 to 150 ?

That is simple linear conversion:

TempC = -20 + (x-0)*(150- -20)/(3.3-0); // , where x is your voltage.

For library function you have to provide values in Kelvin, so you use ...CToKelvin(TempC)...

Or better would be use SI in code inside and use conversion only for view values. Then your function would be:

TempK = 253.15 + (x-0)*(423.15-253.15)/(3.3-0);

Then you can just pass TempK to library function.

timolappalainen: That is simple linear conversion:

TempC = -20 + (x-0)*(150- -20)/(3.3-0); // , where x is your voltage.

For library function you have to provide values in Kelvin, so you use ...CToKelvin(TempC)...

Or better would be use SI in code inside and use conversion only for view values. Then your function would be:

TempK = 253.15 + (x-0)*(423.15-253.15)/(3.3-0);

Then you can just pass TempK to library function.

That looks good so far, just one thing: It results in a negative value. I get shown -21.7 C and just multiplying it by -1 doesn't work for any reason.

Can this be used for any kind of temp value like oiltemp ?

What shows -21.7 and why it should be multiplied with -1?

If your x is positive, the function returns allways >=-20 C!

Linear scaling works for any kind of sensor, which has linear scale. E.g. tank sensors have often non linear scale due to irregural tank shape. Then one has to split it several smaller ranges, where linear scaling gives reasonably good result.

timolappalainen: What shows -21.7 and why it should be multiplied with -1?

If your x is positive, the function returns allways >=-20 C!

Linear scaling works for any kind of sensor, which has linear scale. E.g. tank sensors have often non linear scale due to irregural tank shape. Then one has to split it several smaller ranges, where linear scaling gives reasonably good result.

The MFD showed a temp of -21.7 C. The voltage is currently 1.151 V on the analog in. But now the engine is almost warm (~55 C) In code I use the following:

double EngineCoolantTemp = 253.15 + (analogRead(coolantTempPin)-0)*(423.15-253.15)/(3.3-0);

and pass the EngineCoolantTemp through return back. In SendN2kMessagesDynamic I call the function by EngineCoolantTempRead() inside EngineCoolantTempRead() with all the others which have todo with Engine parameter dynamic.

analogRead(coolantTempPin) does not return voltage. It return integer value depending of your analog resesolution. So e.g. with 10 bit resolution it will return value 0 - 1023 and for 12 bit resolution 0 - 4095. The resolution depends of device you are using and in some devices you can control it with analogReadResolution() function.

Then you need to scale value from analogRead with range it is using. That depends of analog reference voltage. E.g. on Teensy you can select internal analog reference with analogReference(0) and then it will use 3.3 V ref. In that case you you convert 10 bit analog pin data to voltage with function analogRead(coolantTempPin)/1023*3.3

So check which resolution and reference you have to get right conversion to voltage.

timolappalainen: analogRead(coolantTempPin) does not return voltage. It return integer value depending of your analog resesolution. So e.g. with 10 bit resolution it will return value 0 - 1023 and for 12 bit resolution 0 - 4095. The resolution depends of device you are using and in some devices you can control it with analogReadResolution() function.

Then you need to scale value from analogRead with range it is using. That depends of analog reference voltage. E.g. on Teensy you can select internal analog reference with analogReference(0) and then it will use 3.3 V ref. In that case you you convert 10 bit analog pin data to voltage with function analogRead(coolantTempPin)/1023*3.3

So check which resolution and reference you have to get the right conversion to voltage.

That was actually my initial question. How to map the 0-1023 to the coolant temp value. This you wrote here I know about (would be very difficult without i guess)

The point I need to know here is what to do with the 0-1023? Usually, there is a range it can be mapped to like I do with the oil pressure. There I use the custom map function (you showed me once I tried my luck with the rudder position) to 0 - 10000 pascals.

In the example of rudder position, the drive I have and the MFD Axiom shows -50 - 0 + 50 degrees. So I map here the 0-1023 like this rudderposition=(analogRead(rudderPositionPin), 49, 1023, -50, 50).

So in case of temperature, I don't know the range I can map it on. I thought there are somewhere definitions or standards which tells me what to use.

Hi Timo,

Thanks for the prompt replies. Question of GPS compass has been discussed here:

https://forum.arduino.cc/index.php?topic=366167.0

So necessarily it does not work that way. Was not mentioned what kind of base was used. Anyhow I want to have a GPS to the bus so I will get some receivers. This could be what I will buy:

https://www.banggood.com/Radiolink-M8N-GPS-Module-UBX-M8030-for-Naze32-APM-CC3D-SP-F3-Naze32-Flip32-PX4-Flight-Controller-p-1051291.html?rmmds=search

It has freq. of 10 Hz.

I have rate of turn measured with a quite good gyro at autopilot. I could feed that to bus and use it on another Arduino to improve dynamics of filtered heading from calculations the same way that I did with roll and pitch calculated from accel signals.

Would it be all wrong if arduino would read GPS-position of the other sensor from bus and other would be connected to serial?

Please do not quote everything as it is, since it does not make sense, since same can be read on previous post.

Do you mean dMap function example I wrote on post #351? map is just a simple function for making linear scaling I wrote. Arduino map uses long values and dMap doubles.

Anyway in principle you 0-1023 maps finally to your temperature values -20 - 150 C. You can also use direct mapping, if you know that it is right: tempK=dMap(analogRead(coolantTempPin),0,1023,253.15,423.15); This is naturally fastest way to calculate it, since you do mapping only once. But now, if your reference changes e.g. by providing more accurate external 2.5V reference, you have to remember that then 0-1023 values are within 0 - 2.5 V, which means that 1023 does not map to 423.15 K anymore. So if you know your sensor mapping in voltages and you make it as commonly usable function, you need two mapping.

...
const double VRef=3.3;
const double AnalogMax=1023;
...
double ReadAnalogVoltage(int pin) {
  return dMap(analogRead(pin),0,AnalogMax,0,VRef);
}
...
double SensorMxyzToKelvin(double Vin) {
  return dMap(Vin,0,3.3,253.15,423.15);
}
...
double ReadTemp(coolantTempPin) {
  return SensorMxyzToKelvin(ReadAnalogVoltage());
}
...

This makes your code a bit more abstract, understantable and movable, but also unfortunately also slower depending of you processor. Teensy works rather well with double, but Mega lags much.

There is no standards, since sensors has different output. But the mapping range depends of sensor and you may find it from the specifig sensor data sheets.