release 0.9.0
This commit is contained in:
parent
6e3006c4c8
commit
4a2d3f0b9a
|
|
@ -46,7 +46,7 @@ jobs:
|
|||
~/.arduino15/packages
|
||||
~/.arduino15/cache
|
||||
~/Arduino/libraries
|
||||
key: linux-arduino-esp32-v2-${{ hashFiles('**/library.properties') }}
|
||||
key: linux-arduino-esp32-v2-v3
|
||||
|
||||
- name: Install Dependencies
|
||||
if: steps.cache-arduino.outputs.cache-hit != 'true'
|
||||
|
|
@ -83,7 +83,7 @@ jobs:
|
|||
~/.arduino15/packages
|
||||
~/.arduino15/cache
|
||||
~/Arduino/libraries
|
||||
key: linux-arduino-esp32-v2-${{ hashFiles('**/library.properties') }}
|
||||
key: linux-arduino-esp32-v2-v3
|
||||
|
||||
- name: Run Arduino Lint
|
||||
uses: arduino/arduino-lint-action@v2
|
||||
|
|
@ -125,7 +125,7 @@ jobs:
|
|||
~/.arduino15/packages
|
||||
~/.arduino15/cache
|
||||
~/Arduino/libraries
|
||||
key: linux-arduino-esp32-v2-${{ hashFiles('**/library.properties') }}
|
||||
key: linux-arduino-esp32-v2-v3
|
||||
|
||||
- name: Compile Sketch
|
||||
run: arduino-cli compile --fqbn esp32:esp32:esp32 --library ${{ github.workspace }} "${{ matrix.sketch }}"
|
||||
|
|
|
|||
|
|
@ -114,9 +114,9 @@ The main class is `DShotRMT`. Here are the most important methods:
|
|||
- `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(dshotCommands_e command)`: Sends a DShot command (0-47) to the ESC. Automatically handles repetitions and delays for specific commands (e.g., `DSHOT_CMD_SAVE_SETTINGS`).
|
||||
- `sendCommand(dshotCommands_e command, uint16_t repeat_count, uint16_t delay_us)`: Sends a DShot command (0-47) to the ESC with a specified repeat count and delay. This is a blocking function.
|
||||
- `sendCommand(uint16_t command_value)`: Sends a DShot command (0-47) to the ESC by accepting an integer value. It validates the input and then calls `sendCommand(dshotCommands_e command)`.
|
||||
- `sendCommand(dshotCommands_e command)`: Sends a DShot command to the ESC. Automatically handles repetitions and delays for specific commands (e.g., `DSHOT_CMD_SAVE_SETTINGS`).
|
||||
- `sendCommand(dshotCommands_e command, uint16_t repeat_count, uint16_t delay_us)`: Sends a DShot command to the ESC with a specified repeat count and delay. This is a blocking function.
|
||||
- `sendCommand(uint16_t command_value)`: Sends a DShot command to the ESC by accepting an integer value. It validates the input and then calls `sendCommand(dshotCommands_e command)`.
|
||||
- `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.
|
||||
|
|
|
|||
|
|
@ -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, DEFAULT_MOTOR_MAGNET_COUNT);
|
||||
DShotRMT motor01(MOTOR01_PIN, DSHOT_MODE, IS_BIDIRECTIONAL);
|
||||
|
||||
//
|
||||
void setup()
|
||||
|
|
|
|||
|
|
@ -33,21 +33,17 @@ DShotRMT::~DShotRMT()
|
|||
// Cleanup TX channel
|
||||
if (_rmt_tx_channel)
|
||||
{
|
||||
if (rmt_disable(_rmt_tx_channel) == DSHOT_OK)
|
||||
{
|
||||
rmt_del_channel(_rmt_tx_channel);
|
||||
_rmt_tx_channel = nullptr;
|
||||
}
|
||||
rmt_disable(_rmt_tx_channel);
|
||||
rmt_del_channel(_rmt_tx_channel);
|
||||
_rmt_tx_channel = nullptr;
|
||||
}
|
||||
|
||||
// Cleanup RX channel
|
||||
if (_rmt_rx_channel)
|
||||
{
|
||||
if (rmt_disable(_rmt_rx_channel) == DSHOT_OK)
|
||||
{
|
||||
rmt_del_channel(_rmt_rx_channel);
|
||||
_rmt_rx_channel = nullptr;
|
||||
}
|
||||
rmt_disable(_rmt_rx_channel);
|
||||
rmt_del_channel(_rmt_rx_channel);
|
||||
_rmt_rx_channel = nullptr;
|
||||
}
|
||||
|
||||
// Cleanup encoder
|
||||
|
|
@ -65,6 +61,7 @@ dshot_result_t DShotRMT::begin()
|
|||
|
||||
if (!result.success)
|
||||
{
|
||||
_cleanupRmtResources(); // Clean up any allocated resources on failure
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -73,10 +70,7 @@ dshot_result_t DShotRMT::begin()
|
|||
result = init_rmt_rx_channel(_gpio, &_rmt_rx_channel, &_rx_event_callbacks, this);
|
||||
if (!result.success)
|
||||
{
|
||||
// Cleanup previously allocated TX channel on failure
|
||||
rmt_disable(_rmt_tx_channel);
|
||||
rmt_del_channel(_rmt_tx_channel);
|
||||
_rmt_tx_channel = nullptr;
|
||||
_cleanupRmtResources(); // Clean up any allocated resources on failure
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -85,17 +79,7 @@ dshot_result_t DShotRMT::begin()
|
|||
|
||||
if (!result.success)
|
||||
{
|
||||
// Cleanup previously allocated channels on failure
|
||||
rmt_disable(_rmt_tx_channel);
|
||||
rmt_del_channel(_rmt_tx_channel);
|
||||
_rmt_tx_channel = nullptr;
|
||||
|
||||
if (_rmt_rx_channel)
|
||||
{
|
||||
rmt_disable(_rmt_rx_channel);
|
||||
rmt_del_channel(_rmt_rx_channel);
|
||||
_rmt_rx_channel = nullptr;
|
||||
}
|
||||
_cleanupRmtResources(); // Clean up any allocated resources on failure
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -260,10 +244,10 @@ dshot_result_t DShotRMT::saveESCSettings()
|
|||
// Simple check
|
||||
bool DShotRMT::_isValidCommand(dshotCommands_e command) const
|
||||
{
|
||||
return (command >= dshotCommands_e::DSHOT_CMD_MOTOR_STOP && command <= dshotCommands_e::DSHOT_CMD_MAX);
|
||||
return (command >= dshotCommands_e::DSHOT_CMD_MOTOR_STOP && command <= DSHOT_CMD_MAX);
|
||||
}
|
||||
|
||||
//
|
||||
// Executes a single DShot command by building and sending a DShot frame.
|
||||
dshot_result_t DShotRMT::_executeCommand(dshotCommands_e command)
|
||||
{
|
||||
uint64_t start_time = esp_timer_get_time();
|
||||
|
|
@ -314,18 +298,18 @@ uint16_t DShotRMT::_calculateCRC(const uint16_t &data) const
|
|||
|
||||
void DShotRMT::_preCalculateRMTTicks()
|
||||
{
|
||||
// Pre-calculate all timing values in RMT ticks to save CPU cycles later
|
||||
// Pre-calculate all timing values in RMT ticks to save CPU cycles later.
|
||||
_rmt_ticks.bit_length_ticks = static_cast<uint16_t>(_dshot_timing.bit_length_us * RMT_TICKS_PER_US);
|
||||
_rmt_ticks.t1h_ticks = static_cast<uint16_t>(_dshot_timing.t1h_lenght_us * RMT_TICKS_PER_US);
|
||||
_rmt_ticks.t0h_ticks = _rmt_ticks.t1h_ticks >> 1; // High time for a 1 is always double of 0
|
||||
_rmt_ticks.t0h_ticks = _rmt_ticks.t1h_ticks >> 1; // High time for a '0' bit is half of a '1' bit.
|
||||
_rmt_ticks.t1l_ticks = _rmt_ticks.bit_length_ticks - _rmt_ticks.t1h_ticks;
|
||||
_rmt_ticks.t0l_ticks = _rmt_ticks.bit_length_ticks - _rmt_ticks.t0h_ticks;
|
||||
|
||||
// Calculate the minimum time required between frames
|
||||
// Pause between frames is frame time in us, some padding and about 30 us is added by hardware
|
||||
// Calculate the minimum time required between frames.
|
||||
// Pause between frames is frame time in us, some padding and about 30 us is added by hardware.
|
||||
_frame_timer_us = (static_cast<uint64_t>(_dshot_timing.bit_length_us * DSHOT_BITS_PER_FRAME) << 1) + DSHOT_PADDING_US;
|
||||
|
||||
// For bidirectional, double up
|
||||
// For bidirectional, double up.
|
||||
if (_is_bidirectional)
|
||||
{
|
||||
_frame_timer_us = (_frame_timer_us << 1);
|
||||
|
|
@ -365,12 +349,12 @@ dshot_result_t DShotRMT::_sendDShotFrame(const dshot_packet_t &packet)
|
|||
|
||||
// This function needs to be fast, as it generates the RMT symbols just before sending
|
||||
|
||||
// Placed in IRAM for high performance, as it's called from an ISR context
|
||||
// Placed in IRAM for high performance, as it's called from an ISR context.
|
||||
uint16_t IRAM_ATTR DShotRMT::_decodeDShotFrame(const rmt_symbol_word_t *symbols) const
|
||||
{
|
||||
uint32_t gcr_value = 0;
|
||||
|
||||
// Step 1: Decode RMT symbols into a 21-bit GCR (Group Code Recording) value.
|
||||
// Decode RMT symbols into a 21-bit GCR (Group Code Recording) value.
|
||||
// The ESC sends back a signal where the duration determines the bit value.
|
||||
for (size_t i = 0; i < GCR_BITS_PER_FRAME; ++i)
|
||||
{
|
||||
|
|
@ -378,23 +362,23 @@ uint16_t IRAM_ATTR DShotRMT::_decodeDShotFrame(const rmt_symbol_word_t *symbols)
|
|||
gcr_value = (gcr_value << 1) | bit_is_one;
|
||||
}
|
||||
|
||||
// Step 2: Perform GCR decoding (GCR = Value ^ (Value >> 1))
|
||||
// Perform GCR decoding (GCR = Value ^ (Value >> 1)).
|
||||
uint32_t decoded_frame = gcr_value ^ (gcr_value >> 1);
|
||||
|
||||
// Step 3: Extract the 16-bit DShot frame from the decoded data
|
||||
// Extract the 16-bit DShot frame from the decoded data.
|
||||
uint16_t data_and_crc = (decoded_frame & DSHOT_FULL_PACKET);
|
||||
|
||||
// Step 4: Extract data and CRC from the 16-bit frame
|
||||
// Extract data and CRC from the 16-bit frame.
|
||||
uint16_t received_data = data_and_crc >> DSHOT_CRC_BIT_SHIFT;
|
||||
uint16_t received_crc = data_and_crc & DSHOT_CRC_MASK;
|
||||
|
||||
// Step 5: A valid response must have the telemetry request bit set to 1. This is a sanity check.
|
||||
// A valid response must have the telemetry request bit set to 1. This is a sanity check.
|
||||
if (!((received_data >> DSHOT_TELEMETRY_BIT_POSITION) & 1))
|
||||
{
|
||||
return DSHOT_NULL_PACKET;
|
||||
}
|
||||
|
||||
// Step 6: Calculate and validate CRC
|
||||
// Calculate and validate CRC.
|
||||
uint16_t calculated_crc = _calculateCRC(received_data);
|
||||
if (received_crc != calculated_crc)
|
||||
{
|
||||
|
|
@ -440,3 +424,26 @@ bool IRAM_ATTR DShotRMT::_on_rx_done(rmt_channel_handle_t rmt_rx_channel, const
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
void DShotRMT::_cleanupRmtResources()
|
||||
{
|
||||
if (_rmt_tx_channel)
|
||||
{
|
||||
rmt_disable(_rmt_tx_channel);
|
||||
rmt_del_channel(_rmt_tx_channel);
|
||||
_rmt_tx_channel = nullptr;
|
||||
}
|
||||
|
||||
if (_rmt_rx_channel)
|
||||
{
|
||||
rmt_disable(_rmt_rx_channel);
|
||||
rmt_del_channel(_rmt_rx_channel);
|
||||
_rmt_rx_channel = nullptr;
|
||||
}
|
||||
|
||||
if (_dshot_encoder)
|
||||
{
|
||||
rmt_del_encoder(_dshot_encoder);
|
||||
_dshot_encoder = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
106
src/DShotRMT.h
106
src/DShotRMT.h
|
|
@ -18,18 +18,19 @@
|
|||
#include "dshot_definitions.h"
|
||||
#include "dshot_init.h"
|
||||
|
||||
// Forward declaration for the RMT receive callback
|
||||
class DShotRMT;
|
||||
void IRAM_ATTR rmt_rx_done_callback(rmt_channel_handle_t rx_chan, const rmt_rx_done_event_data_t *edata, void *user_data);
|
||||
|
||||
// DShot Protocol Constants
|
||||
static constexpr auto DSHOT_THROTTLE_FAILSAFE = 0;
|
||||
static constexpr auto DSHOT_THROTTLE_MIN = 48;
|
||||
static constexpr auto DSHOT_BITS_PER_FRAME = 16;
|
||||
static constexpr auto DEFAULT_MOTOR_MAGNET_COUNT = 14;
|
||||
|
||||
//
|
||||
// DShotRMT class for generating DShot signals and receiving telemetry.
|
||||
class DShotRMT
|
||||
{
|
||||
public:
|
||||
// Constructor with GPIO number
|
||||
DShotRMT(gpio_num_t gpio, dshot_mode_t mode, bool is_bidirectional = false, uint16_t magnet_count = DEFAULT_MOTOR_MAGNET_COUNT);
|
||||
// Constructor for DShotRMT.
|
||||
DShotRMT(gpio_num_t gpio, dshot_mode_t mode = DSHOT300, bool is_bidirectional = false, uint16_t magnet_count = DEFAULT_MOTOR_MAGNET_COUNT);
|
||||
|
||||
// Constructor using pin number
|
||||
DShotRMT(uint16_t pin_nr, dshot_mode_t mode, bool is_bidirectional = false, uint16_t magnet_count = DEFAULT_MOTOR_MAGNET_COUNT);
|
||||
|
|
@ -40,28 +41,28 @@ public:
|
|||
// Initialize DShotRMT
|
||||
dshot_result_t begin();
|
||||
|
||||
// Send throttle value
|
||||
// Sends a raw throttle value to the ESC.
|
||||
dshot_result_t sendThrottle(uint16_t throttle);
|
||||
|
||||
// Send throttle value as a percentage
|
||||
// Sends a throttle value as a percentage to the ESC.
|
||||
dshot_result_t sendThrottlePercent(float percent);
|
||||
|
||||
// Sends a DShot command (0-47) to the ESC by accepting an integer value.
|
||||
// Sends a DShot command to the ESC by accepting an integer value.
|
||||
dshot_result_t sendCommand(uint16_t command_value);
|
||||
|
||||
// Sends a DShot command (0-47) to the ESC.
|
||||
// Sends a DShot command to the ESC.
|
||||
dshot_result_t sendCommand(dshotCommands_e command);
|
||||
|
||||
// Sends a DShot command (0-47) to the ESC with a specified repeat count and delay.
|
||||
// Sends a DShot command to the ESC with a specified repeat count and delay.
|
||||
dshot_result_t sendCommand(dshotCommands_e command, uint16_t repeat_count, uint16_t delay_us);
|
||||
|
||||
// Get telemetry data
|
||||
// Retrieves telemetry data from the ESC.
|
||||
dshot_result_t getTelemetry();
|
||||
|
||||
// Reverse motor direction directly
|
||||
// Sets the motor spin direction.
|
||||
dshot_result_t setMotorSpinDirection(bool reversed);
|
||||
|
||||
// Use with caution
|
||||
// Sends a command to the ESC to save its current settings.
|
||||
dshot_result_t saveESCSettings();
|
||||
|
||||
// Getters for DShot info
|
||||
|
|
@ -71,50 +72,53 @@ public:
|
|||
uint16_t getEncodedFrameValue() const { return _encoded_frame_value; }
|
||||
|
||||
private:
|
||||
// Configuration
|
||||
gpio_num_t _gpio;
|
||||
dshot_mode_t _mode;
|
||||
bool _is_bidirectional;
|
||||
uint16_t _motor_magnet_count;
|
||||
dshot_timing_us_t _dshot_timing;
|
||||
static bool IRAM_ATTR _on_rx_done(rmt_channel_handle_t rmt_rx_channel, const rmt_rx_done_event_data_t *edata, void *user_data);
|
||||
|
||||
// RMT Handles & Config
|
||||
rmt_channel_handle_t _rmt_tx_channel = nullptr;
|
||||
rmt_channel_handle_t _rmt_rx_channel = nullptr;
|
||||
rmt_encoder_handle_t _dshot_encoder = nullptr;
|
||||
rmt_ticks_t _rmt_ticks;
|
||||
uint16_t _pulse_level = 1; // Default to high
|
||||
uint16_t _idle_level = 0; // Default to low
|
||||
// DShot Configuration Parameters
|
||||
gpio_num_t _gpio; // GPIO pin used for DShot communication
|
||||
dshot_mode_t _mode; // DShot mode (e.g., DSHOT300, DSHOT600)
|
||||
bool _is_bidirectional; // True if bidirectional DShot is enabled
|
||||
uint16_t _motor_magnet_count; // Number of magnets in the motor for RPM calculation
|
||||
dshot_timing_us_t _dshot_timing; // DShot timing parameters in microseconds
|
||||
|
||||
// Timing & State
|
||||
uint64_t _last_transmission_time_us = 0;
|
||||
uint64_t _frame_timer_us = 0;
|
||||
uint16_t _last_throttle = 0;
|
||||
dshot_packet_t _packet;
|
||||
uint16_t _encoded_frame_value = 0;
|
||||
uint64_t _last_command_timestamp = 0;
|
||||
// RMT Hardware Handles and Configuration
|
||||
rmt_channel_handle_t _rmt_tx_channel = nullptr; // RMT transmit channel handle
|
||||
rmt_channel_handle_t _rmt_rx_channel = nullptr; // RMT receive channel handle
|
||||
rmt_encoder_handle_t _dshot_encoder = nullptr; // DShot RMT encoder handle
|
||||
rmt_ticks_t _rmt_ticks; // Pre-calculated RMT timing ticks
|
||||
uint16_t _pulse_level = 1; // Output level for a pulse (typically high)
|
||||
uint16_t _idle_level = 0; // Output level for idle (typically low)
|
||||
|
||||
// Telemetry
|
||||
std::atomic<uint16_t> _last_erpm_atomic = 0;
|
||||
std::atomic<bool> _telemetry_ready_flag_atomic = false;
|
||||
// DShot Frame Timing and State Variables
|
||||
uint64_t _last_transmission_time_us = 0; // Timestamp of the last DShot frame transmission
|
||||
uint64_t _frame_timer_us = 0; // Minimum time required between DShot frames
|
||||
uint16_t _last_throttle = 0; // Last transmitted throttle value
|
||||
dshot_packet_t _packet; // Current DShot packet being processed
|
||||
uint16_t _encoded_frame_value = 0; // Last encoded 16-bit DShot frame value
|
||||
uint64_t _last_command_timestamp = 0; // Timestamp of the last command sent
|
||||
|
||||
// Telemetry Related Variables
|
||||
std::atomic<uint16_t> _last_erpm_atomic = 0; // Atomically stored last received eRPM value
|
||||
std::atomic<bool> _telemetry_ready_flag_atomic = false; // Atomically stored flag indicating new telemetry data
|
||||
rmt_rx_event_callbacks_t _rx_event_callbacks = {
|
||||
// RMT receive event callbacks
|
||||
.on_recv_done = _on_rx_done,
|
||||
};
|
||||
|
||||
// Private helper functions
|
||||
bool _isValidCommand(dshotCommands_e command) const;
|
||||
dshot_result_t _executeCommand(dshotCommands_e command);
|
||||
dshot_packet_t _buildDShotPacket(const uint16_t &value) const;
|
||||
uint16_t _buildDShotFrameValue(const dshot_packet_t &packet) const;
|
||||
uint16_t _calculateCRC(const uint16_t &data) const;
|
||||
void _preCalculateRMTTicks();
|
||||
dshot_result_t _sendDShotFrame(const dshot_packet_t &packet);
|
||||
uint16_t IRAM_ATTR _decodeDShotFrame(const rmt_symbol_word_t *symbols) const;
|
||||
bool IRAM_ATTR _isFrameIntervalElapsed() const;
|
||||
void _recordFrameTransmissionTime();
|
||||
// Private Helper Functions for DShot Protocol Logic
|
||||
bool _isValidCommand(dshotCommands_e command) const; // Checks if a given DShot command is valid
|
||||
dshot_result_t _executeCommand(dshotCommands_e command); // Executes a single DShot command
|
||||
dshot_packet_t _buildDShotPacket(const uint16_t &value) const; // Builds a DShot packet from a value (throttle or command)
|
||||
uint16_t _buildDShotFrameValue(const dshot_packet_t &packet) const; // Combines packet data into a 16-bit DShot frame value
|
||||
uint16_t _calculateCRC(const uint16_t &data) const; // Calculates the 4-bit CRC for a DShot frame
|
||||
void _preCalculateRMTTicks(); // Pre-calculates RMT timing ticks for the selected DShot mode
|
||||
dshot_result_t _sendDShotFrame(const dshot_packet_t &packet); // Sends a DShot frame via RMT TX channel
|
||||
uint16_t IRAM_ATTR _decodeDShotFrame(const rmt_symbol_word_t *symbols) const; // Decodes a received RMT symbol array into an eRPM value
|
||||
bool IRAM_ATTR _isFrameIntervalElapsed() const; // Checks if enough time has passed since the last frame transmission
|
||||
void _recordFrameTransmissionTime(); // Records the current time as the last frame transmission time
|
||||
|
||||
// Static Callback Functions
|
||||
static bool IRAM_ATTR _on_rx_done(rmt_channel_handle_t rmt_rx_channel, const rmt_rx_done_event_data_t *edata, void *user_data);
|
||||
// Static Callback Function for RMT RX Events
|
||||
void _cleanupRmtResources();
|
||||
};
|
||||
|
||||
#include "dshot_utils.h" // Include for helper functions
|
||||
#include "dshot_utils.h" // Include for helper functions
|
||||
|
|
|
|||
|
|
@ -11,6 +11,19 @@
|
|||
#include <cstdint>
|
||||
#include <driver/rmt_common.h>
|
||||
|
||||
// DShot protocol definitions
|
||||
static constexpr uint16_t DSHOT_FRAME_LENGTH = 16; // 11 throttle bits + 1 telemetry bit + 4 CRC bits
|
||||
static constexpr uint16_t DSHOT_BITS_PER_FRAME = 16;
|
||||
static constexpr uint16_t DSHOT_THROTTLE_MAX = 2047; // Maximum throttle value (0-2047)
|
||||
static constexpr uint16_t DSHOT_THROTTLE_MIN = 48; // Minimum throttle value for motor spin
|
||||
static constexpr uint16_t DSHOT_CMD_MIN = 0; // Minimum command value
|
||||
static constexpr uint16_t DSHOT_CMD_MAX = 47; // Maximum command value
|
||||
static constexpr uint16_t DSHOT_TELEMETRY_BIT_MASK = 0x0800; // Bit mask for telemetry request bit (11th bit)
|
||||
static constexpr uint16_t DSHOT_CRC_MASK = 0x000F; // Bit mask for CRC bits
|
||||
|
||||
// Default motor magnet count for RPM calculation
|
||||
static constexpr uint16_t DEFAULT_MOTOR_MAGNET_COUNT = 14;
|
||||
|
||||
// Defines the available DShot communication speeds.
|
||||
enum dshot_mode_t
|
||||
{
|
||||
|
|
@ -114,8 +127,7 @@ enum dshotCommands_e
|
|||
DSHOT_CMD_LED2_OFF,
|
||||
DSHOT_CMD_LED3_OFF,
|
||||
DSHOT_CMD_AUDIO_STREAM_MODE_ON_OFF = 30,
|
||||
DSHOT_CMD_SILENT_MODE_ON_OFF = 31,
|
||||
DSHOT_CMD_MAX = 47
|
||||
DSHOT_CMD_SILENT_MODE_ON_OFF = 31
|
||||
};
|
||||
|
||||
// Custom status codes
|
||||
|
|
@ -125,7 +137,6 @@ static constexpr int DSHOT_ERROR = 1;
|
|||
// Configuration Constants
|
||||
static constexpr auto DSHOT_NULL_PACKET = 0b0000000000000000;
|
||||
static constexpr auto DSHOT_FULL_PACKET = 0b1111111111111111;
|
||||
static constexpr auto DSHOT_CRC_MASK = 0b0000000000001111;
|
||||
static constexpr auto DSHOT_CLOCK_SRC_DEFAULT = RMT_CLK_SRC_DEFAULT;
|
||||
static constexpr auto DSHOT_RMT_RESOLUTION = 8000000; // 8 MHz resolution
|
||||
static constexpr auto RMT_TICKS_PER_US = DSHOT_RMT_RESOLUTION / 1000000; // RMT Ticks per microsecond
|
||||
|
|
@ -137,7 +148,6 @@ static constexpr auto GCR_BITS_PER_FRAME = 21; // GCR bits in a DShot answer fra
|
|||
static constexpr auto POLE_PAIRS_MIN = 1;
|
||||
static constexpr auto MAGNETS_PER_POLE_PAIR = 2;
|
||||
static constexpr auto NO_DSHOT_TELEMETRY = 0;
|
||||
static constexpr auto DSHOT_THROTTLE_MAX = 2047;
|
||||
static constexpr auto DSHOT_PULSE_MIN_NS = 800; // 0.8us minimum pulse
|
||||
static constexpr auto DSHOT_PULSE_MAX_NS = 8000; // 8.0us maximum pulse
|
||||
static constexpr auto DSHOT_TELEMETRY_INVALID = DSHOT_THROTTLE_MAX;
|
||||
|
|
@ -156,5 +166,5 @@ const dshot_timing_us_t DSHOT_TIMING_US[] = {
|
|||
{6.67, 5.00}, // DSHOT150
|
||||
{3.33, 2.50}, // DSHOT300
|
||||
{1.67, 1.25}, // DSHOT600
|
||||
{0.83, 0.67} // DSHOT1200
|
||||
};
|
||||
{0.83, 0.67} // DSHOT1200
|
||||
};
|
||||
|
|
@ -41,7 +41,7 @@ static constexpr char INVALID_COMMAND[] = "Invalid command!";
|
|||
static constexpr char COMMAND_SUCCESS[] = "DShot command sent successfully";
|
||||
|
||||
// Helper to get result code string
|
||||
inline const char *_get_result_code_str(dshot_msg_code_t code)
|
||||
inline const char *get_result_code_str(dshot_msg_code_t code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
|
|
@ -103,7 +103,7 @@ inline const char *_get_result_code_str(dshot_msg_code_t code)
|
|||
// Helper to quick print DShot result codes
|
||||
inline void printDShotResult(dshot_result_t &result, Stream &output = Serial)
|
||||
{
|
||||
output.printf("Status: %s - %s", result.success ? "SUCCESS" : "FAILED", _get_result_code_str(result.result_code));
|
||||
output.printf("Status: %s - %s", result.success ? "SUCCESS" : "FAILED", get_result_code_str(result.result_code));
|
||||
|
||||
// Print telemetry data if available
|
||||
if (result.success && (result.erpm > 0 || result.motor_rpm > 0))
|
||||
|
|
|
|||
Loading…
Reference in New Issue