Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DSHOT support #1393

Closed
Linjieqiang opened this issue Mar 12, 2017 · 55 comments
Closed

Add DSHOT support #1393

Linjieqiang opened this issue Mar 12, 2017 · 55 comments
Milestone

Comments

@Linjieqiang
Copy link
Contributor

Port from betaflight.

@oleost
Copy link
Contributor

oleost commented Mar 14, 2017

Any reason for closing this?

Dshot is more than just raw performance.
It gives to possibility in future to use motor as buzzers, etc etc.

Should be on the to do list for INAV.

@oleost oleost reopened this Mar 14, 2017
@Linjieqiang
Copy link
Contributor Author

But I see DE is besy to deal with other problems so I choosed to close it.But I love to see dShot will be implemented in INAV project

@digitalentity digitalentity added this to the 1.8 milestone May 30, 2017
@fiam
Copy link
Member

fiam commented Sep 25, 2017

I'm moving this issue to 2.0, since there seems no interest in implementing DSHOT soon. PRs for it are welcome at any time though.

@Azuxul
Copy link

Azuxul commented Feb 22, 2018

Dshot implementation is important for BLheli32, without dshot we need to change throttle value and i dosen't found how to calibrate esc after. So for using inav with BLheli32 esc dshot is important.

@Jeeper10A
Copy link

Is Dshot in the works? I have a Matek f7 board and decided on betaflight or Inav. INAV will be my first choice but only if Dshot is implemented,

@Azuxul
Copy link

Azuxul commented Mar 17, 2018

Currently Dshot doesn't work.

@digitalentity digitalentity modified the milestones: 2.0, Future Apr 16, 2018
@Blaster1920
Copy link

Any update on dshot1200 ?

@Jhinta
Copy link

Jhinta commented May 11, 2018

+1 waiting for dshot

@strepto42
Copy link

+1 please, it's 2018 now. DSHOT is not only really useful, it's not even new tech now

@NeilGaede
Copy link

+1

@digitalentity
Copy link
Member

I see a lot of requests to add DHOT. Anybody want to have a crack at it?

@turboworks
Copy link

You gave me all the servos, thank You very much, please+1 DSHOT me as well...https://youtu.be/koOqenMpvck

@avrahams
Copy link

+1 and also esc telemetry

@digitalentity digitalentity changed the title [Feature Request]Add DShot ESC support. Add DSHOT support Jul 28, 2018
@digitalentity digitalentity modified the milestones: Future, 2.1 Jul 28, 2018
@digitalentity
Copy link
Member

Will look into DSHOT after we get 2.0 out of the door

@teckel12
Copy link
Contributor

I wouldn't use DSHOT even it it was implemented, so I've got no motivation to add support. I feel there's too much potential risk with no gain over other more stable and tolerant protocols. But, there's a difference between a racing drone and a GPS navigation craft.

@digitalentity
Copy link
Member

digitalentity commented Jul 29, 2018

DSHOT support is more a marketing move than a real added value. For racing quads it might be worth it (although I doubt the real effect on flight performance would be different from effect of a placebo).

For bigger machines it will definitely do more harm than good since it's much more succeptible for poor wiring quality and EMI noise.

@strepto42
Copy link

I have to disagree. Dshot eliminates the need to calibrate escs and provides a much more fault tolerant protocol for control. Poor wiring and so on will actually affect non-dshot quads more. My long range rig suffers from motor twitch badly using one shot, but flies perfectly using Dshot (which is why I switched it back to betaflight). I have great respect for contributors to open source and this project in particular but seriously, get with the program guys. Digital > analogue

@owengrey
Copy link

owengrey commented Aug 7, 2018

On the wire DSHOT is analog. CRC checking masks issues by discarding corrupt packets and what is observed as "motor twitching" with OS125 with DSHOT will result in spontaneous stop of one motor at some point once too many packets are discarded.

This statement cant be true! you are mixing an analog answer mixed with a digital answer, It cant be both.... CRC checking cant be used with an analog signal.

When I get more time I will look into this as well.
I am a research and developement engineer and have been designing industrial embedded controllers for many years. All software can be improved and that goes for communications between items also.

@teckel12
Copy link
Contributor

teckel12 commented Aug 7, 2018

@owengrey On the wire it's analog, but it's converted to a digital signal on the ends, which then does the CRC check. This is a quite common "digital" communication technique.

@digitalentity
Copy link
Member

We live in an analog world. There is no such thing as "digital signal", only "digital data" and "digital transmission" which means that binary data entering the transmitter is identical to binary data leaving the receiver. Even two logic elements connected by a simple wire operate voltage levels which they interpret as binary "1" and "0".

Same for DSHOT - it's a modulation technique to transmit a digital packet over analog wire. One largest drawback of digital transmission - it's usually all or nothing - communication works flawlessly even at very high levels of distortion. Beyond that it doesn't work at all.

@RCnator
Copy link

RCnator commented Aug 12, 2018

