parent
08c3a50423
commit
6c1c7e38e0
40
DShotRMT.cpp
40
DShotRMT.cpp
|
|
@ -19,8 +19,7 @@ constexpr dshot_timing_t DSHOT_TIMINGS[] = {
|
|||
};
|
||||
|
||||
//
|
||||
DShotRMT::DShotRMT(gpio_num_t gpio, dshot_mode_t mode, bool is_bidirectional):
|
||||
_gpio(gpio),
|
||||
DShotRMT::DShotRMT(gpio_num_t gpio, dshot_mode_t mode, bool is_bidirectional) : _gpio(gpio),
|
||||
_mode(mode),
|
||||
_is_bidirectional(is_bidirectional),
|
||||
_timing_config(DSHOT_TIMINGS[mode]),
|
||||
|
|
@ -28,16 +27,17 @@ DShotRMT::DShotRMT(gpio_num_t gpio, dshot_mode_t mode, bool is_bidirectional):
|
|||
_rmt_rx_channel(nullptr),
|
||||
_dshot_encoder(nullptr),
|
||||
_last_erpm(0),
|
||||
_last_transmission_time(0)
|
||||
_last_transmission_time(0),
|
||||
_current_packet(0)
|
||||
{
|
||||
// Calculate frame time including switch time
|
||||
_frame_time_us = _timing_config.frame_length_us + DSHOT_SWITCH_TIME;
|
||||
|
||||
// Double up frame time for bidirectional mode
|
||||
if (_is_bidirectional)
|
||||
{
|
||||
_frame_time_us += _frame_time_us;
|
||||
_frame_time_us = (_timing_config.frame_length_us << 1) + DSHOT_SWITCH_TIME;
|
||||
}
|
||||
|
||||
// Calculate frame time including switch time
|
||||
_frame_time_us = _timing_config.frame_length_us + DSHOT_SWITCH_TIME;
|
||||
}
|
||||
|
||||
// Init DShotRMT
|
||||
|
|
@ -75,7 +75,7 @@ bool DShotRMT::setThrottle(uint16_t throttle)
|
|||
|
||||
// Create DShot packet
|
||||
packet.throttle_value = constrain(throttle, DSHOT_THROTTLE_MIN, DSHOT_THROTTLE_MAX);
|
||||
packet.telemetric_request = _is_bidirectional;
|
||||
packet.telemetric_request = 0;
|
||||
packet.checksum = _calculateCRC(packet);
|
||||
|
||||
if (!_sendDShotFrame(packet))
|
||||
|
|
@ -94,13 +94,14 @@ bool DShotRMT::sendDShotCommand(uint16_t command)
|
|||
|
||||
// Create DShot packet
|
||||
packet.throttle_value = constrain(command, DSHOT_CMD_MOTOR_STOP, DSHOT_CMD_MAX);
|
||||
packet.telemetric_request = _is_bidirectional;
|
||||
packet.telemetric_request = 0;
|
||||
packet.checksum = _calculateCRC(packet);
|
||||
|
||||
if (!_sendDShotFrame(packet))
|
||||
{
|
||||
return DSHOT_ERROR;
|
||||
}
|
||||
|
||||
return DSHOT_OK;
|
||||
}
|
||||
|
||||
|
|
@ -156,7 +157,7 @@ bool DShotRMT::_initTXChannel()
|
|||
return DSHOT_ERROR;
|
||||
}
|
||||
|
||||
return rmt_enable(_rmt_tx_channel) == 0;
|
||||
return (rmt_enable(_rmt_tx_channel) == 0);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -177,7 +178,7 @@ bool DShotRMT::_initRXChannel()
|
|||
return DSHOT_ERROR;
|
||||
}
|
||||
|
||||
return rmt_enable(_rmt_rx_channel) == 0;
|
||||
return (rmt_enable(_rmt_rx_channel) == 0);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -211,17 +212,18 @@ uint16_t DShotRMT::_sendDShotFrame(const dshot_packet_t &packet)
|
|||
// Time Stamp
|
||||
_timer_reset();
|
||||
|
||||
return _assembleDShotFrame(packet);
|
||||
//
|
||||
return _parseDShotPacket(packet);
|
||||
}
|
||||
|
||||
//
|
||||
// Calculates checksum for given package
|
||||
uint16_t DShotRMT::_calculateCRC(const dshot_packet_t &packet)
|
||||
{
|
||||
uint16_t data = (packet.throttle_value << 1) | packet.telemetric_request;
|
||||
uint16_t crc = (data ^ (data >> 4) ^ (data >> 8)) & 0b0000000000001111;
|
||||
|
||||
// Invert CRC for bidirectional DShot
|
||||
if (packet.telemetric_request)
|
||||
if (_is_bidirectional)
|
||||
{
|
||||
crc = (~crc) & 0b0000000000001111;
|
||||
}
|
||||
|
|
@ -230,7 +232,7 @@ uint16_t DShotRMT::_calculateCRC(const dshot_packet_t &packet)
|
|||
}
|
||||
|
||||
//
|
||||
uint16_t DShotRMT::_assembleDShotFrame(const dshot_packet_t &packet)
|
||||
uint16_t DShotRMT::_parseDShotPacket(const dshot_packet_t &packet)
|
||||
{
|
||||
// Parses DShot Frame
|
||||
uint16_t data = (packet.throttle_value << 1) | packet.telemetric_request;
|
||||
|
|
@ -238,10 +240,13 @@ uint16_t DShotRMT::_assembleDShotFrame(const dshot_packet_t &packet)
|
|||
}
|
||||
|
||||
//
|
||||
bool DShotRMT::_encodeDShotFrame(const dshot_packet_t& packet, rmt_symbol_word_t* symbols)
|
||||
bool IRAM_ATTR DShotRMT::_encodeDShotFrame(const dshot_packet_t &packet, rmt_symbol_word_t *symbols)
|
||||
{
|
||||
// Encoding to "raw" DShot Packet
|
||||
uint16_t frame_bits = _assembleDShotFrame(packet);
|
||||
uint16_t frame_bits = _parseDShotPacket(packet);
|
||||
|
||||
// Updates temp buffer with encoded packet
|
||||
_current_packet = frame_bits;
|
||||
|
||||
// Convert the parsed dshot frame to rmt_tx data
|
||||
for (int i = 0; i < DSHOT_BITS_PER_FRAME; i++)
|
||||
|
|
@ -303,6 +308,7 @@ uint16_t DShotRMT::_decodeDShotFrame(const rmt_symbol_word_t *symbols, size_t sy
|
|||
//
|
||||
bool DShotRMT::_timer_signal()
|
||||
{
|
||||
// Timer triggered
|
||||
return (micros() - _last_transmission_time) >= _frame_time_us;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ public:
|
|||
//
|
||||
gpio_num_t getGPIO() const { return _gpio; }
|
||||
dshot_mode_t getDShotMode() const { return _mode; }
|
||||
uint16_t getDShotPacket() { return _current_packet; }
|
||||
bool is_bidirectional() const { return _is_bidirectional; }
|
||||
|
||||
private:
|
||||
|
|
@ -118,6 +119,7 @@ private:
|
|||
rmt_symbol_word_t _rx_symbols[RX_BUFFER_SIZE];
|
||||
uint16_t _last_erpm;
|
||||
unsigned long _last_transmission_time;
|
||||
uint16_t _current_packet;
|
||||
|
||||
//
|
||||
bool _initTXChannel();
|
||||
|
|
@ -126,8 +128,8 @@ private:
|
|||
|
||||
uint16_t _sendDShotFrame(const dshot_packet_t &packet);
|
||||
uint16_t _calculateCRC(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);
|
||||
uint16_t _parseDShotPacket(const dshot_packet_t &packet);
|
||||
bool IRAM_ATTR _encodeDShotFrame(const dshot_packet_t &packet, rmt_symbol_word_t *symbols);
|
||||
uint16_t _decodeDShotFrame(const rmt_symbol_word_t *symbols, size_t symbol_count);
|
||||
|
||||
bool _timer_signal();
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@ void printRPMPeriodically(uint16_t throttle);
|
|||
// Reads throttle value from serial input
|
||||
uint16_t readSerialThrottle();
|
||||
|
||||
// Prints out the dshot packet bitwise (Debug)
|
||||
void printPacket();
|
||||
|
||||
//
|
||||
void setup()
|
||||
{
|
||||
|
|
@ -63,6 +66,9 @@ void loop()
|
|||
{
|
||||
printRPMPeriodically(throttle_input);
|
||||
}
|
||||
|
||||
// Prints out "raw" DShot packet
|
||||
// printPacket();
|
||||
}
|
||||
|
||||
// Reads throttle value from serial input
|
||||
|
|
@ -111,3 +117,30 @@ void printRPMPeriodically(uint16_t throttle)
|
|||
last_print_time = millis();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
void printPacket()
|
||||
{
|
||||
static unsigned long last_print_time = 0;
|
||||
|
||||
if (millis() - last_print_time >= 2000)
|
||||
{
|
||||
// Prints out actual DShot Packet bitwise
|
||||
uint16_t packet = motor01.getDShotPacket();
|
||||
|
||||
for (int i = 15; i >= 0; --i)
|
||||
{
|
||||
if ((packet >> i) & 1)
|
||||
{
|
||||
USB_SERIAL.print("1");
|
||||
}
|
||||
else
|
||||
{
|
||||
USB_SERIAL.print("0");
|
||||
}
|
||||
}
|
||||
|
||||
USB_SERIAL.println("");
|
||||
last_print_time = millis();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue