Go Down

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


i was chasing accuracy in fuel tank measurement (I have 2 large tanks that are coupled together)
with only one sender... and a few % is a LOT of litres in my case :)
however i quickly realised that the resistive sender unit appears to have quantisation (it doesnt appear to be
a continuous resistance?) .. so given all the errors (inc those mentioned by timo)
and also the effect of boat movement etc ... i realised that a 20 step readout
(ie showing fuel level in 5% increments was the best i could expect ... and realistically
the overall accuracy is probably worse than 5%)

remember that the additional voltage divider you add (is not across the 650ohm ... its across the
voltage output from the sender unit (the lower leg of the voltage divider formed by sender unit( 0-180)
It depends on what type of fuel level sens it is. The "old good" once where linear 100% resistive sensors. The newer type today is some kind of a pipe with metal or magnetic sensitive switches in series inside. In my case, I have 8 switching points where resistance is added or subtracted depending on position.

With 650 ohms the hole circuit is meant. If I go out from the 180 ohms of the sensor now the additional voltage divider in parallel do not affect the shown value of the gauge at all (180 ohms sensor to 33.1 KOhms voltage divider). If I calculated right this is an error in microAmp. Sensor and gauge together while the sensor have in 180-ohm max. This is values from the datasheet of the gauges/fabricant (Faria Beede).

The movement of the boat has to be compensated by smoothing the measurements.
But there are also other sensors for fuel available, "radar" based once. They are very expensive but deliver a more linear result. But I do not think this is worth the money.

I guess using the digital solution now is much more accurate than the gauges ever have been.



I thought to use the RTC of the Teensy 3.5 to count the Engine running seconds and save them to sd. I know there are a ton of threads regarding counting engine running hours, but this all looks so complicated.

As trigger to set the start point I thought to use the rpm (if >=300). How to save the elapsed seconds to sd or EEPROM I have figured out.

Another option I thought can be to use millis to count the seconds and save them to SD every 5 minutes by reading the last saved seconds and add them to the counted seconds and write it back to file.
5 minutes instead of 15 minutes interval I think makes sense since if the power is lost due to the stopped engine I lose too many minutes and the counted time gets to inaccurate.

I use the Teensy 3.5 for all the engine rapid and engine dynamic data (not tested yet live)
I am not sure how the writing to card process will affect the rest of the program. I hope it does not stop the whole process until save to sd is finished?

Any better Idea, does this makes sense?


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.
Code: [Select]
struct tNvRamData {
   uint32_t EngineRunTime;  // Seconds

#define NVRAM_BASE 0x4003E000

tNvRamData *pNvRamData=(tNvRamData *)(NVRAM_BASE);

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?


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.



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.


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

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.

Go Up