Bridge between Wifi and CAN.
With the commit from September 2024, the CAN baud rate was changed to 105kBaud, with the goal to support DXBUS (More details here: https://github.com/uhi22/invacare-g50-investigations). This breaks the use cases, which require 500kBaud. It is not yet clarified whether setting the baud rate in SavvyCAN actually works. This needs further investigations. There is no clean solution at the moment, because custom baud rates are not supported in SavvyCAN (collin80/SavvyCAN#469 , collin80/SavvyCAN#654, https://savvycan.com/index.php/forum/welcome-mat/207-custom-speeds).
So the conclusion is:
- To use 500kBaud, take the version from April 2024 (https://github.com/uhi22/wifican/tree/0a0cf46a09e730d81c4dcf6dd06660cd7e77c16b)
- To use other custom baud rates, have a look to the commit https://github.com/uhi22/wifican/commit/1e717946a06a594cf2e79b092cbaf7b376e8bb55 to see at which places you need to adapt something. It is not clarified, which places are really effective and which maybe could be removed.
- If you like investigating, you could find out how the baud rate setting could be improved in SavvyCAN and wifican.
Wifican used by forum members, and description on the openinverter wiki available.
Receive path runs much more stable with the own TWAI FIFO driver. Transmit path not yet implemented.
SavvyCAN is a great open-source CAN tool, and the ESP32RET is assumingly a pretty good interface between the PC and multiple CANs. However, the try to use ESP32RET to create a simple single-channel-CAN interface using a good old ESP32 dev kit and adding a CAN transceiver, was not successful.
The good old ESP32 board had the following issues:
- 1 MBit for the serial-USB did not work. It showed a lot of scrambled data, sometimes something senseful in between. Changing to 115k solved this, but is no real solution.
- Connecting to an existing Wifi network failed for unknown reason. The same hardware and same credentials work fine with a very old Arduino ESP32 installation, but not with the latest (Arduino 2.2.1, latest ESP32 arduino environment, 2023-10-03).
- Using a more up-to-date ESP32s3 board reveals incompatibilites:
- The ESP32s3 does not support classic bluetooth, only BT low energy. This is not compatible with the ELM327 emulation, at least not out-of-the box.
- The ESP32_CAN driver hangs endless loop in a high-prio CAN driver task, maybe due to changes in the scheduling concept of the espressif twai driver.
Even when switching to the ESP32s3, there are stability issues with the original espressif TWAI driver, see doc/crashlog.md .
Out of this situation, the plan is create a minimal single channel device, which is a bridge between Wifi and CAN, and is still compatible to SavvyCAN.
The better way would be to add fixes to the ESP32RET and the espressif TWAI driver, but for experimentation the following approach was chosen:
- Instead of using the Libs which ESP32RET uses, copy the content directly into the project folder. This makes it easy to modify and develop, and to keep a consistent state.
- Single CAN channel: use the built-in TWAI of the ESP. No SPI, no MCP..., no FD support.
- One hard-coded configuration of the board. No EEPROM parameters.
- The only configuration option is the selection between Wifi-AP and Wifi-Station. The selection is done by a switch on a digital input.
- Kicked-out bluetooth completely.
- Kicked-out serial GVRET completely.
- Kicked-out the espressif TWAI driver (which has stability issue in the queue handling), and created a simple FIFO based receive path.
So we end-up with the following features for the moment:
- Single CAN channel. Configured to 500kBaud.
- Wifi connection to an existing wifi network (configured in the wifi_credentials.h file) or providing an access point.
- Connection between PC and wifican runs over wifi, using GVRET over wifi, which is in fact a telnet TCP connection.
- The usb-serial-port is used just for debugging. No serial GVRET support.
- Install the Arduino IDE and the ESP32s3 board support.
- Solder a 3.3V CAN transceiver board to the ESP32s3 board. This needs just four wires: 3.3V, ground, CAN_RX (pin 4), CAN_TX (pin 5).
- Connect a switch, which connects the pin35 either to ground or to pin 47.
- Connect the ESP32s3 board at the "COM" USB (not the "USB"-USB) to the PC.
- Rename the wifi_credentials_template.h to wifi_credentials.h, and enter your wifi credentials there.
- Build and download the project in the Arduino IDE.
- Open SavvyCAN, choose menu -> connection -> open connection window.
- Choose "Add new device connection", and "Network connection (GVRET)". In the IP address field there should automatically appear the IP of the wifican device. If not, check whether the wifican device and your PC are in the same Wifi network, or thy entering the IP manually.
- The wifican should now be visible in the connection list, with status "Connected".
- In the connection window, set the bus speed and check the "Enable bus" checkbox.
- Connect the CANH and CANL to your CAN network. The SavvyCAN should show the incoming traffic.
- SavvyCAN -> Menu -> SendFrames -> Custom allows you to transmit frames.
(Collecting the experiences from https://openinverter.org/forum/viewtopic.php?p=69766#p69766 and https://openinverter.org/forum/viewtopic.php?p=69881#p69881 and https://openinverter.org/wiki/Getting_started_with_CAN_bus)
- Install the Arduino IDE (e.g. version 2.2.1) and the ESP32s3 board support.
- Solder a 3.3V CAN transceiver board to the ESP32s3 board. This needs just four wires: 3.3V, ground, CAN_RX (pin 4), CAN_TX (pin 5). Attention: There are cheap CAN transceiver boards on Aliexpress which do not work, and also wrongly labeled CAN transceiver chips. It makes sense to obtain the transceiver from a reliable source.
- Connect a switch, which connects the pin35 either to ground or to pin 47. (See chapter wifi modes below)
- Create a new folder C:\Sketchfolder
- Open in a browser https://github.com/uhi22/wifican
- Green Button "Code", choose "Download zip". This creates a wifican-main.zip in the downloads folder.
- Copy this zip into C:\Sketchfolder
- Unzip, and arrange the folders in the way that you have the folder C:\Sketchfolder\wifican, and in this is the wifican.ino. This is because the Arduino IDE takes the folder name as name of the sketch, and the main ino file needs to have the same name.
- Start the Arduino IDE. In my case it is Arduino IDE 2.2.1.
- File -> Open..., navigate to C:\Sketchfolder\wifican\wifican.ino. This should directly show all files, with the wifican.ino as most left, because it is the main file.
- Choose the board "ESP32S3 Dev Module"
- Rename the wifi_credentials_template.h to wifi_credentials.h, and enter the credentials of your home wifi there.
- Make sure that your home wifi is a 2.4GHz wifi. The ESP does not work with 5GHz wifi.
- Press the upload button. This takes some minutes to compile, and afterwards it will upload the code to the ESP.
- In the Arduino IDE, open the serial monitor. Configure it to 115200 Baud.
- Connect pin35 to 3.3V (which are also provided by pin 47). This selects the "home mode".
- On the ESP, press shortly the reset button.
- In the Arduino IDE, observe the serial monitor. It should show something like this
wifiMode1
andWifiMode is 'station'. Connecting to myHomeWifi"
andWiFi connected
andtelnet is listening
- Open SavvyCAN, choose menu -> connection -> open connection window.
- Choose "Add new device connection", and "Network connection (GVRET)". In the IP address field there should automatically appear the IP of the wifican device. If not, check whether the wifican device and your PC are in the same Wifi network.
- The wifican should now be visible in the connection list, with status "Connected".
- In the connection window, set the bus speed and check the "Enable bus" checkbox.
- Connect the CANH and CANL to your CAN network. The SavvyCAN should show the incoming traffic.
- SavvyCAN -> Menu -> SendFrames -> Custom allows you to transmit frames.
The wifican supports two different modes of wifi operation. The mode is selected by the level of pin35 during startup.
In the source code called WIFI_MODE_STATION. This mode is reached when during the boot the pin35 is high (3.3V). The wifican tries to connect to your home wifi. You configured the name of your wifi and the password in wifi_credentials.h. The wifican will be in your home network, so you can use SavvyCAN to observe the CAN while you are in parallel browsing the internet or sending mails.
In the source code called WIFI_MODE_ACCESS_POINT. This mode is reached if during boot the pin35 is grounded. The wifican will create its own wifi network, called "wifican" and with the password "topsecret", configurable here:
Line 15 in 44dbb5f
The wifican privides some debug data as "virtual" CAN messages. For debugging your setup, you could add the data base file (dbc) of the "virtual" debug messages into SavvyCAN. This file is here: https://github.com/uhi22/wifican/blob/m ... opment.dbc This allows you to see how long the wifican is running (wificanAliveCounter is counting up), and how many messages it has seen on CAN (wificanTotalRxMessages)
- CANManager::sendFrame
- CAN_COMMON.sendFrame(...)
- ESP32CAN::sendFrame(CAN_FRAME& txFrame)
- twai_transmit()
The states and transitions of the ESP32S3 CAN driver are described here: https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/twai.html
- During startup, the task task_LowLevelRX is started.
- The task_LowLevelRX suspends in twai_receive().
- If data is available, the task_LowLevelRX resumes and calls processFrame().
- ESP32CAN::processFrame() filters and distributes the data, using xQueueSend(callbackQueue, ...)
- The task_CAN reads the messages from the queue: xQueueReceive(callbackQueue, ...) and calls the ESP32CAN::sendCallback.
- The ESP32CAN::sendCallback either calls
- one of the listeners (gotFrame()) (but CANListener::gotFrame() is an empty function) or
- a mailbox callback (cbCANFrame) or
- a general callback (cbGeneral)
...
- CANManager::loop
- canBuses[i]->available()
- canBuses[i]->read(incoming)
- CANManager::displayFrame --> wifiGVRET.sendFrameToBuffer(frame, whichBus)
attachCANInterrupt() --> CAN_COMMON::setGeneralCallback() sets the cbGeneral. canBuses[i]->watchFor() --> setRXFilter() CAN_COMMON::attachCANInterrupt() --> CAN0.setCallback() --> ...tbd...
Source code in the espressif IDE:
- C:\esp-idf-v4.4.4\components\driver\twai.c
Header and lib in the arduino IDE:
- C:\Users\uwemi\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.13\tools\sdk\esp32s3\include\driver\include\driver\twai.h
- C:\Users\uwemi\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.13\tools\sdk\esp32s3\lib\libdriver.a
Yes, the SavvyCAN sends 0xE7 as first two bytes. This turns-on the binary mode.