SignalK becomes more and more popular to integrate and visualise data from different sources.
This repository shows how to build a simple NMEA2000 to SignalK gateway using an ESP32 and only a few more elements (CAN bus transceiver, DC converter).
There are three different ways shown to implement a NMEA2000 to SignalK gateway:
- A WLAN gateway for specific PGNs
- A WLAN gateway for all PGNs (Yacht Devices format via UDP)
- An USB-Serial gateway for all PGNs (Actisense format)
For all implementations the same hardware is used. The following schematics shows the required components and connections.
The PCB from the WLAN gateway can be used for the gateway. Just ignore the not needed parts.
The board can be ordered at Aisler.net: https://aisler.net/p/DNXXRLFU
!!! Be careful with placing the the ESP32 on the PCB. The USB connector has to be on the right side !!!
For unknown reasons, many CAN bus transceivers for the ESP32 have a 120 Ohm resistor built into them. The resistor does not belong to the devices at the ends of the stub lines, but to the ends of the backbone cable.
Whether the transceiver contains a 120 ohm resistor can be determined either by looking at the circuit diagram or by measuring with the multimeter.
A knife tip is suitable for removing the SMD resistor. Use it to scratch or pry off the resistance. With the transceiver shown here, place the tip of the knife in front of the resistor (between the chip and the resistor) and support the knife against the chip. Then lever the tip against the resistance and use it to scratch / loosen / break the resistance. Whichever happens first.
It then looks like the picture. Then measure to be on the safe side. Without a 120 ohm resistor, the multimeter shows approx. 75 kOhm.
With this implementation you do have the full control about how NMEA2000 PGNs are interpreted and what "path" information is used to forward it to SignalK. The connection between the ESP32 and the SignalK server is wireless with WLAN.
The software is based on the ESP8266 library for SignalK (EspSigK). But it was necessary to change the software to use it on an ESP32 with up-to-date libraries (ArduinoJson, ESP32SSDP, WebSockets).
And I had to add also a String-Method for "EspSigK::addDeltaValue()" and "EspSigK::sendDelta()". Without the extension, it was not possible to send a position.
To use the gateway, the following libraries have to be installed:
- NMEA2000 (via ZIP-File)
- NMEA2000_esp32 (via ZIP-File)
- ESP32SSDP (via ZIP-File)
- WebSockets (fom Markus Sattler, via Library Manager)
- ArduinoJson (via Library Manager).
In the main programm, you have to change the WLAN information to allow the ESP32 to connect to you WLAN network.
const String hostname = "NMEA2000-Gateway"; //Hostname for network discovery
const String ssid = "ssid"; //SSID to connect to
const String ssidPass = "password"; // Password for wifi
In setup() you can also define details regarding your local SignalK gateway:
sigK.setPrintDebugSerial(true); // Default false, causes debug messages to be printed to Serial (connecting etc)
sigK.setPrintDeltaSerial(false); // Default false, prints deltas to Serial.
//sigK.setServerHost("192.168.0.20"); // Optional. Sets the ip of the SignalKServer to connect to. If not set we try to discover server with mDNS
//sigK.setServerPort(80); // If manually setting host, this sets the port for the signalK Server (default 80);
//sigK.setServerToken("secret"); // if you have security enabled in node server, it wont accept deltas unles you auth
// add a user via the admin console, and then run the "signalk-generate-token" script
// included with signalk to generate the string. (or disable security)
sigK.begin(); // Start everything. Connect to wifi, setup services, etc...
Server discovery via MDNS is default. If the ESP32 can't find the SignalK server, you can set the hostname and port of the server.
If you do have security enabled on your SignalK server, you have to use "sigK.setServerToken("secret")" with the correct value generated on the gateway.
The gateway has many predefined conversions from NMEA2000 to SignalK. Feel free to add more.
Information regarding the different "path" information for SignalK conversion can be found here.
The following PGNs are currently supported:
// Set the information for other bus devices, which messages we support
const unsigned long ReceiveMessages[] PROGMEM = {/*126992L,*/ // System time
127250L, // Heading
128259L, // Boat speed
128267L, // Depth
129025L, // Position
129026L, // COG and SOG
129029L, // GNSS
130306L, // Wind
128275L, // Log
130310L, // Water temperature
127245L, // Rudder
0
};
It is easy to add other PGNs as required.
You can also connect sensors (I2C, 1-Wire) to the ESP32. Then it is also possible to send sensor data to the SignalK server. See Examples of the EspSigK library for details on how to send.
Alternatively you can follow the tutorial part of the NMEA2000 tutorial regarding SignalK (currently only available in German language, but you can use Google translator).
This picture shows the data in te SignalK "Instrumentpanel WebApp" window.
The second implementation shows how to build a gateway that sends all PGNs from NMEA2000 via WLAN to a SignalK server. The format is Yacht Devices format via UDP. TCP is also possible, but I recognised re-connect problems (restart of SignalK server necessary). But UDP is working fine.
For this solution, only these libraries have to be installed:
in the Programm you have to set the details for your WLAN and also for the SignalK server.
const char* hostname = "NMEA2000-Gateway"; // Hostname for network discovery
const char* ssid = "ssid"; // SSID to connect to
const char* ssidPass = "password"; // Password for wifi
// UPD broadcast to SignalK server
const char * udpAddress = "192.168.0.20"; // UDP broadcast address. Should be the SignalK server
const int udpPort = 4444; // YD UDP port
With "192.168.0.20" it will send UDP packets only to the gateway IP. Broadcast to all is possible with "192.168.0.255". But you have to adjust to your network address anyway in both cases.
With a broadcast you can also use many apps on tablets directly with NMEA2000 (e.g. NMEAremote from Zapfware). That is working even without a SignalK server!
With this solution, you will get directly all NMEA2000 PGNs in the SignalK server (or the tablet).
For SignalK you have to define a new Data Connection in the SignalK server:
That's all.
Many thanks to the Canboatjs team for the CanId calculation. That was very helpful for my implementation.
If you prefer a cable connection between NMEA2000 bus and the SignalK server, you can use the same hardware together with the sketch ActisenseListenerSender-ESP32.ino.
Due to the fact that power is supplied through USB, you do not need the additional DC converter.
For this implementation, only these libraries have to be installed:
With this solution, you will get directly all NMEA2000 PGNs in the SignalK server. You have to define a new data connection within the server.
As COM port you have to select the COM port of the ESP32.
That's all.
- 12.02.21 Version 1.0: Initial version.