diff --git a/src/main/drivers/dshot_bitbang.c b/src/main/drivers/dshot_bitbang.c index 8045019829..59133b7337 100644 --- a/src/main/drivers/dshot_bitbang.c +++ b/src/main/drivers/dshot_bitbang.c @@ -145,13 +145,27 @@ static void bbOutputDataInit(uint32_t *buffer, uint16_t portMask, bool inverted) setMask = portMask; } - int bitpos; + int symbol_index; - for (bitpos = 0; bitpos < 16; bitpos++) { - buffer[bitpos * 3 + 0] |= setMask ; // Always set all ports - buffer[bitpos * 3 + 1] = 0; // Reset bits are port dependent - buffer[bitpos * 3 + 2] |= resetMask; // Always reset all ports + for (symbol_index = 0; symbol_index < MOTOR_DSHOT_FRAME_BITS; symbol_index++) { + buffer[symbol_index * MOTOR_DSHOT_STATE_PER_SYMBOL + 0] |= setMask ; // Always set all ports + buffer[symbol_index * MOTOR_DSHOT_STATE_PER_SYMBOL + 1] = 0; // Reset bits are port dependent + buffer[symbol_index * MOTOR_DSHOT_STATE_PER_SYMBOL + 2] |= resetMask; // Always reset all ports } + + // + // output one more 'bit' that keeps the line level at idle to allow the ESC to sample the last bit + // + // Avoid CRC errors in the case of bi-directional d-shot. CRC errors can occur if the output is + // transitioned to an input before the signal has been sampled by the ESC as the sampled voltage + // may be somewhere between logic-high and logic-low depending on how the motor output line is + // driven or floating. On some MCUs it's observed that the voltage momentarily drops low on transition + // to input. + + int hold_bit_index = MOTOR_DSHOT_FRAME_BITS * MOTOR_DSHOT_STATE_PER_SYMBOL; + buffer[hold_bit_index + 0] |= resetMask; // Always reset all ports + buffer[hold_bit_index + 1] = 0; // Never any change + buffer[hold_bit_index + 2] = 0; // Never any change } static void bbOutputDataSet(uint32_t *buffer, int pinNumber, uint16_t value, bool inverted) diff --git a/src/main/drivers/dshot_bitbang_impl.h b/src/main/drivers/dshot_bitbang_impl.h index e33baf23d4..f81fcc46db 100644 --- a/src/main/drivers/dshot_bitbang_impl.h +++ b/src/main/drivers/dshot_bitbang_impl.h @@ -51,6 +51,7 @@ #define MOTOR_DSHOT_BIT_PER_SYMBOL 1 #define MOTOR_DSHOT_STATE_PER_SYMBOL 3 // Initial high, 0/1, low +#define MOTOR_DSHOT_BIT_HOLD_STATES 3 // 3 extra states at the end of transmission required to allow ESC to sample the last bit correctly. #define MOTOR_DSHOT_FRAME_BITS 16 @@ -62,7 +63,7 @@ #define MOTOR_DSHOT_GCR_CHANGE_INTERVAL_NS(rate) (MOTOR_DSHOT_CHANGE_INTERVAL_NS(rate) * 5 / 4) -#define MOTOR_DSHOT_BUF_LENGTH ((MOTOR_DSHOT_FRAME_BITS / MOTOR_DSHOT_BIT_PER_SYMBOL) * MOTOR_DSHOT_STATE_PER_SYMBOL) +#define MOTOR_DSHOT_BUF_LENGTH (((MOTOR_DSHOT_FRAME_BITS / MOTOR_DSHOT_BIT_PER_SYMBOL) * MOTOR_DSHOT_STATE_PER_SYMBOL) + MOTOR_DSHOT_BIT_HOLD_STATES) #ifdef USE_DSHOT_CACHE_MGMT // MOTOR_DSHOT_BUF_LENGTH is multiples of uint32_t // Number of bytes required for buffer