parent
dbfe3922f0
commit
95c9100ecb
95
DShotRMT.cpp
95
DShotRMT.cpp
|
|
@ -19,8 +19,7 @@ const dshot_timing_t DSHOT_TIMINGS[] = {
|
||||||
|
|
||||||
//
|
//
|
||||||
DShotRMT::DShotRMT(gpio_num_t gpio, dshot_mode_t mode, bool is_bidirectional)
|
DShotRMT::DShotRMT(gpio_num_t gpio, dshot_mode_t mode, bool is_bidirectional)
|
||||||
: _gpio(gpio)
|
: _gpio(gpio), _mode(mode)
|
||||||
, _mode(mode)
|
|
||||||
, _is_bidirectional(is_bidirectional)
|
, _is_bidirectional(is_bidirectional)
|
||||||
, _timing_config(DSHOT_TIMINGS[mode])
|
, _timing_config(DSHOT_TIMINGS[mode])
|
||||||
, _rmt_tx_channel(nullptr)
|
, _rmt_tx_channel(nullptr)
|
||||||
|
|
@ -63,9 +62,10 @@ bool DShotRMT::begin()
|
||||||
return DSHOT_OK;
|
return DSHOT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the throttle value and transmits
|
//
|
||||||
bool DShotRMT::setThrottle(uint16_t throttle)
|
bool DShotRMT::setThrottle(uint16_t throttle)
|
||||||
{
|
{
|
||||||
|
|
||||||
// DShot Frame Container
|
// DShot Frame Container
|
||||||
dshot_packet_t packet = {};
|
dshot_packet_t packet = {};
|
||||||
|
|
||||||
|
|
@ -78,32 +78,6 @@ bool DShotRMT::setThrottle(uint16_t throttle)
|
||||||
{
|
{
|
||||||
return DSHOT_ERROR;
|
return DSHOT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DSHOT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// DShot Commands
|
|
||||||
bool DShotRMT::sendDShotCommand(uint16_t command)
|
|
||||||
{
|
|
||||||
// DShot Frame Container
|
|
||||||
dshot_packet_t packet = {};
|
|
||||||
|
|
||||||
if ((command < DSHOT_CMD_MOTOR_STOP) || command > DSHOT_CMD_MAX)
|
|
||||||
{
|
|
||||||
return DSHOT_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create DShot packet
|
|
||||||
packet.throttle_value = command;
|
|
||||||
packet.telemetric_request = _is_bidirectional;
|
|
||||||
packet.checksum = _calculateCRC(packet);
|
|
||||||
|
|
||||||
if (!_sendDShotFrame(packet))
|
|
||||||
{
|
|
||||||
return DSHOT_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return DSHOT_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
@ -229,47 +203,40 @@ uint16_t DShotRMT::_calculateCRC(const dshot_packet_t &packet)
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a "raw" DShot Frame
|
//
|
||||||
uint16_t DShotRMT::_assembleDShotFrame(const dshot_packet_t &packet)
|
uint16_t DShotRMT::_assembleDShotFrame(const dshot_packet_t &packet)
|
||||||
{
|
{
|
||||||
// Check packet
|
// Parses DShot Frame
|
||||||
uint16_t crc_calculated = _calculateCRC(packet);
|
|
||||||
uint16_t crc_in_packet = packet.checksum;
|
|
||||||
|
|
||||||
if (crc_calculated != crc_in_packet)
|
|
||||||
{
|
|
||||||
return DSHOT_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parses DShot Packet
|
|
||||||
uint16_t data = (packet.throttle_value << 1) | packet.telemetric_request;
|
uint16_t data = (packet.throttle_value << 1) | packet.telemetric_request;
|
||||||
return (data << 4) | packet.checksum;
|
return (data << 4) | packet.checksum;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts DShot Frame
|
//
|
||||||
bool DShotRMT::_encodeDShotFrame(const dshot_packet_t &packet, rmt_symbol_word_t *symbols)
|
void DShotRMT::_encodeDShotFrame(const dshot_packet_t &packet, rmt_symbol_word_t *symbols)
|
||||||
{
|
{
|
||||||
// Encoding to "raw" DShot Packet
|
|
||||||
uint16_t frame_bits = _assembleDShotFrame(packet);
|
|
||||||
|
|
||||||
// Convert the parsed dshot frame to rmt_tx data
|
|
||||||
for (int i = 0; i < DSHOT_BITS_PER_FRAME; i++)
|
|
||||||
{
|
{
|
||||||
// Encode RMT symbols bitwise (MSB first) - tricky
|
// Encoding to "raw" DShot Packet
|
||||||
bool bit = (frame_bits >> ((DSHOT_BITS_PER_FRAME - 1) - i)) & 0b0000000000000001;
|
uint16_t frame_bits = _assembleDShotFrame(packet);
|
||||||
if (_is_bidirectional)
|
|
||||||
|
// Convert the parsed dshot frame to rmt_tx data
|
||||||
|
for (int i = 0; i < DSHOT_BITS_PER_FRAME; i++)
|
||||||
{
|
{
|
||||||
symbols[i].level0 = 0;
|
// Encode RMT symbols bitwise (MSB first) - tricky
|
||||||
symbols[i].duration0 = bit ? _timing_config.ticks_one_high : _timing_config.ticks_zero_high;
|
bool bit = (frame_bits >> (DSHOT_BITS_PER_FRAME - 1 - i)) & 0b0000000000000001;
|
||||||
symbols[i].level1 = 1;
|
if (_is_bidirectional)
|
||||||
symbols[i].duration1 = bit ? _timing_config.ticks_one_low : _timing_config.ticks_zero_low;
|
{
|
||||||
}
|
symbols[i].level0 = 0;
|
||||||
else
|
symbols[i].duration0 = bit ? _timing_config.ticks_one_high : _timing_config.ticks_zero_high;
|
||||||
{
|
symbols[i].level1 = 1;
|
||||||
symbols[i].level0 = 1;
|
symbols[i].duration1 = bit ? _timing_config.ticks_one_low : _timing_config.ticks_zero_low;
|
||||||
symbols[i].duration0 = bit ? _timing_config.ticks_one_high : _timing_config.ticks_zero_high;
|
}
|
||||||
symbols[i].level1 = 0;
|
else
|
||||||
symbols[i].duration1 = bit ? _timing_config.ticks_one_low : _timing_config.ticks_zero_low;
|
{
|
||||||
|
symbols[i].level0 = 1;
|
||||||
|
symbols[i].duration0 = bit ? _timing_config.ticks_one_high : _timing_config.ticks_zero_high;
|
||||||
|
symbols[i].level1 = 0;
|
||||||
|
symbols[i].duration1 = bit ? _timing_config.ticks_one_low : _timing_config.ticks_zero_low;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -308,13 +275,13 @@ uint16_t DShotRMT::_decodeDShotFrame(const rmt_symbol_word_t *symbols, size_t sy
|
||||||
return data >> 1;
|
return data >> 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timer is ringing
|
//
|
||||||
bool DShotRMT::_timer_signal()
|
bool DShotRMT::_timer_signal()
|
||||||
{
|
{
|
||||||
return ((micros() - _last_transmission_time) >= _frame_time_us);
|
return (micros() - _last_transmission_time) >= _frame_time_us;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timer restart
|
//
|
||||||
void DShotRMT::_timer_reset()
|
void DShotRMT::_timer_reset()
|
||||||
{
|
{
|
||||||
_last_transmission_time = micros();
|
_last_transmission_time = micros();
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ public:
|
||||||
// Sets the throttle value and transmits
|
// Sets the throttle value and transmits
|
||||||
bool setThrottle(uint16_t throttle);
|
bool setThrottle(uint16_t throttle);
|
||||||
|
|
||||||
// Sends a valid DShot Command
|
// Sends a DShot Command
|
||||||
bool sendDShotCommand(uint16_t command);
|
bool sendDShotCommand(uint16_t command);
|
||||||
|
|
||||||
// Gets eRPM from ESC telemetry
|
// Gets eRPM from ESC telemetry
|
||||||
|
|
@ -89,7 +89,7 @@ public:
|
||||||
//
|
//
|
||||||
gpio_num_t getGPIO() const { return _gpio; }
|
gpio_num_t getGPIO() const { return _gpio; }
|
||||||
dshot_mode_t getDShotMode() const { return _mode; }
|
dshot_mode_t getDShotMode() const { return _mode; }
|
||||||
bool isBidirectional() const { return _is_bidirectional; }
|
bool is_bidirectional() const { return _is_bidirectional; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Config ---
|
// --- Config ---
|
||||||
|
|
@ -117,14 +117,14 @@ private:
|
||||||
uint16_t _last_erpm;
|
uint16_t _last_erpm;
|
||||||
unsigned long _last_transmission_time;
|
unsigned long _last_transmission_time;
|
||||||
|
|
||||||
//
|
//
|
||||||
bool _initTXChannel();
|
bool _initTXChannel();
|
||||||
bool _initRXChannel();
|
bool _initRXChannel();
|
||||||
bool _initDShotEncoder();
|
bool _initDShotEncoder();
|
||||||
|
|
||||||
uint16_t _calculateCRC(const dshot_packet_t &packet);
|
uint16_t _calculateCRC(const dshot_packet_t &packet);
|
||||||
uint16_t _assembleDShotFrame(const dshot_packet_t &packet);
|
uint16_t _assembleDShotFrame(const dshot_packet_t &packet);
|
||||||
bool _encodeDShotFrame(const dshot_packet_t &packet, rmt_symbol_word_t *symbols);
|
void _encodeDShotFrame(const dshot_packet_t &packet, rmt_symbol_word_t *symbols);
|
||||||
uint16_t _decodeDShotFrame(const rmt_symbol_word_t *symbols, size_t symbol_count);
|
uint16_t _decodeDShotFrame(const rmt_symbol_word_t *symbols, size_t symbol_count);
|
||||||
bool _sendDShotFrame(const dshot_packet_t &packet);
|
bool _sendDShotFrame(const dshot_packet_t &packet);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,13 @@ constexpr uint32_t USB_SERIAL_BAUD = 115200;
|
||||||
// Motor configuration
|
// Motor configuration
|
||||||
constexpr gpio_num_t MOTOR01_PIN = GPIO_NUM_17;
|
constexpr gpio_num_t MOTOR01_PIN = GPIO_NUM_17;
|
||||||
constexpr dshot_mode_t DSHOT_MODE = DSHOT300;
|
constexpr dshot_mode_t DSHOT_MODE = DSHOT300;
|
||||||
constexpr uint8_t MOTOR01_MAGNET_COUNT = 14;
|
|
||||||
|
|
||||||
// BiDirectional DShot Signal (default: false)
|
// BiDirectional DShot Support (default: false)
|
||||||
constexpr bool IS_BIDIRECTIONAL = false;
|
constexpr bool IS_BIDIRECTIONAL = false;
|
||||||
|
|
||||||
|
// Motor magnet count for RPM calculation
|
||||||
|
constexpr uint8_t MOTOR01_MAGNET_COUNT = 14;
|
||||||
|
|
||||||
// Setup Motor Pin, DShot Mode and optional BiDirectional Support
|
// Setup Motor Pin, DShot Mode and optional BiDirectional Support
|
||||||
DShotRMT motor01(MOTOR01_PIN, DSHOT_MODE, IS_BIDIRECTIONAL);
|
DShotRMT motor01(MOTOR01_PIN, DSHOT_MODE, IS_BIDIRECTIONAL);
|
||||||
|
|
||||||
|
|
@ -39,6 +41,9 @@ void setup()
|
||||||
// Initialize DShot Signal
|
// Initialize DShot Signal
|
||||||
motor01.begin();
|
motor01.begin();
|
||||||
|
|
||||||
|
// Arm ESC with minimum throttle
|
||||||
|
motor01.setThrottle(DSHOT_THROTTLE_MIN);
|
||||||
|
|
||||||
USB_SERIAL.println("**********************");
|
USB_SERIAL.println("**********************");
|
||||||
USB_SERIAL.println("DShotRMT Demo started.");
|
USB_SERIAL.println("DShotRMT Demo started.");
|
||||||
USB_SERIAL.println("Enter a throttle value (48 – 2047):");
|
USB_SERIAL.println("Enter a throttle value (48 – 2047):");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue