From 3b84df295f70b82e2769dd2dc3d5fc620755cfde Mon Sep 17 00:00:00 2001 From: Wastl Kraus Date: Sat, 27 Sep 2025 23:17:43 +0200 Subject: [PATCH] ...break down result struct --- DShotRMT.code-workspace | 5 +- examples/dshot300/dshot300.ino | 4 +- src/DShotRMT.cpp | 61 +++++------ src/dshot_definitions.h | 187 ++++++++++----------------------- 4 files changed, 89 insertions(+), 168 deletions(-) diff --git a/DShotRMT.code-workspace b/DShotRMT.code-workspace index 821c319..e535653 100644 --- a/DShotRMT.code-workspace +++ b/DShotRMT.code-workspace @@ -7,6 +7,9 @@ "settings": { "files.associations": { "string": "cpp" - } + }, + "arduino.logLevel": "verbose", + "arduino.path": "/usr/bin/arduino-cli", + "arduino.useArduinoCli": true } } \ No newline at end of file diff --git a/examples/dshot300/dshot300.ino b/examples/dshot300/dshot300.ino index abdb6bd..3d10bef 100644 --- a/examples/dshot300/dshot300.ino +++ b/examples/dshot300/dshot300.ino @@ -7,7 +7,7 @@ */ #include -#include "DShotRMT.h" +#include // USB serial port settings static constexpr auto &USB_SERIAL = Serial0; @@ -29,7 +29,7 @@ static constexpr auto IS_BIDIRECTIONAL = false; static constexpr auto MOTOR01_MAGNET_COUNT = 14; // Creates the motor instance -DShotRMT motor01(MOTOR01_PIN, DSHOT_MODE, IS_BIDIRECTIONAL, MOTOR01_MAGNET_COUNT); +DShotRMT motor01(MOTOR01_PIN, DSHOT_MODE, IS_BIDIRECTIONAL); // void setup() diff --git a/src/DShotRMT.cpp b/src/DShotRMT.cpp index 964342e..08a3e25 100644 --- a/src/DShotRMT.cpp +++ b/src/DShotRMT.cpp @@ -38,9 +38,6 @@ DShotRMT::DShotRMT(gpio_num_t gpio, dshot_mode_t mode, bool is_bidirectional, ui { // Pre-calculate timing and bit positions for performance _preCalculateRMTTicks(); - - // Activate internal pullup resistor - // gpio_set_pull_mode(_gpio, GPIO_PULLUP_ONLY); } // Constructor using pin number @@ -87,7 +84,7 @@ dshot_result_t DShotRMT::begin() { if (!_initTXChannel().success) { - return {false, dshot_msg_code_t::DSHOT_ERROR_TX_INIT_FAILED}; + return {false, TX_INIT_FAILED}; } if (_is_bidirectional) @@ -98,7 +95,7 @@ dshot_result_t DShotRMT::begin() rmt_disable(_rmt_tx_channel); rmt_del_channel(_rmt_tx_channel); _rmt_tx_channel = nullptr; - return {false, dshot_msg_code_t::DSHOT_ERROR_RX_INIT_FAILED}; + return {false, RX_INIT_FAILED}; } } @@ -116,10 +113,10 @@ dshot_result_t DShotRMT::begin() _rmt_rx_channel = nullptr; } - return {false, dshot_msg_code_t::DSHOT_ERROR_ENCODER_INIT_FAILED}; + return {false, ENCODER_INIT_FAILED}; } - return {true, dshot_msg_code_t::DSHOT_ERROR_INIT_SUCCESS}; + return {true, INIT_SUCCESS}; } // Send throttle value @@ -143,12 +140,11 @@ dshot_result_t DShotRMT::sendThrottlePercent(float percent) { if (percent < 0.0f || percent > 100.0f) { - return {false, dshot_msg_code_t::DSHOT_ERROR_PERCENT_NOT_IN_RANGE}; + return {false, PERCENT_NOT_IN_RANGE}; } // Map percent to DShot throttle range uint16_t throttle = static_cast(DSHOT_THROTTLE_MIN + ((DSHOT_THROTTLE_MAX - DSHOT_THROTTLE_MIN) / 100.0f) * percent); - return sendThrottle(throttle); } @@ -157,7 +153,7 @@ dshot_result_t DShotRMT::sendCommand(uint16_t command) { if (command > static_cast(dshotCommands_e::DSHOT_CMD_MAX)) { - return {false, dshot_msg_code_t::DSHOT_ERROR_COMMAND_NOT_VALID}; + return {false, COMMAND_NOT_VALID}; } _packet = _buildDShotPacket(command); @@ -168,11 +164,11 @@ dshot_result_t DShotRMT::sendCommand(uint16_t command) // This is a blocking function that uses delayMicroseconds for repetitions. dshot_result_t DShotRMT::sendCommand(dshotCommands_e dshot_command, uint16_t repeat_count, uint16_t delay_us) { - dshot_result_t result = {false, dshot_msg_code_t::DSHOT_ERROR_UNKNOWN}; + dshot_result_t result = {false, UNKNOWN_ERROR}; if (!_isValidCommand(dshot_command)) { - result.error_code = dshot_msg_code_t::DSHOT_ERROR_INVALID_COMMAND; + result.result_code = INVALID_COMMAND; return result; } @@ -186,7 +182,7 @@ dshot_result_t DShotRMT::sendCommand(dshotCommands_e dshot_command, uint16_t rep if (!single_result.success) { all_successful = false; - result.error_code = single_result.error_code; + result.result_code = single_result.result_code; break; } @@ -202,7 +198,7 @@ dshot_result_t DShotRMT::sendCommand(dshotCommands_e dshot_command, uint16_t rep if (result.success) { - result.error_code = dshot_msg_code_t::DSHOT_ERROR_COMMAND_SUCCESS; + result.result_code = COMMAND_SUCCESS; } return result; @@ -211,11 +207,11 @@ dshot_result_t DShotRMT::sendCommand(dshotCommands_e dshot_command, uint16_t rep // Get telemetry data dshot_result_t DShotRMT::getTelemetry(uint16_t magnet_count) { - dshot_result_t result = {false, dshot_msg_code_t::DSHOT_ERROR_TELEMETRY_FAILED, NO_DSHOT_TELEMETRY, NO_DSHOT_TELEMETRY}; + dshot_result_t result = {false, TELEMETRY_FAILED, NO_DSHOT_TELEMETRY, NO_DSHOT_TELEMETRY}; if (!_is_bidirectional) { - result.error_code = dshot_msg_code_t::DSHOT_ERROR_BIDIR_NOT_ENABLED; + result.result_code = BIDIR_NOT_ENABLED; return result; } @@ -237,7 +233,7 @@ dshot_result_t DShotRMT::getTelemetry(uint16_t magnet_count) result.success = true; result.erpm = erpm; result.motor_rpm = motor_rpm; - result.error_code = dshot_msg_code_t::DSHOT_ERROR_TELEMETRY_SUCCESS; + result.result_code = TELEMETRY_SUCCESS; } } @@ -298,14 +294,15 @@ dshot_result_t DShotRMT::_initTXChannel() if (rmt_new_tx_channel(&_tx_channel_config, &_rmt_tx_channel) != DSHOT_OK) { - return {false, dshot_msg_code_t::DSHOT_ERROR_TX_INIT_FAILED}; + return {false, TX_INIT_FAILED}; } + if (rmt_enable(_rmt_tx_channel) != DSHOT_OK) { - return {false, dshot_msg_code_t::DSHOT_ERROR_TX_INIT_FAILED}; + return {false, TX_INIT_FAILED}; } - return {true, dshot_msg_code_t::DSHOT_ERROR_TX_INIT_SUCCESS}; + return {true, TX_INIT_SUCCESS}; } dshot_result_t DShotRMT::_initRXChannel() @@ -313,7 +310,7 @@ dshot_result_t DShotRMT::_initRXChannel() // Double check if bidirectional mode is enabled if (!_is_bidirectional) { - return {true, dshot_msg_code_t::DSHOT_ERROR_NONE}; + return {true, NONE}; } _rx_channel_config.gpio_num = _gpio; @@ -327,19 +324,19 @@ dshot_result_t DShotRMT::_initRXChannel() if (rmt_new_rx_channel(&_rx_channel_config, &_rmt_rx_channel) != DSHOT_OK) { - return {false, dshot_msg_code_t::DSHOT_ERROR_RX_INIT_FAILED}; + return {false, RX_INIT_FAILED}; } // Register the callback function that will be triggered when a frame is received _rx_event_callbacks.on_recv_done = _on_rx_done; if (rmt_rx_register_event_callbacks(_rmt_rx_channel, &_rx_event_callbacks, this) != DSHOT_OK) { - return {false, dshot_msg_code_t::DSHOT_ERROR_CALLBACK_REGISTERING_FAILED}; + return {false, CALLBACK_REGISTERING_FAILED}; } if (rmt_enable(_rmt_rx_channel) != DSHOT_OK) { - return {false, dshot_msg_code_t::DSHOT_ERROR_RX_INIT_FAILED}; + return {false, RX_INIT_FAILED}; } // Start the receiver to wait for incoming telemetry data @@ -347,10 +344,10 @@ dshot_result_t DShotRMT::_initRXChannel() size_t rx_size_bytes = GCR_BITS_PER_FRAME * sizeof(rmt_symbol_word_t); if (rmt_receive(_rmt_rx_channel, rx_symbols, rx_size_bytes, &_rmt_rx_config) != DSHOT_OK) { - return {false, dshot_msg_code_t::DSHOT_ERROR_RECEIVER_FAILED}; + return {false, RECEIVER_FAILED}; } - return {true, dshot_msg_code_t::DSHOT_ERROR_RX_INIT_SUCCESS}; + return {true, RX_INIT_SUCCESS}; } dshot_result_t DShotRMT::_initDShotEncoder() @@ -375,10 +372,10 @@ dshot_result_t DShotRMT::_initDShotEncoder() if (rmt_new_bytes_encoder(&encoder_config, &_dshot_encoder) != DSHOT_OK) { - return {false, dshot_msg_code_t::DSHOT_ERROR_ENCODER_INIT_FAILED}; + return {false, ENCODER_INIT_FAILED}; } - return {true, dshot_msg_code_t::DSHOT_ERROR_ENCODER_INIT_SUCCESS}; + return {true, ENCODER_INIT_SUCCESS}; } // Private Packet Management Functions @@ -442,7 +439,7 @@ dshot_result_t DShotRMT::_sendDShotFrame(const dshot_packet_t &packet) // Ensure enough time has passed since the last transmission if (!_isFrameIntervalElapsed()) { - return {true, dshot_msg_code_t::DSHOT_ERROR_NONE}; + return {true, NONE}; } _encoded_frame_value = _buildDShotFrameValue(packet); @@ -455,12 +452,12 @@ dshot_result_t DShotRMT::_sendDShotFrame(const dshot_packet_t &packet) if (rmt_transmit(_rmt_tx_channel, _dshot_encoder, &swapped_value, tx_size_bytes, &_rmt_tx_config) != DSHOT_OK) { - return {false, dshot_msg_code_t::DSHOT_ERROR_TRANSMISSION_FAILED}; + return {false, TRANSMISSION_FAILED}; } _recordFrameTransmissionTime(); // Reset the timer for the next frame - return {true, dshot_msg_code_t::DSHOT_ERROR_TRANSMISSION_SUCCESS}; + return {true, TRANSMISSION_SUCCESS}; } // This function needs to be fast, as it generates the RMT symbols just before sending @@ -568,4 +565,4 @@ void DShotRMT::printCpuInfo(Stream &output) output.printf("CPU Freq = %lu MHz\n", ESP.getCpuFreqMHz()); output.printf("XTAL Freq = %lu MHz\n", getXtalFrequencyMhz()); output.printf("APB Freq = %lu Hz\n", getApbFrequency()); -} \ No newline at end of file +} diff --git a/src/dshot_definitions.h b/src/dshot_definitions.h index b5f1877..fd3f55d 100644 --- a/src/dshot_definitions.h +++ b/src/dshot_definitions.h @@ -44,38 +44,38 @@ typedef struct rmt_ticks // Enum class for specific error and success codes returned by DShotRMT functions. enum class dshot_msg_code_t { - DSHOT_ERROR_NONE = 0, - DSHOT_ERROR_UNKNOWN, - DSHOT_ERROR_TX_INIT_FAILED, - DSHOT_ERROR_RX_INIT_FAILED, - DSHOT_ERROR_ENCODER_INIT_FAILED, - DSHOT_ERROR_CALLBACK_REGISTERING_FAILED, - DSHOT_ERROR_RECEIVER_FAILED, - DSHOT_ERROR_TRANSMISSION_FAILED, - DSHOT_ERROR_THROTTLE_NOT_IN_RANGE, - DSHOT_ERROR_PERCENT_NOT_IN_RANGE, - DSHOT_ERROR_COMMAND_NOT_VALID, - DSHOT_ERROR_BIDIR_NOT_ENABLED, - DSHOT_ERROR_TELEMETRY_FAILED, - DSHOT_ERROR_INVALID_MAGNET_COUNT, - DSHOT_ERROR_INVALID_COMMAND, - DSHOT_ERROR_TIMING_CORRECTION, - DSHOT_ERROR_INIT_FAILED, - DSHOT_ERROR_INIT_SUCCESS, - DSHOT_ERROR_TX_INIT_SUCCESS, - DSHOT_ERROR_RX_INIT_SUCCESS, - DSHOT_ERROR_ENCODER_INIT_SUCCESS, - DSHOT_ERROR_ENCODING_SUCCESS, - DSHOT_ERROR_TRANSMISSION_SUCCESS, - DSHOT_ERROR_TELEMETRY_SUCCESS, - DSHOT_ERROR_COMMAND_SUCCESS + DSHOT_NONE = 0, + DSHOT_UNKNOWN, + DSHOT_TX_INIT_FAILED, + DSHOT_RX_INIT_FAILED, + DSHOT_ENCODER_INIT_FAILED, + DSHOT_CALLBACK_REGISTERING_FAILED, + DSHOT_RECEIVER_FAILED, + DSHOT_TRANSMISSION_FAILED, + DSHOT_THROTTLE_NOT_IN_RANGE, + DSHOT_PERCENT_NOT_IN_RANGE, + DSHOT_COMMAND_NOT_VALID, + DSHOT_BIDIR_NOT_ENABLED, + DSHOT_TELEMETRY_FAILED, + DSHOT_INVALID_MAGNET_COUNT, + DSHOT_INVALID_COMMAND, + DSHOT_TIMING_CORRECTION, + DSHOT_INIT_FAILED, + DSHOT_INIT_SUCCESS, + DSHOT_TX_INIT_SUCCESS, + DSHOT_RX_INIT_SUCCESS, + DSHOT_ENCODER_INIT_SUCCESS, + DSHOT_ENCODING_SUCCESS, + DSHOT_TRANSMISSION_SUCCESS, + DSHOT_TELEMETRY_SUCCESS, + DSHOT_COMMAND_SUCCESS }; // 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. + char *result_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; @@ -168,115 +168,36 @@ const dshot_timing_us_t DSHOT_TIMING_US[] = { {0.83, 0.67}}; // DSHOT1200 // Error Messages -const char *const NONE = ""; -const char *const UNKNOWN_ERROR = "Unknown Error!"; -const char *const INIT_SUCCESS = "SignalGeneratorRMT initialized successfully"; -const char *const INIT_FAILED = "SignalGeneratorRMT init failed!"; -const char *const TX_INIT_SUCCESS = "TX RMT channel initialized successfully"; -const char *const TX_INIT_FAILED = "TX RMT channel init failed!"; -const char *const RX_INIT_SUCCESS = "RX RMT channel initialized successfully"; -const char *const RX_INIT_FAILED = "RX RMT channel init failed!"; -const char *const ENCODER_INIT_SUCCESS = "RMT encoder initialized successfully"; -const char *const ENCODER_INIT_FAILED = "RMT encoder init failed!"; -const char *const ENCODING_SUCCESS = "Packet encoded successfully"; -const char *const TRANSMISSION_SUCCESS = "Transmission successfully"; -const char *const TRANSMISSION_FAILED = "Transmission failed!"; -const char *const RECEIVER_FAILED = "RMT receiver failed!"; -const char *const THROTTLE_NOT_IN_RANGE = "Throttle not in range! (48 - 2047)"; -const char *const PERCENT_NOT_IN_RANGE = "Percent not in range! (0.0 - 100.0)"; -const char *const COMMAND_NOT_VALID = "Command not valid! (0 - 47)"; -const char *const BIDIR_NOT_ENABLED = "Bidirectional DShot not enabled!"; -const char *const TELEMETRY_SUCCESS = "Valid Telemetric Frame received!"; -const char *const TELEMETRY_FAILED = "No valid Telemetric Frame received!"; -const char *const INVALID_MAGNET_COUNT = "Invalid motor magnet count!"; -const char *const TIMING_CORRECTION = "Timing correction!"; -const char *const CALLBACK_REGISTERING_FAILED = "RMT RX Callback registering failed!"; -const char *const INVALID_COMMAND = "Invalid command!"; -const char *const COMMAND_SUCCESS = "DShot command sent successfully"; +static constexpr char *NONE = ""; +static constexpr char *UNKNOWN_ERROR = "Unknown Error!"; +static constexpr char *INIT_SUCCESS = "SignalGeneratorRMT initialized successfully"; +static constexpr char *INIT_FAILED = "SignalGeneratorRMT init failed!"; +static constexpr char *TX_INIT_SUCCESS = "TX RMT channel initialized successfully"; +static constexpr char *TX_INIT_FAILED = "TX RMT channel init failed!"; +static constexpr char *RX_INIT_SUCCESS = "RX RMT channel initialized successfully"; +static constexpr char *RX_INIT_FAILED = "RX RMT channel init failed!"; +static constexpr char *ENCODER_INIT_SUCCESS = "RMT encoder initialized successfully"; +static constexpr char *ENCODER_INIT_FAILED = "RMT encoder init failed!"; +static constexpr char *ENCODING_SUCCESS = "Packet encoded successfully"; +static constexpr char *TRANSMISSION_SUCCESS = "Transmission successfully"; +static constexpr char *TRANSMISSION_FAILED = "Transmission failed!"; +static constexpr char *RECEIVER_FAILED = "RMT receiver failed!"; +static constexpr char *THROTTLE_NOT_IN_RANGE = "Throttle not in range! (48 - 2047)"; +static constexpr char *PERCENT_NOT_IN_RANGE = "Percent not in range! (0.0 - 100.0)"; +static constexpr char *COMMAND_NOT_VALID = "Command not valid! (0 - 47)"; +static constexpr char *BIDIR_NOT_ENABLED = "Bidirectional DShot not enabled!"; +static constexpr char *TELEMETRY_SUCCESS = "Valid Telemetric Frame received!"; +static constexpr char *TELEMETRY_FAILED = "No valid Telemetric Frame received!"; +static constexpr char *INVALID_MAGNET_COUNT = "Invalid motor magnet count!"; +static constexpr char *TIMING_CORRECTION = "Timing correction!"; +static constexpr char *CALLBACK_REGISTERING_FAILED = "RMT RX Callback registering failed!"; +static constexpr char *INVALID_COMMAND = "Invalid command!"; +static constexpr char *COMMAND_SUCCESS = "DShot command sent successfully"; -// Helper Functions +// Helpers inline void printDShotResult(dshot_result_t &result, Stream &output = Serial) { - const char *msg_str; - switch (result.error_code) - { - case dshot_msg_code_t::DSHOT_ERROR_NONE: - msg_str = "None"; - break; - case dshot_msg_code_t::DSHOT_ERROR_UNKNOWN: - msg_str = "Unknown Error!"; - break; - case dshot_msg_code_t::DSHOT_ERROR_TX_INIT_FAILED: - msg_str = "TX RMT channel init failed!"; - break; - case dshot_msg_code_t::DSHOT_ERROR_RX_INIT_FAILED: - msg_str = "RX RMT channel init failed!"; - break; - case dshot_msg_code_t::DSHOT_ERROR_ENCODER_INIT_FAILED: - msg_str = "RMT encoder init failed!"; - break; - case dshot_msg_code_t::DSHOT_ERROR_CALLBACK_REGISTERING_FAILED: - msg_str = "RMT RX Callback registering failed!"; - break; - case dshot_msg_code_t::DSHOT_ERROR_RECEIVER_FAILED: - msg_str = "RMT receiver failed!"; - break; - case dshot_msg_code_t::DSHOT_ERROR_TRANSMISSION_FAILED: - msg_str = "Transmission failed!"; - break; - case dshot_msg_code_t::DSHOT_ERROR_THROTTLE_NOT_IN_RANGE: - msg_str = "Throttle not in range! (48 - 2047)"; - break; - case dshot_msg_code_t::DSHOT_ERROR_PERCENT_NOT_IN_RANGE: - msg_str = "Percent not in range! (0.0 - 100.0)"; - break; - case dshot_msg_code_t::DSHOT_ERROR_COMMAND_NOT_VALID: - msg_str = "Command not valid! (0 - 47)"; - break; - case dshot_msg_code_t::DSHOT_ERROR_BIDIR_NOT_ENABLED: - msg_str = "Bidirectional DShot not enabled!"; - break; - case dshot_msg_code_t::DSHOT_ERROR_TELEMETRY_FAILED: - msg_str = "No valid Telemetric Frame received!"; - break; - case dshot_msg_code_t::DSHOT_ERROR_INVALID_MAGNET_COUNT: - msg_str = "Invalid motor magnet count!"; - break; - case dshot_msg_code_t::DSHOT_ERROR_INVALID_COMMAND: - msg_str = "Invalid command!"; - break; - case dshot_msg_code_t::DSHOT_ERROR_TIMING_CORRECTION: - msg_str = "Timing correction!"; - break; - case dshot_msg_code_t::DSHOT_ERROR_INIT_FAILED: - msg_str = "SignalGeneratorRMT init failed!"; - break; - case dshot_msg_code_t::DSHOT_ERROR_INIT_SUCCESS: - msg_str = "SignalGeneratorRMT initialized successfully"; - break; - case dshot_msg_code_t::DSHOT_ERROR_TX_INIT_SUCCESS: - msg_str = "TX RMT channel initialized successfully"; - break; - case dshot_msg_code_t::DSHOT_ERROR_RX_INIT_SUCCESS: - msg_str = "RX RMT channel initialized successfully"; - break; - case dshot_msg_code_t::DSHOT_ERROR_ENCODING_SUCCESS: - msg_str = "Packet encoded successfully"; - break; - case dshot_msg_code_t::DSHOT_ERROR_TRANSMISSION_SUCCESS: - msg_str = "Transmission successfully"; - break; - case dshot_msg_code_t::DSHOT_ERROR_TELEMETRY_SUCCESS: - msg_str = "Valid Telemetric Frame received!"; - break; - case dshot_msg_code_t::DSHOT_ERROR_COMMAND_SUCCESS: - msg_str = "DShot command sent successfully"; - break; - default: - msg_str = "Unhandled Error Code!"; - break; - } - output.printf("Status: %s - %s", result.success ? "SUCCESS" : "FAILED", msg_str); + output.printf("Status: %s - %s", result.success ? "SUCCESS" : "FAILED", result.result_code); // Print telemetry data if available if (result.success && (result.erpm > 0 || result.motor_rpm > 0)) @@ -285,4 +206,4 @@ inline void printDShotResult(dshot_result_t &result, Stream &output = Serial) } output.println(); -} \ No newline at end of file +}