From eb5b469dd003a6a6b21f0c8c39c3acad08f8db06 Mon Sep 17 00:00:00 2001 From: Wastl Kraus Date: Sat, 27 Sep 2025 14:59:23 +0200 Subject: [PATCH] prepare release 0.8.6 --- DShotRMT.h | 2 +- README.md | 46 ++++++++++--- src/DShotRMT.h | 140 ++++++++-------------------------------- src/dshot_definitions.h | 75 +++++++-------------- src/web_content.h | 2 +- 5 files changed, 88 insertions(+), 177 deletions(-) diff --git a/DShotRMT.h b/DShotRMT.h index 367f706..29d290d 100644 --- a/DShotRMT.h +++ b/DShotRMT.h @@ -6,5 +6,5 @@ * @license MIT */ - #include "src/DShotRMT.h" +#include "src/DShotRMT.h" \ No newline at end of file diff --git a/README.md b/README.md index 370f231..4186cf2 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,13 @@ [![Arduino CI](https://github.com/derdoktor667/DShotRMT/actions/workflows/ci.yml/badge.svg)](https://github.com/derdoktor667/DShotRMT/actions/workflows/ci.yml) -A C++ library for generating DShot signals on ESP32 microcontrollers using the **modern ESP-IDF 5 RMT encoder API** (`rmt_tx.h` / `rmt_rx.h`). It leverages the standard `rmt_bytes_encoder` to ensure an efficient, hardware-timed, and maintainable implementation. **Note:** A byte-swapping fix has been implemented to address endianness differences when using `rmt_bytes_encoder` on ESP32. The library provides a simple way to control brushless motors in both Arduino and ESP-IDF projects. The legacy version using the old `rmt.h` API is available in the `oldAPI` branch. +A C++ library for generating DShot signals on ESP32 microcontrollers using the **modern ESP-IDF 5 RMT encoder API** (`rmt_tx.h` / `rmt_rx.h`). This library specifically leverages the official `rmt_bytes_encoder` API for an efficient, hardware-timed, and maintainable implementation. It provides a simple way to control brushless motors in both Arduino and ESP-IDF projects. The legacy version using the old `rmt.h` API is available in the `oldAPI` branch. + +### DShot300 Example Output + +Here's an example of the output from the `dshot300` example sketch: + +![DShot300 Example Output](img/dshot300.png) ## 🚀 Core Features @@ -14,6 +20,17 @@ A C++ library for generating DShot signals on ESP32 microcontrollers using the * - **Efficient and Lightweight:** The core library has no external dependencies. - **Arduino and ESP-IDF Compatible:** Can be used in both Arduino and ESP-IDF projects. +## ⏱️ DShot Timing Information + +The DShot protocol defines specific timing characteristics for each mode. The following table outlines the bit length, T1H (high time for a '1' bit), T0H (high time for a '0' bit), and frame length for the supported DShot modes: + +| DShot Mode | Bit Length (µs) | T1H Length (µs) | T0H Length (µs) | Frame Length (µs) | +| :--------- | :-------------- | :-------------- | :-------------- | :---------------- | +| DSHOT150 | 6.67 | 5.00 | 2.50 | 106.72 | +| DSHOT300 | 3.33 | 2.50 | 1.25 | 53.28 | +| DSHOT600 | 1.67 | 1.25 | 0.625 | 26.72 | +| DSHOT1200 | 0.83 | 0.67 | 0.335 | 13.28 | + ## 📦 Installation ### Arduino IDE @@ -105,15 +122,24 @@ lib_deps = The main class is `DShotRMT`. Here are the most important methods: -- `DShotRMT(gpio_num_t gpio, dshot_mode_t mode, bool is_bidirectional = false, uint16_t magnet_count = DEFAULT_MOTOR_MAGNET_COUNT)`: Constructor to create a new DShotRMT instance. (Note: Bidirectional DShot is currently not officially supported.) -- `begin()`: Initializes the RMT peripheral and the DShot encoder. -- `sendThrottlePercent(float percent)`: Sends a throttle value as a percentage (0.0-100.0). -- `sendThrottle(uint16_t throttle)`: Sends a raw throttle value (48-2047) to the motor. -- `sendCommand(uint16_t command)`: Sends a DShot command (0-47) to the motor. -- `getTelemetry(uint16_t magnet_count)`: Receives and parses telemetry data from the motor (for bidirectional DShot, which is currently not officially supported). -- `printDShotResult(dshot_result_t &result, Stream &output = Serial)`: Helper function to print DShot operation results and telemetry to a specified serial output. -- `DShotRMT::printDShotInfo(const DShotRMT &dshot_rmt, Stream &output = Serial)`: Static helper function to print detailed DShot signal information for a given DShotRMT instance. -- `DShotRMT::printCpuInfo(Stream &output = Serial)`: Static helper function to print detailed CPU information. +- `DShotRMT(gpio_num_t gpio, dshot_mode_t mode, bool is_bidirectional = false, uint16_t magnet_count = DEFAULT_MOTOR_MAGNET_COUNT)`: Constructor to create a new DShotRMT instance. +- `begin()`: Initializes the DShot RMT channels and encoder. +- `sendThrottlePercent(float percent)`: Sends a throttle value as a percentage (0.0-100.0) to the ESC. +- `sendThrottle(uint16_t throttle)`: Sends a raw throttle value (48-2047) to the ESC. A value of 0 sends a motor stop command. +- `sendCommand(uint16_t command)`: Sends a single DShot command (0-47) to the ESC. +- `sendCommand(dshotCommands_e dshot_command, uint16_t repeat_count = DEFAULT_CMD_REPEAT_COUNT, uint16_t delay_us = DEFAULT_CMD_DELAY_US)`: Sends a DShot command multiple times with a delay between repetitions. This is a blocking function. +- `getTelemetry(uint16_t magnet_count = 0)`: Retrieves telemetry data from the ESC. If `magnet_count` is 0, uses the stored motor magnet count. +- `getESCInfo()`: Sends a command to the ESC to request ESC information. +- `setMotorSpinDirection(bool reversed)`: Sets the motor spin direction. `true` for reversed, `false` for normal. +- `saveESCSettings()`: Sends a command to the ESC to save its current settings. Use with caution as this writes to ESC's non-volatile memory. +- `printDShotResult(dshot_result_t &result, Stream &output = Serial)`: Prints the result of a DShot operation to the specified output stream. +- `DShotRMT::printDShotInfo(const DShotRMT &dshot_rmt, Stream &output = Serial)`: Prints detailed DShot signal information for a given DShotRMT instance. +- `DShotRMT::printCpuInfo(Stream &output = Serial)`: Prints detailed CPU information. +- `setMotorMagnetCount(uint16_t magnet_count)`: Sets the motor magnet count for RPM calculation. +- `getMode()`: Gets the current DShot mode. +- `isBidirectional()`: Checks if bidirectional DShot is enabled. +- `getEncodedFrameValue()`: Gets the last encoded DShot frame value. +- `getThrottleValue()`: Gets the last transmitted throttle value. ## 🤝 Contributing diff --git a/src/DShotRMT.h b/src/DShotRMT.h index 4117245..9505881 100644 --- a/src/DShotRMT.h +++ b/src/DShotRMT.h @@ -15,153 +15,75 @@ #include #include -/** - * @brief DShotRMT Main Class for DShot signal generation and reception. - * - * This class provides an interface to generate DShot signals for Electronic Speed Controllers (ESCs) - * and to receive telemetry data using the ESP32's RMT peripheral. - */ +// Main class for DShot signal generation and reception. +// This class provides an interface to generate DShot signals for Electronic Speed Controllers (ESCs) +// and to receive telemetry data using the ESP32's RMT peripheral. class DShotRMT { public: - /** - * @brief Constructor for DShotRMT with GPIO number. - * @param gpio The GPIO pin number to use for DShot communication. - * @param mode The DShot mode (e.g., DSHOT150, DSHOT300, DSHOT600). - * @param is_bidirectional True if bidirectional DShot is enabled, false otherwise. - * @param magnet_count The number of magnets in the motor for RPM calculation. - */ + // Constructor for DShotRMT with GPIO number. explicit DShotRMT(gpio_num_t gpio = GPIO_NUM_16, dshot_mode_t mode = dshot_mode_t::DSHOT300, bool is_bidirectional = false, uint16_t magnet_count = DEFAULT_MOTOR_MAGNET_COUNT); - /** - * @brief Constructor for DShotRMT with Arduino pin number. - * @param pin_nr The Arduino pin number to use for DShot communication. - * @param mode The DShot mode (e.g., DSHOT150, DSHOT300, DSHOT600). - * @param is_bidirectional True if bidirectional DShot is enabled, false otherwise. - * @param magnet_count The number of magnets in the motor for RPM calculation. - */ + // Constructor for DShotRMT with Arduino pin number. DShotRMT(uint16_t pin_nr, dshot_mode_t mode, bool is_bidirectional, uint16_t magnet_count = DEFAULT_MOTOR_MAGNET_COUNT); - /** - * @brief Destructor for DShotRMT. - * Cleans up RMT channels and encoder resources. - */ + // Destructor for DShotRMT. + // Cleans up RMT channels and encoder resources. ~DShotRMT(); // Public Core Functions - /** - * @brief Initializes the DShot RMT channels and encoder. - * @return dshot_result_t indicating success or failure of the initialization. - */ + // Initializes the DShot RMT channels and encoder. dshot_result_t begin(); - /** - * @brief Sends a DShot throttle value to the ESC. - * @param throttle The throttle value (48-2047). A value of 0 sends a motor stop command. - * @return dshot_result_t indicating success or failure of the transmission. - */ + // Sends a DShot throttle value to the ESC. dshot_result_t sendThrottle(uint16_t throttle); - /** - * @brief Sends a DShot throttle value as a percentage to the ESC. - * @param percent The throttle percentage (0.0f - 100.0f). - * @return dshot_result_t indicating success or failure of the transmission. - */ + // Sends a DShot throttle value as a percentage to the ESC. dshot_result_t sendThrottlePercent(float percent); - /** - * @brief Sends a single DShot command to the ESC. - * @param command The DShot command value (0-47). - * @return dshot_result_t indicating success or failure of the transmission. - */ + // Sends a single DShot command to the ESC. dshot_result_t sendCommand(uint16_t command); - /** - * @brief Sends a DShot command multiple times with a delay between repetitions. This is a blocking function. - * @param dshot_command The DShot command to send. - * @param repeat_count The number of times to repeat the command. - * @param delay_us The delay in microseconds between repetitions. - * @return dshot_result_t indicating success or failure of the transmission. - */ + // Sends a DShot command multiple times with a delay between repetitions. This is a blocking function. dshot_result_t sendCommand(dshotCommands_e dshot_command, uint16_t repeat_count = DEFAULT_CMD_REPEAT_COUNT, uint16_t delay_us = DEFAULT_CMD_DELAY_US); - /** - * @brief Retrieves telemetry data from the ESC. - * @param magnet_count The number of magnets in the motor. If 0, uses the stored motor_magnet_count. - * @return dshot_result_t containing telemetry data (eRPM, motor RPM) if successful. - */ + // Retrieves telemetry data from the ESC. dshot_result_t getTelemetry(uint16_t magnet_count = 0); - /** - * @brief Sends a command to the ESC to request ESC information. - * @return dshot_result_t indicating success or failure of the command transmission. - */ + // Sends a command to the ESC to request ESC information. dshot_result_t getESCInfo(); - /** - * @brief Sets the motor spin direction. - * @param reversed True for reversed direction, false for normal. - * @return dshot_result_t indicating success or failure of the command transmission. - */ + // Sets the motor spin direction. dshot_result_t setMotorSpinDirection(bool reversed); - /** - * @brief Sends a command to the ESC to save its current settings. - * Use with caution as this writes to ESC's non-volatile memory. - * @return dshot_result_t indicating success or failure of the command transmission. - */ + // Sends a command to the ESC to save its current settings. + // Use with caution as this writes to ESC's non-volatile memory. dshot_result_t saveESCSettings(); // Public Utility & Info Functions - /** - * @brief Prints detailed DShot signal information for a given DShotRMT instance. - * @param dshot_rmt The DShotRMT instance to get information from. - * @param output The output stream (e.g., Serial) to print to. Defaults to Serial. - */ + // Prints detailed DShot signal information for a given DShotRMT instance. static void printDShotInfo(const DShotRMT &dshot_rmt, Stream &output = Serial); - /** - * @brief Prints detailed CPU information. - * @param output The output stream (e.g., Serial) to print to. Defaults to Serial. - */ + // Prints detailed CPU information. static void printCpuInfo(Stream &output = Serial); - /** - * @brief Sets the motor magnet count for RPM calculation. - * @param magnet_count The number of magnets in the motor. - */ + // Sets the motor magnet count for RPM calculation. void setMotorMagnetCount(uint16_t magnet_count); - /** - * @brief Gets the current DShot mode. - * @return The current dshot_mode_t. - */ + // Gets the current DShot mode. dshot_mode_t getMode() const { return _mode; } - /** - * @brief Checks if bidirectional DShot is enabled. - * @return True if bidirectional DShot is enabled, false otherwise. - */ + // Checks if bidirectional DShot is enabled. bool isBidirectional() const { return _is_bidirectional; } - /** - * @brief Gets the last encoded DShot frame value. - * @return The 16-bit encoded DShot frame value. - */ + // Gets the last encoded DShot frame value. uint16_t getEncodedFrameValue() const { return _encoded_frame_value; } - /** - * @brief Gets the last transmitted throttle value. - * @return The last transmitted throttle value. - */ + // Gets the last transmitted throttle value. uint16_t getThrottleValue() const { return _packet.throttle_value; } // Deprecated Methods - /** - * @brief Deprecated. Use sendThrottle() instead. - * @param throttle The throttle value. - * @return True on success, false on failure. - */ + // Deprecated. Use sendThrottle() instead. [[deprecated("Use sendThrottle() instead")]] bool setThrottle(uint16_t throttle) { @@ -169,11 +91,7 @@ public: return result.success; } - /** - * @brief Deprecated. Use sendCommand() instead. - * @param command The DShot command. - * @return True on success, false on failure. - */ + // Deprecated. Use sendCommand() instead. [[deprecated("Use sendCommand() instead")]] bool sendDShotCommand(uint16_t command) { @@ -181,11 +99,7 @@ public: return result.success; } - /** - * @brief Deprecated. Use getTelemetry() instead. - * @param magnet_count The number of magnets in the motor. - * @return The motor RPM. - */ + // Deprecated. Use getTelemetry() instead. [[deprecated("Use getTelemetry() instead")]] uint32_t getMotorRPM(uint8_t magnet_count) { diff --git a/src/dshot_definitions.h b/src/dshot_definitions.h index 268f342..b5f1877 100644 --- a/src/dshot_definitions.h +++ b/src/dshot_definitions.h @@ -6,10 +6,7 @@ #include #include // Added for std::atomic -/** - * @brief DShot Modes - * Defines the available DShot communication speeds. - */ +// Defines the available DShot communication speeds. enum class dshot_mode_t { DSHOT_OFF, @@ -19,44 +16,32 @@ enum class dshot_mode_t DSHOT1200 }; -/** - * @brief DShot Packet Structure - * Represents the 16-bit DShot data packet sent to the ESC. - */ +// Represents the 16-bit DShot data packet sent to the ESC. typedef struct dshot_packet { - uint16_t throttle_value : 11; ///< 11-bit throttle value or command. - bool telemetric_request : 1; ///< 1-bit telemetry request flag. - uint16_t checksum : 4; ///< 4-bit CRC checksum. + uint16_t throttle_value : 11; // 11-bit throttle value or command. + bool telemetric_request : 1; // 1-bit telemetry request flag. + uint16_t checksum : 4; // 4-bit CRC checksum. } dshot_packet_t; -/** - * @brief DShot Timing Configuration - * Defines the bit length and high time for a '1' bit in microseconds for each DShot mode. - */ +// Defines the bit length and high time for a '1' bit in microseconds for each DShot mode. typedef struct dshot_timing { - double bit_length_us; ///< Total duration of one bit in microseconds. - double t1h_lenght_us; ///< High time duration for a '1' bit in microseconds. + double bit_length_us; // Total duration of one bit in microseconds. + double t1h_lenght_us; // High time duration for a '1' bit in microseconds. } dshot_timing_us_t; -/** - * @brief RMT Timing Configuration - * Stores pre-calculated timing values in RMT ticks for efficient signal generation. - */ +// Stores pre-calculated timing values in RMT ticks for efficient signal generation. typedef struct rmt_ticks { - uint16_t bit_length_ticks; ///< Total duration of one bit in RMT ticks. - uint16_t t1h_ticks; ///< High time duration for a '1' bit in RMT ticks. - uint16_t t1l_ticks; ///< Low time duration for a '1' bit in RMT ticks. - uint16_t t0h_ticks; ///< High time duration for a '0' bit in RMT ticks. - uint16_t t0l_ticks; ///< Low time duration for a '0' bit in RMT ticks. + uint16_t bit_length_ticks; // Total duration of one bit in RMT ticks. + uint16_t t1h_ticks; // High time duration for a '1' bit in RMT ticks. + uint16_t t1l_ticks; // Low time duration for a '1' bit in RMT ticks. + uint16_t t0h_ticks; // High time duration for a '0' bit in RMT ticks. + uint16_t t0l_ticks; // Low time duration for a '0' bit in RMT ticks. } rmt_ticks_t; -/** - * @brief DShot Error Codes - * Enum class for specific error and success codes returned by DShotRMT functions. - */ +// Enum class for specific error and success codes returned by DShotRMT functions. enum class dshot_msg_code_t { DSHOT_ERROR_NONE = 0, @@ -86,22 +71,16 @@ enum class dshot_msg_code_t DSHOT_ERROR_COMMAND_SUCCESS }; -/** - * @brief Unified DShot Result Structure - * Contains the success status, an error code, and optional telemetry data. - */ +// Contains the success status, an error code, and optional telemetry data. typedef struct dshot_result { bool success; - dshot_msg_code_t error_code; ///< Specific error or success code. - uint16_t erpm; ///< Electrical RPM (eRPM) if telemetry is successful. - uint16_t motor_rpm; ///< Motor RPM if telemetry is successful and magnet count is known. + dshot_msg_code_t error_code; // Specific error or success code. + uint16_t erpm; // Electrical RPM (eRPM) if telemetry is successful. + uint16_t motor_rpm; // Motor RPM if telemetry is successful and magnet count is known. } dshot_result_t; -/** - * @brief DShot Commands - * Enum class for standard DShot commands that can be sent to an ESC. - */ +// Enum class for standard DShot commands that can be sent to an ESC. enum dshotCommands_e { DSHOT_CMD_MOTOR_STOP = 0, @@ -134,14 +113,11 @@ enum dshotCommands_e DSHOT_CMD_MAX = 47 }; -/** - * @brief DShot Command Type Enum - * Defines how DShot commands are sent. - */ +// Defines how DShot commands are sent. enum class dshotCommandType_e { - DSHOT_CMD_TYPE_INLINE = 0, ///< Commands sent inline with motor signal (motors must be enabled). - DSHOT_CMD_TYPE_BLOCKING ///< Commands sent in blocking method (motors must be disabled). + DSHOT_CMD_TYPE_INLINE = 0, // Commands sent inline with motor signal (motors must be enabled). + DSHOT_CMD_TYPE_BLOCKING // Commands sent in blocking method (motors must be disabled). }; // DShot Protocol Constants @@ -219,11 +195,6 @@ const char *const INVALID_COMMAND = "Invalid command!"; const char *const COMMAND_SUCCESS = "DShot command sent successfully"; // Helper Functions -/** - * @brief Prints the result of a DShot operation to the specified output stream. - * @param result The dshot_result_t structure containing the operation's outcome. - * @param output The output stream (e.g., Serial) to print to. Defaults to Serial. - */ inline void printDShotResult(dshot_result_t &result, Stream &output = Serial) { const char *msg_str; diff --git a/src/web_content.h b/src/web_content.h index 104adcb..2b8130d 100644 --- a/src/web_content.h +++ b/src/web_content.h @@ -9,7 +9,7 @@ #pragma once // Web Site Content -static constexpr char index_html[] = R"rawliteral( +const char *index_html = R"rawliteral(