Skip to content

Commit c2d581a

Browse files
authored
Add int32_publisher_custom_transport_usbcdc example (#255)
* Add int32_publisher_custom_transport_usbcdc example This example demonstrates how to enable ROS2 communication via USB CDC and log output on the ESP32-S2. Reviewed-by: Leandro Mendes do Santos <[email protected]> Signed-off-by: Samuel Henrique Guimarães Alencar <[email protected]> * Add build for int32_publisher_custom_transport_usbcdc example to the CI workflow Signed-off-by: Samuel Henrique Guimarães Alencar <[email protected]> * Fix CI condition for int32_publisher_custom_transport_usbcdc example - Updated conditional logic to ensure builds are triggered only when idf_target is either 'esp32s2' or 'esp32s3' and idf_version is 'espressif/idf:release-v5.2'. Signed-off-by: Samuel Henrique Guimarães Alencar <[email protected]> --------- Signed-off-by: Samuel Henrique Guimarães Alencar <[email protected]>
1 parent 97796fe commit c2d581a

File tree

19 files changed

+563
-0
lines changed

19 files changed

+563
-0
lines changed

.github/workflows/ci.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,15 @@ jobs:
8080
idf.py set-target ${{ matrix.idf_target }}
8181
idf.py build
8282
83+
- name: Build sample - int32_publisher_custom_transport_usbcdc
84+
shell: bash
85+
if: (matrix.idf_target == 'esp32s2' || matrix.idf_target == 'esp32s3') && matrix.idf_version == 'espressif/idf:release-v5.2'
86+
run: |
87+
. $IDF_PATH/export.sh
88+
cd micro_ros_espidf_component/examples/int32_publisher_custom_transport_usbcdc
89+
idf.py set-target ${{ matrix.idf_target }}
90+
idf.py build
91+
8392
- name: Build sample - multithread_publisher
8493
shell: bash
8594
run: |
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
build
2+
sdkconfig
3+
sdkconfig.old
4+
managed_components
5+
.vscode
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
cmake_minimum_required(VERSION 3.5)
2+
3+
set (EXTRA_COMPONENT_DIRS "./../../.")
4+
5+
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
6+
project(int32_publisher)
7+
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
2+
# USB-CDC Custom Transport Example
3+
4+
| Supported Targets | ESP32-S2 | ESP32-S3 |
5+
|-------------------|----------|----------|
6+
7+
This example demonstrates how to set up the ESP32-S2/S3 to function as a USB Serial Device (CDC-ACM) and communicate with micro-ROS agent using USB-CDC custom transport.
8+
9+
The [TinyUSB component](https://components.espressif.com/components/espressif/esp_tinyusb) is used as the USB stack.
10+
11+
This example is based on the [int32_publisher_custom_transport](https://github.com/micro-ROS/micro_ros_espidf_component/tree/jazzy/examples/int32_publisher_custom_transport), the [TinyUSB Serial Device Example](https://github.com/espressif/esp-idf/tree/master/examples/peripherals/usb/device/tusb_serial_device), and the [TinyUSB Console Example](https://github.com/espressif/esp-idf/tree/master/examples/peripherals/usb/device/tusb_console) for log output.
12+
13+
## How to use example
14+
15+
This example is configured to use the two interfaces of USB-CDC. One interface is used for the micro-ROS communication, and the other interface is used for the log output.
16+
17+
### Hardware Required
18+
19+
This example can be run on any development board that has a USB-CDC interface.
20+
21+
### Configure the project
22+
23+
Set the target device in the project configuration:
24+
25+
```bash
26+
idf.py set-target esp32s2 # or esp32s3
27+
```
28+
29+
If you want to use only the micro-ROS communication interface, you need to turn off log output in menuconfig. Run `idf.py menuconfig` and navigate to `Component config → Log output → Default log verbosity` and set it to `No output`. You should also set `Component config → TinyUSB Stack → Communication Device Class (CDC) → CDC Channel Count` to 1.
30+
31+
### Build and Flash
32+
33+
> [!NOTE]
34+
> The ESP32-S2/S3 chip needs to be in bootloader mode before it can be detected as a DFU device and flash. This can be achieved by pulling GPIO0 down (e.g., pressing the BOOT button), pulling RESET down for a moment, and releasing GPIO0.
35+
36+
#### Build the project
37+
38+
Build DFU image:
39+
40+
```bash
41+
idf.py dfu
42+
```
43+
44+
#### Flash the project
45+
46+
Put the ESP32-S2/S3 into bootloader mode and run the following command:
47+
48+
```bash
49+
idf.py dfu-flash
50+
```
51+
52+
### Run micro-ROS Agent
53+
54+
```bash
55+
export ROS_DOMAIN_ID=100 # Set the ROS2 domain ID
56+
ros2 run micro_ros_agent micro_ros_agent serial --dev /dev/ttyACM0
57+
```
58+
59+
Output expected:
60+
61+
```bash
62+
[1724443525.673894] info | TermiosAgentLinux.cpp | init | running... | fd: 3
63+
[1724443525.674071] info | Root.cpp | set_verbose_level | logger setup | verbose_level: 4
64+
[1724443529.936542] info | TermiosAgentLinux.cpp | init | running... | fd: 3
65+
[1724443531.062646] info | Root.cpp | create_client | create | client_key: 0x3E801A05, session_id: 0x81
66+
[1724443531.062805] info | SessionManager.hpp | establish_session | session established | client_key: 0x3E801A05, address: 0
67+
[1724443531.107532] info | ProxyClient.cpp | create_participant | participant created | client_key: 0x3E801A05, participant_id: 0x000(1)
68+
[1724443531.137064] info | ProxyClient.cpp | create_topic | topic created | client_key: 0x3E801A05, topic_id: 0x000(2), participant_id: 0x000(1)
69+
[1724443531.167351] info | ProxyClient.cpp | create_publisher | publisher created | client_key: 0x3E801A05, publisher_id: 0x000(3), participant_id: 0x000(1)
70+
[1724443531.237811] info | ProxyClient.cpp | create_datawriter | datawriter created | client_key: 0x3E801A05, datawriter_id: 0x000(5), publisher_id: 0x000(3)
71+
```
72+
73+
After connecting the ESP32-S2/S3 and the micro-ROS agent, you can list the topics:
74+
75+
```bash
76+
export ROS_DOMAIN_ID=100 # Set the ROS2 domain ID
77+
ros2 topic list
78+
```
79+
80+
Output expected:
81+
82+
```bash
83+
/esp32s2/int32_publisher_usbcdc
84+
/parameter_events
85+
/rosout
86+
```
87+
88+
And see if the `esp32s2/int32_publisher_usbcdc` topic is available. You can echo the topic to see the messages:
89+
90+
```bash
91+
export ROS_DOMAIN_ID=100 # Set the ROS2 domain ID
92+
ros2 topic echo esp32s2/int32_publisher_usbcdc
93+
```
94+
95+
Output expected:
96+
97+
```bash
98+
data: 1
99+
---
100+
data: 2
101+
---
102+
data: 3
103+
---
104+
data: 4
105+
---
106+
data: 5
107+
.
108+
.
109+
.
110+
```
111+
112+
To see the log output, you can use the following command:
113+
114+
```bash
115+
minicom -D /dev/ttyACM1 -b 115200
116+
```
117+
118+
Output expected:
119+
120+
```bash
121+
Welcome to minicom 2.8
122+
123+
OPTIONS: I18n
124+
Port /dev/ttyACM1
125+
Press CTRL-A Z for help on special keys
126+
127+
I (2688) MAIN: micro-ROS task created
128+
I (2688) main_task: Returned from app_main()
129+
I (3708) TIMER_CALLBACK: Message published: 0
130+
I (4708) TIMER_CALLBACK: Message published: 1
131+
I (5708) TIMER_CALLBACK: Message published: 2
132+
I (6708) TIMER_CALLBACK: Message published: 3
133+
I (7708) TIMER_CALLBACK: Message published: 4
134+
I (8708) TIMER_CALLBACK: Message published: 5
135+
.
136+
.
137+
.
138+
```
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"names": {
3+
"rmw_microxrcedds": {
4+
"cmake-args": [
5+
"-DRMW_UXRCE_TRANSPORT=custom"
6+
]
7+
}
8+
}
9+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
idf_component_register(SRCS "esp32s2_usbcdc_logging.c" INCLUDE_DIRS ".")
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#include "esp32s2_usbcdc_logging.h"
2+
3+
// Initialize USB-CDC logging
4+
esp_err_t esp32s2_usbcdc_logging_init(void)
5+
{
6+
const tinyusb_config_t tinyusb_config = {
7+
.descriptor = NULL,
8+
.string_descriptor = NULL,
9+
.external_phy = false,
10+
.configuration_descriptor = NULL,
11+
};
12+
13+
esp_err_t ret = tinyusb_driver_install(&tinyusb_config);
14+
15+
if (ret == ESP_ERR_INVALID_ARG || ret == ESP_FAIL) {
16+
return ret;
17+
}
18+
19+
tinyusb_config_cdcacm_t acm_config = {
20+
.usb_dev = TINYUSB_USBDEV_0,
21+
.cdc_port = TINYUSB_CDC_ACM_1,
22+
.rx_unread_buf_sz = CONFIG_TINYUSB_CDC_RX_BUFSIZE,
23+
.callback_rx = NULL,
24+
.callback_rx_wanted_char = NULL,
25+
.callback_line_state_changed = NULL,
26+
.callback_line_coding_changed = NULL,
27+
};
28+
29+
ret = tusb_cdc_acm_init(&acm_config);
30+
31+
if (ret != ESP_OK) {
32+
return ret;
33+
}
34+
35+
ret = esp_tusb_init_console(TINYUSB_CDC_ACM_1);
36+
37+
return ret;
38+
}
39+
40+
// Deinitialize USB-CDC logging
41+
esp_err_t esp32s2_usbcdc_logging_deinit(void)
42+
{
43+
esp_err_t ret = esp_tusb_deinit_console(TINYUSB_CDC_ACM_1);
44+
45+
return ret;
46+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#ifndef ESP32S2_USBCDC_LOGGING_H
2+
#define ESP32S2_USBCDC_LOGGING_H
3+
4+
#include "esp_err.h"
5+
#include "tinyusb.h"
6+
#include "tusb_cdc_acm.h"
7+
#include "tusb_console.h"
8+
#include "sdkconfig.h"
9+
10+
#if (CONFIG_TINYUSB_CDC_COUNT < 2)
11+
#warning "Define CONFIG_TINYUSB_CDC_COUNT to 2 in menuconfig if you want log over USBCDC. Otherwise, disable log output in menuconfig."
12+
#endif
13+
14+
#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
15+
16+
#ifdef __cplusplus
17+
extern "C"
18+
{
19+
#endif
20+
21+
esp_err_t esp32s2_usbcdc_logging_init(void);
22+
esp_err_t esp32s2_usbcdc_logging_deinit(void);
23+
24+
#ifdef __cplusplus
25+
}
26+
#endif
27+
28+
#else
29+
#error "Logging over USB-CDC is only supported on ESP32-S2 or ESP32-S3 targets"
30+
#endif
31+
32+
#endif // ESP32S2_USBCDC_LOGGING_H
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
## IDF Component Manager Manifest File
2+
dependencies:
3+
espressif/esp_tinyusb: "^1.4.4"
4+
## Required IDF version
5+
idf:
6+
version: ">=5.0"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
idf_component_register(SRCS "esp32s2_usbcdc_transport.c"
2+
INCLUDE_DIRS "."
3+
REQUIRES micro_ros_espidf_component # include <uxr/client/transport.h>
4+
)

0 commit comments

Comments
 (0)