...break down result struct

This commit is contained in:
Wastl Kraus 2025-09-27 23:17:43 +02:00
parent 9dc91a01c4
commit 3b84df295f
4 changed files with 89 additions and 168 deletions

View File

@ -7,6 +7,9 @@
"settings": {
"files.associations": {
"string": "cpp"
}
},
"arduino.logLevel": "verbose",
"arduino.path": "/usr/bin/arduino-cli",
"arduino.useArduinoCli": true
}
}

View File

@ -7,7 +7,7 @@
*/
#include <Arduino.h>
#include "DShotRMT.h"
#include <DShotRMT.h>
// 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()

View File

@ -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<uint16_t>(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<uint16_t>(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());
}
}

View File

@ -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();
}
}