Pardon my lack of knowledge regarding IT etc but I hear about this timer and digitalentity wrote that he will "add a timer DMA framework after we release 2.0 (similar to what is there in Betaflight) - it will make adding dshot easier". What does that mean? Will we have dshot with 2.0.1 or will it be som kind of add on to 2.0?

@digitalentity
Copy link
Member

@RCnator this means precisely what it means - another step of timer code refactoring in the development branch after release 2.0 goes public. It will make effort to add DSHOT easier but I have no idea when we'll have DSHOT implemented. Most likely next version, but no guarantees.

@digitalentity
Copy link
Member

Ok, 2.0.0 almost out of the door. Time to start looking into DSHOT 😄

@teckel12
Copy link
Contributor

@digitalentity Please reconsider. Imagine the users we'll have if INAV includes DSHOT. 😵

@digitalentity
Copy link
Member

I'm ok with closing "motors stopped in air" issues if reporter is using DSHOT 😈

@teckel12
Copy link
Contributor

Braces for DSHOT, the next SBUS disarm bug of 2018. Only difference is this time there's no fixing it.

@TwoToneEddy
Copy link

@digitalentity I'd love to look into this once the timer has been implemented. I'm literally moving house this weekend though so please don't wait for me if there's some urgency to get it in there for the next release. I know allot of pilots who will be thrilled at the addition of D-shot.

@digitalentity
Copy link
Member

@TwoToneEddy I've started on TIM/DMA framework in #3833 (work in progress). Adding DSHOT on top of that should be fairly simple.

@digitalentity
Copy link
Member

Also: I want DSHOT to be only available on targets where ALL motor outputs can support it. Otherwise firmware should automatically fallback to i.e. OS125. All DSHOT-related stuff should be guarded with define USE_DSHOT.

@digitalentity
Copy link
Member

@teckel12 yes, we'll definitely see increase in bugreports. We'll figure out DSHOT policy once we have some statistics.

@davidngrc
Copy link

can't wait to test this, the next step will be esc telemetry, LOL

@wx4cb
Copy link

wx4cb commented Sep 6, 2018

Any news on dshot support?

@teckel12
Copy link
Contributor

@wx4cb TwoToneEddy said he was planning on adding this once the timing stuff was added, which it has been. I'd ask TTE of the status.

@TwoToneEddy
Copy link

I fully intend to look into this but I've just moved house and don't even have an internet connection. Happy to do it but it won't be for a few weeks.

@teckel12
Copy link
Contributor

@TwoToneEddy You're doing it wrong. When I move, I get the Internet before anything. 😁

@TwoToneEddy
Copy link

@teckel12 Don't get me wrong, I fuming I don't have the internet yet, how am I supposed to make a cup of coffee

@turboworks
Copy link

dial-up?

@digitalentity
Copy link
Member

No internet is really annoying. When I moved I got Internet even before the bed, table and microwave 😆

On topic: timer refactoring is in progress and I do it with DSHOT in mind - so adding DSHOT would be quite trivial.

Have a look at LEDSTRIP driver built on top of new timer framework https://github.com/iNavFlight/inav/blob/5ace4e6e59c3600bbe45dbd8ea9bf2ef1e17477a/src/main/drivers/light_ws2811strip.c - that's the complete driver, all low level hardware ops are done in timer code. DSHOT is very similar to LEDSTRIP protocol so implementation wouldn't be too different.

@digitalentity
Copy link
Member

F7 implementation is clumsy and not tested yet. I kind of miss elegacy of ST's StdLib - HAL is true monstrosity. HAL_LL is much nicer, however amount of work to rewrite everything is huge (but eventually I might consider doing it anyway).

@teckel12
Copy link
Contributor

teckel12 commented Sep 16, 2018

These days, the Internet comes before food, clothing and shelter, because what's the point without the Internet?

@digitalentity
Copy link
Member

Initial cut of DSHOT implementation - #3879

@digitalentity
Copy link
Member

As I said - on new timer framework implementation is trivial

@TwoToneEddy
Copy link

So you've done it already! That was quick! Sorry I couldn't pull my finger out in time, once I'm up and running I really hope I can contribute.

@digitalentity
Copy link
Member

@TwoToneEddy yep, new timer framework made it so trivial that I decided to go for it. Basically these ~140 lines of code are DSHOT protocol:

