September 9, 2019  New functions and disassembler in the Bridge

Better understanding of your code allows development of real-time and complex CAN processing applications using a built-in programming language.

Disassembler of the NMEA 2000 Bridge

The NMEA 2000 Bridge is the only product with a built-in programming language to process CAN messages. You can load the program's text from a MicroSD card, and get a log of the program execution or compilation errors in the output files. This allows editing and tuning of your programs while on board; you only need a device with a MicroSD card reader and text editor.

With the Bridge, it is possible to "remove" wrong data or filter out unnecessary messages with 2-3 lines of code, or change CAN messages on the fly (see example 1), or run much more complicated programs (trigonometry example, digital switching example).

The Bridge also protects your software from unauthorized access or coping. Even though it has special support for NMEA 2000 (like pre-assembling of fast messages), it can be used with different CAN networks (for example, J1939) running on speeds from 50 kbps to 1 Mbps. Both 11-bit and 29-bit CAN identifiers are supported.

The user's code is compiled to byte code and then executed in a virtual machine. Usually you do not need to know "assembler", but many users like to know what is under the hood. Just add DECOMPILER=1 to your program (the program below does nothing, it's just an example):


	A = 1
	B = 2
	if (A > 0)
		B = B+A*3
		B = 0
	while (B > 0)

	B = B-1

And you will get YDNBSAVE.CFG where every line of your code is accompanied by disassembled byte code:

