NMEA2000_CAN.h Patch for newer ESP32xx devices
red8o opened this issue · comments
I had a problem with newer ESP32xx MCUs, as they apparently are not compatible with the included ESP32 code for the internal ESP32xx CAN interface. (Now named "TWAI" by Esperssif.)
Luckily this has already been circumvented by jiauka, see https://github.com/jiauka/NMEA2000_esp32xx .
The esp32xx library seems to work flawlessly on my ESP32-C3.
In order to use the standard NMEA2000_CAN.h, I have modified the file like this, from line 267 onwards:
#elif USE_N2K_CAN == USE_N2K_ESP32_CAN
#if defined( CONFIG_IDF_TARGET_ESP32C3 ) || defined( CONFIG_IDF_TARGET_ESP32S2 ) || defined( CONFIG_IDF_TARGET_ESP32S3 )
#include <NMEA2000_esp32xx.h> // https://github.com/jiauka/NMEA2000_esp32xx
tNMEA2000 &NMEA2000=*(new tNMEA2000_esp32xx());
#else
#include <NMEA2000_esp32.h> // https://github.com/ttlappalainen/NMEA2000_esp32
tNMEA2000 &NMEA2000=*(new tNMEA2000_esp32());
#endif
#else //
I am not sure if CONFIG_IDF_TARGET_... is the best way to do it, but it seems do it for me. Maybe this can be improved.
NMEA2000_esp32xx should work with all ESP32 versions. NMEA2000_esp32 is tested and certified by companies using it. NMEA2000_esp32xx has not yet been used by any company and I have not had time to test it. There has been several other cases like "seems to work flawlessly", but finds out in heavy tests that they does not.
I set up with NMEA2000_esp32xx on an Arduino Nano ESP32. This is the Nora S3 version of the ESP32. It compiles OK. I have followed the instructions to test on the serial bus only (leaving CAN for the next step) in the TemperatureMonitor example. Specifically, I
Uncommented:
Serial.begin(115200);
NMEA2000.SetForwardStream(&Serial);
Commented out:
// NMEA2000.EnableForward(false);
It seems to run without hanging. However, I do not get any messages on the Actisense Reader - just a repeated " Get Operating Mode Timeout 500ms". message.
For serial readout, I get unreadable output in the serial monitor. I then uncommented:
NMEA2000.SetForwardType(tNMEA2000::fwdt_Text);
This showed, in the Serial Monitor window (with Actisense disconnected):
14:26:12.917 -> 13211 : Pri:5 PGN:130310 Source:22 Dest:255 Len:8 Data:1,C1,70,FF,FF,FF,FF,FF
for about 15 seconds (running at 9,600 baud) and then switched to alternating lines of:
14:26:12.917 -> 13211 : Pri:5 PGN:130310 Source:22 Dest:255 Len:8 Data:1,C1,70,FF,FF,FF,FF,FF
14:26:13.412 -> PGN 130312 send failed
14:26:13.412 -> 13691 : Pri:5 PGN:130312 Source:22 Dest:255 Len:8 Data:1,1,4,7D,73,FF,FF,FF
14:26:13.412 -> PGN 130311 send failed
14:26:13.412 -> 13701 : Pri:5 PGN:130311 Source:22 Dest:255 Len:8 Data:1,C4,7D,73,FF,7F,FF,FF
14:26:13.412 -> PGN 130310 send failed
I am intensely studying the code but any hints would be appreciated.
Thanks
Sorry, the repeating 3 lines in the serial monitor prior to the "send failed" messages are:
14:33:23.309 -> 2201 : Pri:5 PGN:130311 Source:22 Dest:255 Len:8 Data:1,C4,7D,73,FF,7F,FF,FF
14:33:23.309 -> 2211 : Pri:5 PGN:130310 Source:22 Dest:255 Len:8 Data:1,C1,70,FF,FF,FF,FF,FF
14:33:23.818 -> 2701 : Pri:5 PGN:130311 Source:22 Dest:255 Len:8 Data:1,C4,7D,73,FF,7F,FF,FF
14:33:23.818 -> 2711 : Pri:5 PGN:130310 Source:22 Dest:255 Len:8 Data:1,C1,70,FF,FF,FF,FF,FF
14:33:24.313 -> 3201 : Pri:5 PGN:130311 Source:22 Dest:255 Len:8 Data:1,C4,7D,73,FF,7F,FF,FF
14:33:24.313 -> 3211 : Pri:5 PGN:130310 Source:22 Dest:255 Len:8 Data:1,C1,70,FF,FF,FF,FF,FF
14:33:24.794 -> 3691 : Pri:5 PGN:130312 Source:22 Dest:255 Len:8 Data:1,1,4,7D,73,FF,FF,FF
Have you read the document https://ttlappalainen.github.io/NMEA2000/page_h_w_set_up.html chapter "Most common hardware errors"? If you get "send failed" message, CAN controller does not communicate with bus. Or have you setup can pins properly? See issue #374
Looks like you have noise on the CAN bus that prevents the controller from actually sending the packets. The controller seems to accept the packets and says "ok", but in fact the packets stay in the transmit buffer, because the controller cannot physically send them to the bus. (The controller always reads back what it (tries to) write to the bus, it's part of the protocol.) So after a few seconds the buffer fills up and that is when you get that error message. Sending packets faster may take you to that point a little sooner.
You can check using a logic analyser on the can bus. Most cheap analyzers however will not work with CAN H to CAN L but require you to measure CAN L to Ground.
Also check wiring (CAN H / CAN L and terminators on both ends).
I used a tranceiver board from aliexpress, the one that labels the last pin "VIO" on one side of the PCB and "NC" on the other. Make sure to supply this pin with 5 V, as 3.3 V seem to not be enough to drive the bus. (You can use 3.3 V on the VCC pin for the Interface to the MCU).
On my workbench, connecting all devices to the same ground seemed to help, too.
The problem may also go away if you have three or four devices on the bus - but of course that is not really a proper solution.
Thanks for the very quick responses.
I have studied the CAN issues document and will give it another read.
However, it was my understanding that, at this point in the TermperatureMonitor example (serial lines uncommented) that the CAN transceiver was not yet involved in the send/receive chain. I am in the very initial section:
"Try on PC only
Now we are ready to try sample without N2k bus connection. So you need only Arduino board and PC. No CANBUS shield or extra chips yet!"
I am using the ESP32xx alternate library with the modifications of red80 above. Yes, it does seem a buffer is filling but not being emptied. Can this occur at the point I am in the code testing? Is it possible this is an issue with Actisense Reader not pulling data from the (simulated) COM port?
Again, thanks very much for the assistance.
If you test CAN controller without connecting it to bus, you have that issue. You must have bus with termination resistors and at least one working device. If you do not have proper bus connection, buffer will not empty, since controller fails to send any data to the bus. Easiest is to make one device with e.g., TemperatureMonitor and other with DataDisplay2 or DeviceAnalyzer. Or use ActisenseListenerSender and my NMEASimulator.
You can test device without CAN bus by setting library to debug mode, but there is not much use with it. Either I have tested debug mode for several years.
Thanks very much. I thought I could start with Actisense Listener on the PC and then move to CAN H/W.
Apparently not. I thought I might be experiencing issues due to the ESP32S3 and use of the ESPxx code.
I'll set up the N2K network and give that a try.
Thanks again for your assistance.
Working! I abandoned trying to use the Actisense Reader for debugging. I added a 3.3V CAN driver to the Arduino Nano ESP32 and added the ESP32xx "fix" for the S3 version of the ESP32 (along with red80's code additions). Simple Temperature example is displaying on a Garmin on my bench setup. Good progress. Thanks for all the assistance!