Skip to content

Commit

Permalink
Enable configurable hostnames and improve socketcand documentation.
Browse files Browse the repository at this point in the history
  • Loading branch information
Marcin Anforowicz committed Aug 29, 2024
1 parent 06bb96c commit 6ca0c1e
Show file tree
Hide file tree
Showing 13 changed files with 237 additions and 130 deletions.
28 changes: 20 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

This is a program that lets the [Olimex ESP32-EVB](https://www.olimex.com/Products/IoT/ESP32/ESP32-EVB/open-source-hardware)
act as a [socketcand](https://github.com/linux-can/socketcand/) adapter.
It runs a server that translates traffic between TCP socketcand clients and its CAN bus.
It runs a server on port 29536 that translates traffic between TCP socketcand clients and its CAN bus.

Clients can connect to the adapter via TCP socketcand
to communicate with the CAN bus connected to the adapter.
Expand All @@ -12,7 +12,7 @@ Client1 <---TCP Socketcand---> |---------------------------|
| esp32_socketcand_adapter |
Client2 <---TCP Socketcand---> | running on |
| Olimex ESP32-EVB |
Physical CAN bus (can0) <----> |---------------------------|
Physical CAN bus (vcan0) <---> |---------------------------|
```

Here's an image of an example setup:
Expand Down Expand Up @@ -49,7 +49,7 @@ Alternatively, you can build the project yourself.
3. Run `idf.py flash` to flash your ESP32.


## Usage
## Setup

1. On startup, your ESP32 will print its curent network settings over USB UART.
Hold button `BUT1` for 1 second to reset the settings to default.
Expand All @@ -70,12 +70,24 @@ Change network settings to your liking.

4. Connect the ESP32 to a CAN bus.

5. Use a tool such as [socketcand](https://github.com/linux-can/socketcand)
to connect to your ESP32's IP address.
The ESP32 serves socketcand over port 29536.
## Can-utils Candump Example

6. You should be able to send and receive messages to the CAN bus
connected to the ESP32.
This example lets you listen to CAN packets from the ESP32 Socketcand Adapter. This example only works on Linux.

1. Install can-utils. On Debian: `sudo apt install can-utils`.

2. Install socketcand by following the instructions in
the [socketcand](https://github.com/linux-can/socketcand) repository.

3. Create a virtual CAN device: `sudo ip link add dev vcan0 type vcan`.

4. Enable the virtual CAN device: `sudo ip link set up vcan0`.

5. In the background, start `./socketcandcl -v --server [ESP32 IP ADDRESS] -i vcan0,vcan0`. Use the IP address of your ESP32.

6. Print incoming CAN packets with `candump vcan0`.

## OpenCyphal Example

If the CAN bus has [OpenCyphal](https://opencyphal.org/) nodes on it,
you can interact with them using
Expand Down
10 changes: 5 additions & 5 deletions main/discovery_beacon.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ static void discovery_beacon_task(void* pvParameters) {

int bytes_printed = 0;
int res = snprintf(msg_buf + bytes_printed, sizeof(msg_buf) - bytes_printed,
"<CANBeacon name='ESP32-socketcand' type='adapter' "
"description='ESP32-EVB socketcand adapter'>\n");
"<CANBeacon name='esp32_socketcand_adapter' type='adapter' "
"description='socketcand running on ESP32-EVB Olimex'>\n");
bytes_printed += res;
if (res < 0 || bytes_printed >= sizeof(msg_buf)) {
ESP_LOGE(TAG, "Couldn't snprintf CAN beacon message.");
Expand All @@ -70,7 +70,7 @@ static void discovery_beacon_task(void* pvParameters) {

res =
snprintf(msg_buf + bytes_printed, sizeof(msg_buf) - bytes_printed,
"<URL>can://%d.%d.%d.%d:9999</URL>\n", IP2STR(&ip_info.ip));
"<URL>can://%d.%d.%d.%d:29536</URL>\n", IP2STR(&ip_info.ip));
bytes_printed += res;
if (res < 0 || bytes_printed >= sizeof(msg_buf)) {
ESP_LOGE(TAG, "Couldn't snprintf CAN beacon message.");
Expand All @@ -85,7 +85,7 @@ static void discovery_beacon_task(void* pvParameters) {

res =
snprintf(msg_buf + bytes_printed, sizeof(msg_buf) - bytes_printed,
"<URL>can://%d.%d.%d.%d:9999</URL>\n", IP2STR(&ip_info.ip));
"<URL>can://%d.%d.%d.%d:29536</URL>\n", IP2STR(&ip_info.ip));
bytes_printed += res;
if (res < 0 || bytes_printed >= sizeof(msg_buf)) {
ESP_LOGE(TAG, "Couldn't snprintf CAN beacon message.");
Expand All @@ -94,7 +94,7 @@ static void discovery_beacon_task(void* pvParameters) {
}

res = snprintf(msg_buf + bytes_printed, sizeof(msg_buf) - bytes_printed,
"<Bus name='can0'/>\n"
"<Bus name='vcan0'/>\n"
"</CANBeacon>\n");
bytes_printed += res;
if (res < 0 || bytes_printed >= sizeof(msg_buf)) {
Expand Down
36 changes: 25 additions & 11 deletions main/driver_setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ static void can_recovery_task(void *pvParameters);
static StackType_t can_recovery_task_stack[4096];
static StaticTask_t can_recovery_task_mem;

esp_err_t driver_setup_ethernet(const esp_netif_ip_info_t *ip_info) {
esp_err_t driver_setup_ethernet(const esp_netif_ip_info_t *ip_info,
const char *hostname) {
esp_err_t err;
// Based on:
// https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/network/esp_eth.html
Expand Down Expand Up @@ -98,6 +99,10 @@ esp_err_t driver_setup_ethernet(const esp_netif_ip_info_t *ip_info) {
return ESP_FAIL;
}

//// Set the device hostname ////
err = esp_netif_set_hostname(esp_netif, hostname);
ESP_RETURN_ON_ERROR(err, TAG, "Couldn't set ethernet hostname.");

//// Set static IP info if needed ////
if (ip_info != NULL) {
err = esp_netif_dhcpc_stop(esp_netif);
Expand Down Expand Up @@ -130,6 +135,7 @@ esp_err_t driver_setup_ethernet(const esp_netif_ip_info_t *ip_info) {

/// Wait for internet to actually work ////
if (xSemaphoreTake(internet_ready, pdMS_TO_TICKS(10000)) == pdFALSE) {
vSemaphoreDelete(internet_ready);
ESP_LOGE(TAG, "Couldn't start ethernet driver in 10 seconds.");
return ESP_FAIL;
}
Expand All @@ -140,7 +146,8 @@ esp_err_t driver_setup_ethernet(const esp_netif_ip_info_t *ip_info) {
}

esp_err_t driver_setup_wifi(const esp_netif_ip_info_t *ip_info,
const char ssid[32], const char password[64]) {
const char *hostname, const char ssid[32],
const char password[64]) {
esp_err_t err;
// Check if the ethernet driver has already been started
if (driver_setup_wifi_netif != NULL) {
Expand All @@ -155,19 +162,23 @@ esp_err_t driver_setup_wifi(const esp_netif_ip_info_t *ip_info,
return ESP_FAIL;
}

//// Set the device hostname ////
err = esp_netif_set_hostname(esp_netif, hostname);
ESP_RETURN_ON_ERROR(err, TAG, "Couldn't set Wi-Fi hostname.");

//// Set static IP info if needed ////
if (ip_info != NULL) {
err = esp_netif_dhcpc_stop(esp_netif);
ESP_RETURN_ON_ERROR(err, TAG,
"Couldn't stop WIFI dhcp to set up static IP.");
err = esp_netif_set_ip_info(esp_netif, ip_info);
ESP_RETURN_ON_ERROR(err, TAG, "Couldn't set IP info for WIFI.");
ESP_RETURN_ON_ERROR(err, TAG, "Couldn't set IP info for Wi-Fi.");
}

//// Initialize the wifi driver ////
wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT();
err = esp_wifi_init(&wifi_init_config);
ESP_RETURN_ON_ERROR(err, TAG, "Couldn't initialize WIFI");
ESP_RETURN_ON_ERROR(err, TAG, "Couldn't initialize Wi-Fi");

/// Configure the wifi driver ////
wifi_config_t wifi_config = {0};
Expand All @@ -190,17 +201,19 @@ esp_err_t driver_setup_wifi(const esp_netif_ip_info_t *ip_info,
&ip_event_handler, NULL);
ESP_RETURN_ON_ERROR(err, TAG, "Couldn't register IP handler.");

err = esp_wifi_start();
ESP_RETURN_ON_ERROR(err, TAG, "Couldn't start Wi-Fi.");

// Tell the driver to try connecting to WIFI.
// Note: This will NOT return an error if WIFI can't connect.
// All reconnection logic is instead handled by
// `wifi_recovery_task()`.
err = esp_wifi_start();
ESP_RETURN_ON_ERROR(err, TAG, "Couldn't start WIFI.");
err = esp_wifi_connect();
ESP_RETURN_ON_ERROR(err, TAG, "Couldn't connect to WIFI.");
ESP_RETURN_ON_ERROR(err, TAG, "Couldn't connect to Wi-Fi.");

//// Wait for internet to actually work ////
if (xSemaphoreTake(internet_ready, pdMS_TO_TICKS(10000)) == pdFALSE) {
vSemaphoreDelete(internet_ready);
ESP_LOGE(TAG, "Couldn't start WIFI driver in 10 seconds.");
return ESP_FAIL;
}
Expand Down Expand Up @@ -275,7 +288,8 @@ static void wifi_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data) {
switch (event_id) {
case WIFI_EVENT_STA_START:
ESP_LOGD(TAG, "WIFI station started.");
ESP_LOGD(TAG, "WIFI station started. Connecting...");
esp_wifi_connect();
xSemaphoreGive(internet_ready);
break;
case WIFI_EVENT_STA_CONNECTED:
Expand Down Expand Up @@ -312,8 +326,8 @@ static void ip_event_handler(void *arg, esp_event_base_t event_base,
static void wifi_recovery_task(void *pvParameters) {
// Constantly re-connect to Wi-Fi if needed.
while (true) {
// Check Wi-Fi status every 5 seconds
vTaskDelay(pdMS_TO_TICKS(5000));
// Check Wi-Fi status every 10 seconds
vTaskDelay(pdMS_TO_TICKS(10000));
if (!esp_netif_is_netif_up(driver_setup_wifi_netif)) {
ESP_LOGE(TAG, "Retrying connecting to Wi-Fi.");
esp_err_t err = esp_wifi_connect();
Expand All @@ -322,7 +336,7 @@ static void wifi_recovery_task(void *pvParameters) {
esp_err_to_name(err));
}
// Wait 20 seconds after re-connection attempt before trying again
vTaskDelay(pdMS_TO_TICKS(15000));
vTaskDelay(pdMS_TO_TICKS(10000));
}
}
}
Expand Down
8 changes: 6 additions & 2 deletions main/driver_setup.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@ extern esp_netif_t* driver_setup_wifi_netif;
// Starts the ESP32-EVB ethernet driver and populates `driver_setup_eth_netif`.
// `ip_info` specifies the static IP address config.
// Uses DHCP if `ip_info` is NULL.
esp_err_t driver_setup_ethernet(const esp_netif_ip_info_t* ip_info);
// `hostname` must be a valid hostname C-string.
esp_err_t driver_setup_ethernet(const esp_netif_ip_info_t* ip_info,
const char* hostname);

// Starts the ESP32-EVB wifi driver and populates `driver_setup_wifi_netif`.
// `ip_info` specifies the static IP address config.
// Uses DHCP if `ip_info` is NULL.
// `hostname` must be a valid hostname C-string.
esp_err_t driver_setup_wifi(const esp_netif_ip_info_t* ip_info,
const char ssid[32], const char password[64]);
const char* hostname, const char ssid[32],
const char password[64]);

// Starts the ESP32-EVB CAN driver with the given `timing_config`.
esp_err_t driver_setup_can(const twai_timing_config_t* timing_config);
Loading

0 comments on commit 6ca0c1e

Please sign in to comment.