#ifdef USE_DSHOT
uint32_t getDshotHz(motorPwmProtocolTypes_e pwmProtocolType)
{
switch (pwmProtocolType) {
case(PWM_TYPE_DSHOT1200):
return MOTOR_DSHOT1200_HZ;
case(PWM_TYPE_DSHOT600):
return MOTOR_DSHOT600_HZ;
case(PWM_TYPE_DSHOT300):
return MOTOR_DSHOT300_HZ;
default:
case(PWM_TYPE_DSHOT150):
return MOTOR_DSHOT150_HZ;
}
}
static pwmOutputPort_t * motorConfigDshot(const timerHardware_t * timerHardware, motorPwmProtocolTypes_e proto, uint16_t motorPwmRateHz, bool enableOutput)
{
// Try allocating new port
pwmOutputPort_t * port = pwmOutConfigMotor(timerHardware, getDshotHz(proto), DSHOT_MOTOR_BITLENGTH, 0, enableOutput);
if (!port) {
return NULL;
}
// Keep track of motor update interval
const timeUs_t motorIntervalUs = 1000000 / motorPwmRateHz;
dshotMotorUpdateIntervalUs = MAX(dshotMotorUpdateIntervalUs, motorIntervalUs);
// Configure timer DMA
if (timerPWMConfigChannelDMA(port->tch, port->dmaBuffer, DSHOT_DMA_BUFFER_SIZE)) {
// Only mark as DSHOT channel if DMA was set successfully
port->configured = true;
}
return port;
}
static void pwmWriteDshot(uint8_t index, uint16_t value)
{
// DMA operation might still be running. Cache value for future use
motors[index]->value = value;
}
static void loadDmaBufferDshot(uint32_t * dmaBuffer, uint16_t packet)
{
for (int i = 0; i < 16; i++) {
dmaBuffer[i] = (packet & 0x8000) ? DSHOT_MOTOR_BIT_1 : DSHOT_MOTOR_BIT_0; // MSB first
packet <<= 1;
}
}
static uint16_t prepareDshotPacket(const uint16_t value, bool requestTelemetry)
{
uint16_t packet = (value << 1) | (requestTelemetry ? 1 : 0);
// compute checksum
int csum = 0;
int csum_data = packet;
for (int i = 0; i < 3; i++) {
csum ^= csum_data; // xor data by nibbles
csum_data >>= 4;
}
csum &= 0xf;
// append checksum
packet = (packet << 4) | csum;
return packet;
}
void pwmCompleteDshotUpdate(uint8_t motorCount, timeUs_t currentTimeUs)
{
// Enforce motor update rate
if (!isProtocolDshot || (dshotMotorUpdateIntervalUs == 0) || ((currentTimeUs - dshotMotorLastUpdateUs) <= dshotMotorUpdateIntervalUs)) {
return;
}
dshotMotorLastUpdateUs = currentTimeUs;
// Generate DMA buffers
for (int index = 0; index < motorCount; index++) {
if (motors[index] && motors[index]->configured) {
// TODO: ESC telemetry
uint16_t packet = prepareDshotPacket(motors[index]->value, false);
loadDmaBufferDshot(motors[index]->dmaBuffer, packet);
timerPWMPrepareDMA(motors[index]->tch, DSHOT_DMA_BUFFER_SIZE);
}
}
// Start DMA on all timers
for (int index = 0; index < motorCount; index++) {
if (motors[index] && motors[index]->configured) {
timerPWMStartDMA(motors[index]->tch);
}
}
}
bool isMotorProtocolDshot(void)
{
return isProtocolDshot;
}
#endif

and mixer output conversion to DSHOT scale:

#ifdef USE_DSHOT
// If we use DSHOT we need to convert motorValue to DSHOT ranges
if (isMotorProtocolDshot()) {
const float dshotMinThrottleOffset = (DSHOT_MAX_THROTTLE - DSHOT_MIN_THROTTLE) / 10000.0f * motorConfig()->digitalIdleOffsetValue;
if (feature(FEATURE_3D)) {
if (motor[i] >= motorConfig()->minthrottle && motor[i] <= flight3DConfig()->deadband3d_low) {
motorValue = scaleRangef(motor[i], motorConfig()->minthrottle, flight3DConfig()->deadband3d_low, DSHOT_3D_DEADBAND_LOW, dshotMinThrottleOffset + DSHOT_MIN_THROTTLE);
motorValue = constrain(motorValue, DSHOT_MIN_THROTTLE, DSHOT_3D_DEADBAND_LOW);
}
else if (motor[i] >= flight3DConfig()->deadband3d_high && motor[i] <= motorConfig()->maxthrottle) {
motorValue = scaleRangef(motor[i], flight3DConfig()->deadband3d_high, motorConfig()->maxthrottle, dshotMinThrottleOffset + DSHOT_3D_DEADBAND_HIGH, DSHOT_MAX_THROTTLE);
motorValue = constrain(motorValue, DSHOT_3D_DEADBAND_HIGH, DSHOT_MAX_THROTTLE);
}
else {
motorValue = DSHOT_DISARM_COMMAND;
}
}
else {
if (motor[i] < motorConfig()->minthrottle) { // motor disarmed
motorValue = DSHOT_DISARM_COMMAND;
}
else {
motorValue = scaleRangef(motor[i], motorConfig()->minthrottle, motorConfig()->maxthrottle, (dshotMinThrottleOffset + DSHOT_MIN_THROTTLE), DSHOT_MAX_THROTTLE);
motorValue = constrain(motorValue, (dshotMinThrottleOffset + DSHOT_MIN_THROTTLE), DSHOT_MAX_THROTTLE);
}
}
}
else {
motorValue = motor[i];
}
#else

One thing that will make code easier to understand is mixer change to [-1;1] scale which I might go for next.

@DzikuVx
Copy link
Member

DzikuVx commented Nov 12, 2018

I think we can close it as done in 2.1

@DzikuVx DzikuVx closed this as completed Nov 12, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests