diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..278a862 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build +sdkconfig diff --git a/CMakeLists.txt b/CMakeLists.txt index 8bb92f3..d8895a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,8 @@ -# The following five lines of boilerplate have to be in your project's -# CMakeLists in this exact order for cmake to work correctly +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.16) include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(spincoat-plater-firmware) +# "Trim" the build. Include the minimal set of components, main, and anything it depends on. +idf_build_set_property(MINIMAL_BUILD ON) +project(dshot_esc) diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 440c423..c716685 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,2 +1,3 @@ -idf_component_register(SRCS "spincoat-plater-firmware.c" +idf_component_register(SRCS "spincoat-plater-firmware.c" "dshot_esc_encoder.c" + PRIV_REQUIRES esp_driver_rmt INCLUDE_DIRS ".") diff --git a/main/spincoat-plater-firmware.c b/main/spincoat-plater-firmware.c index 7b66f33..1fe2d6d 100644 --- a/main/spincoat-plater-firmware.c +++ b/main/spincoat-plater-firmware.c @@ -1,6 +1,71 @@ -#include +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "driver/rmt_tx.h" +#include "dshot_esc_encoder.h" + +#if CONFIG_IDF_TARGET_ESP32H2 +#define DSHOT_ESC_RESOLUTION_HZ 32000000 // 32MHz resolution, DSHot protocol needs a relative high resolution +#else +#define DSHOT_ESC_RESOLUTION_HZ 40000000 // 40MHz resolution, DSHot protocol needs a relative high resolution +#endif +#define DSHOT_ESC_GPIO_NUM 22 + +static const char *TAG = "spincoat-plater-firmware"; void app_main(void) { + ESP_LOGI(TAG, "Create RMT TX channel"); + rmt_channel_handle_t esc_chan = NULL; + rmt_tx_channel_config_t tx_chan_config = { + .clk_src = RMT_CLK_SRC_DEFAULT, // select a clock that can provide needed resolution + .gpio_num = DSHOT_ESC_GPIO_NUM, + .mem_block_symbols = 64, + .resolution_hz = DSHOT_ESC_RESOLUTION_HZ, + .trans_queue_depth = 10, // set the number of transactions that can be pending in the background + }; + ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_chan_config, &esc_chan)); + + ESP_LOGI(TAG, "Install Dshot ESC encoder"); + rmt_encoder_handle_t dshot_encoder = NULL; + dshot_esc_encoder_config_t encoder_config = { + .resolution = DSHOT_ESC_RESOLUTION_HZ, + .baud_rate = 300000, // DSHOT300 protocol + .post_delay_us = 50, // extra delay between each frame + }; + ESP_ERROR_CHECK(rmt_new_dshot_esc_encoder(&encoder_config, &dshot_encoder)); + + ESP_LOGI(TAG, "Enable RMT TX channel"); + ESP_ERROR_CHECK(rmt_enable(esc_chan)); + + rmt_transmit_config_t tx_config = { + .loop_count = -1, // infinite loop + }; + dshot_esc_throttle_t throttle = { + .throttle = 0, + .telemetry_req = false, // telemetry is not supported in this example + }; + + ESP_LOGI(TAG, "Start ESC by sending zero throttle for a while..."); + ESP_ERROR_CHECK(rmt_transmit(esc_chan, dshot_encoder, &throttle, sizeof(throttle), &tx_config)); + vTaskDelay(pdMS_TO_TICKS(5000)); + + ESP_LOGI(TAG, "Increase throttle, no telemetry"); + // Commented out esc driving example, working on other stuff for now +// for (uint16_t thro = 100; thro < 1000; thro += 10) { +// throttle.throttle = thro; +// ESP_ERROR_CHECK(rmt_transmit(esc_chan, dshot_encoder, &throttle, sizeof(throttle), &tx_config)); +// // the previous loop transfer is till undergoing, we need to stop it and restart, +// // so that the new throttle can be updated on the output +// ESP_ERROR_CHECK(rmt_disable(esc_chan)); +// ESP_ERROR_CHECK(rmt_enable(esc_chan)); +// vTaskDelay(pdMS_TO_TICKS(1000)); +// } }