# Current configuration of Yacht Devices NMEA 2000 Bridge
# Firmware: 1.32 27/08/2019                 
# Serial: 00000000, Password level: 0


    # 0000:  PUSH 04 01 00 00 00 
    # 0006:  POPV 00 
    # 0008:  PUSH 04 02 00 00 00 
    # 000E:  POPV 01 
    # 0010: PUSHV 00 
    # 0012:  PUSH 04 00 00 00 00 
    # 0018: GREAT 
    if (a > 0) {
        # 0019:  JMPF 12 
        # 001B: PUSHV 01 
        # 001D: PUSHV 00 
        # 001F:  PUSH 04 03 00 00 00 
        # 0025:   MUL 
        # 0026:   ADD 
        b=(b + (a * 3))
        # 0027:  POPV 01 
        # 0029:   JMP 0A 
    else {
        # 002B:  PUSH 04 00 00 00 00 
        # 0031:  POPV 01 
    # 0033:   NOP 
    # 0034: PUSHV 01 
    # 0036:  PUSH 04 00 00 00 00 
    # 003C: GREAT 
    while (b > 0) {
        # 003D:  JMPF 06 
        # 003F:  CALL 
        # 0040:  JMPL F4 FF 

    # 0000: PUSHV 01 
    # 0002:  PUSH 04 01 00 00 00 
    # 0008:   SUB 
    b=(b - 1)
    # 0009:  POPV 01 


The PUSH command puts the number to the top of the stack. The first byte after the PUSH is the type of number (int8 — 0, unsigned int8 — 1, int16 — 2, unsigned int16 — 3, int32 — 4, unsigned int32 — 5, float — 6). The POPV (yes, with "V" suffix) takes the number from the top of the stack and saves it to a specified variable (A — 0, B — 1, and so on). The PUSHV command saves the variable to the stack.

The GREAT command compares two numbers on the top of the stack and sets the flag in the "flag register" of virtual machine. JMPF (jump false) makes forward short jump (a specified number of bytes) if the flag is not set. JMP performs an unconditional forward short jump (JMP 0 is the dead loop).

The similar commands JMPFL and JMPL (long jumps) take a two-byte signed argument, and can perform forward and backward jumps (used in the while() statement).

Our virtual machine is very simple, and we are sure you will be able to read other "assembler" text easily. It has no other registers except flags, and all operations are performed with data on the top of the stack.

The size of one subprogram (inside init(), heartbeat(), match() or func()) is limited to 16 KB. The whole program size is also limited to 16 KB. In other words, you can have one big match() which consumes all available ROM. With disassembler, you find out the size of your bytecode, the 4-digit hexadecimal number before the command in disassembled text is the address of the command inside the subprogram.

If you already familiar with Bridge programming, you may be surprised by call() and func() keywords. The func() is a new keyword where you can place some subprogram and call it with the call().

The recursion ( call() inside func() ) is also allowed, but the depth is limited to 10. If logging is turned on (see "max-recursion" folder), you may get the following line in the file:

    02:57.345 !! FUNC Maximum recursion depth (10) is reached

The while() can also make a dead loop, and we limited the time of subprogram execution to 3 seconds (see "max-execution" folder). Most of the Bridge's programs have only few lines of code and are executed in less than half of a millisecond. And usually you do not have to worry about execution time.

The Bridge's MCU runs at 20 MHz. We can calculate that the performance of the virtual machine (the heartbeat() in this example will be called by the Bridge every 1000 ms):

# Current configuration of Yacht Devices NMEA 2000 Bridge
# Firmware: 1.32 27/08/2019                 
# Serial: 00000000, Password level: 0


    # 0000: TIMER 
    # 0001:  POPV 13 
    # 0003:  PUSH 04 00 00 00 00 
    # 0009:  POPV 01 
    # 000B: PUSHV 01 
    # 000D:  PUSH 04 E8 03 00 00 
    # 0013:  LESS 
    while (b < 1000) {
        # 0014:  JMPF 10 
        # 0016: PUSHV 01 
        # 0018:  PUSH 04 01 00 00 00 
        # 001E:   ADD 
        b=(b + 1)
        # 001F:  POPV 01 
        # 0021:  JMPL EA FF 
    # 0024: PUSHV 13 
    # 0026: TDIFF 
    # 0027:   LOG 


In the log we find that execution of 9006 commands by the virtual machine (9*1000+6) takes 102 ms (0x66) or about 10 microseconds per command:

    00:02.112 LG HEARTBEAT, UINT32 0x00000066
    00:03.222 LG HEARTBEAT, UINT32 0x00000066
    00:04.325 LG HEARTBEAT, UINT32 0x00000066
    00:05.428 LG HEARTBEAT, UINT32 0x00000066

The smallest interval of NMEA 2000 messages in the Standard (for example, wind sensor messages) is 100 milliseconds and even a big handler with 100 commands of virtual machine or 30 lines of source code will have a processing time of about 1 ms.

Of course, trigonometry functions may have a bigger execution time. We calculated wind message handler execution time from this example. It has 85 lines of code (or 55 lines of clear code without comments and empty lines) which are compiled to 492 bytes or 205 commands of virtual machine.

The initial result was 8ms, but most of time was consumed by logging. When the send() function is called (two times in this handler) and the text log is on, the Bridge saves a copy of the sent message to the log on MicroSD card. And, of course, this time counts! When we commented the send() calls, the execution time shrank to only 3 milliseconds. This is about 15 microseconds per command on average, but we are using sqrt(), acos() and floating point math.

To learn more about performance of the Bridge and optimization of your code, see Chapter IX of the Manual.

The firmware update 1.32 for the NMEA 2000 Bridge is available on the Downloads page.

Permanent link...



 August 23, 2019  August updates

Must-have updates for all our Wi-Fi products, USB Gateway and NMEA 0183 Gateway. Gensets support in J1939 Engine Gateway YDEG-04.

New tracks naming for GPX export

Figure 1. New tracks naming for GPX export

The most important feature for Wi-Fi products is the updated TCP/IP stack. We fixed many things and TCP protocol now works much faster. In all products, we fixed two bugs related to AIS conversion and bearings calculation, and we strongly recommend updating of all of your Wi-Fi products, the USB Gateway and the NMEA 0183 Gateway.

We have a huge wish list of additions for Web Gauges, but they got only keyboard short cuts: you can change the color scheme, switch between pages and open settings with B,1,2,3,4 and S keys.

The NMEA 0183 Wi-Fi Gateway and NMEA 0183 Wi-Fi Router had their export of GPX and CSV improved: you can skip tracks with small number of points, and track names contain the date of the track and the number of points (see Figure 1).

Data with Yacht Devices XML schema uploaded to ChartedSails.Com

Figure 2. Data with Yacht Devices XML schema uploaded to ChartedSails.Com

Each GPS point in CSV or GPX has basic set of additional data: COG, SOG, AWA, AWS, TWA, TWS, heading, STW, and depth. In addition to GPX and Garmin XML schemas, we added a Yacht Devices XML schema. This allows to export your data to ChartedSails.Com and see your tracks along with additional data at the same time on one screen (in Google Earth you need to click on the point to see additional data). This web service is free and works very fast, it can easily handle very long tracks.

We are also adding this feature to the NMEA 2000 Wi-Fi Router YDNR-02.It will allow you to select which data you wish to record in addition to the basic set. We prepared sets for racing yachts (with rudder angle, heeling, etc.), single engine and twin engine boats, and for charter companies (groundings, engine alarms, etc.). This update will be released in September along with XML schema documentation.

The NMEA 0183 Gateway can now parse custom XDR sentences with temperature, pressure and humidity data:

    XDR_IN_TEMPERATURE=SM010A,C,14  # In Celsius
    XDR_IN_PRESSURE=Air,P,0 # In Pascal (P) or Bar (B)
    XDR_IN_HUMIDITY=Air,P,1 # In percent

The first two parameters are names of the sensor and units (all NMEA 0183 units supported). The third parameter is the NMEA 2000 data type (you can find numbers in FAQ).

We added this feature in response to a customer request to add support of Silicon Marine SM010 Exhaust Gas Temperature Sensor (btw, we have our own NMEA 2000 Exhaust Gas Sensor). But when we added support, we found that they send data without a talker ID:


We added a hack: tunnel setting (TUNNEL=ON) allows processing of sentences not only without a valid checksum, but without a talker ID, too.

The NMEA 0183 Gateway can supply NMEA 0183 with 12 Hz heading, and we added a fast heading for NMEA 2000 (20 Hz instead of 10 Hz) in this version. Fast headings can be turned on in the settings:


Firmware 1.32 for the Engine Gateway was released in July, but it has new features, which had not yet been announced and were not described in the documentation.

We added support of gensets (it can be turned on with GENSET=ON). This turns on processing of J1939 PGN 65030 (Generator Average Basic AC Quantities; SPN 2444, 2436, 2448), PGN 65029 (Generator Total AC Power; SPN 2452), PGN 65028 (Generator Total AC Reactive Power; SPN 2464, 2456) and output of NMEA 2000 PGN 127504 (AC Output Status).

We also added a setting to request specified PGNs every second from all engines with addressed requests:


This can be used with engines and gensets which report engine hours (PGN 65253), software version (PGN 65242) or serial numbers (PGN 65260) by request only.

Web pages of all products got galleries with high-quality photos (example). The Media Kit was totally updated, we asking all dealers to update their listings.

All updates are available on the Downloads page. We strongly recommend updating all the products mentioned and will be very thankful for feedback on the new Engine Gateway features.

Permanent link...



 August 9, 2019  All hands on deck!

The new firmware for the Alarm Button allows uploading of user sound files. You can replace four of the 28 sounds with your own recordings.

Uploading of audio files to Alarm Button

Figure 1. Uploading of audio files

To replace built-in sounds with your own recordings, you need to download the CAN Log Viewer 1.30 (works on Windows, Linux and OS X) and update the firmware of the Alarm Button to Version 1.02. In the list of NMEA 2000 devices, select the Alarm Button and click "Properties". Then click the "More..." button in the new window and the "Sound Uploader" window will be opened.

You can replace the built-in sounds with numbers 25-28; the other sounds (1-24) cannot be replaced. If you need to replace the sound of event 1, you can upload your recording to slot 25 and run the below command in the "Installation description 2" field:


To replace the sound, select the slot number, select the audio file, and click the "Upload file" button.

You can also adjust the "Start delay" and "Replay delay" parameters (from 0.1 to 600 seconds with 0.1 second intervals) with the "Update delays" button. For example, if you need a 1-second tone signal with 9-second intervals, you don't need to generate silence intervals, you can upload the tone signal and set the replay delay for 9 seconds.

Note that sounds cannot be restored with the YD:RESET command, but the archive with the firmware contains the "SOUND" subfolder where copies of original files are saved. The two last digits in the file name are the factory start delay and replay delay settings.

The CAN Log Viewer allows uploading mono 16-bit PCM WAV files with frequency of 22050 Hz, and length from 0.1 to 13 seconds (from 4 to 688 KB). Yes, the slot size is limited and you will not able to upload your favorite MP3 with a song. But 13 seconds is enough for a long phrase.

We recommend the free Audacity program (works on Windows, OS X and Linux) to prepare audio files. It allows clipping of files, adjusting the volume (Effect \ Amplify...) and saving in various formats. The correct settings for the Alarm Button are shown in Figure 2 (pay attention to the two red boxes).

How to save audio file for Alarm Button in Audacity

Figure 2. How to save audio file in Audacity

This convenient program also allows generation of tone signals (Generate \ Tone...), so you can choose the most annoying frequency to drive yourself away from the cabin.

In addition, you will find voice recordings of "Man Over Board" and "All hands on deck!" phrases in the "VOICE" folder of the firmware package. They are ready for uploading to Alarm Button and sounds great! We will be glad to receive your audio recordings (without copyright restrictions) to share with other visitors.

The firmware 1.02 update for the Alarm Button with sound files inside the archive is available on the Downloads page.

Permanent link...


Next articles:

All news...