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

Added anti-turtle reversemotors and beeper using dshot commands on blheli_s #3267

Merged
merged 1 commit into from Jun 15, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/drivers/pwm_output.c
Expand Up @@ -338,7 +338,7 @@ void pwmWriteDshotCommand(uint8_t index, uint8_t command)
motorDmaOutput_t *const motor = getMotorDmaOutput(index);

unsigned repeats;
if ((command >= 7 && command <= 10) || command == 12) {
if ((DSHOT_CMD_SPIN_ONE_WAY >= 7 && DSHOT_CMD_3D_MODE_ON <= 10) || DSHOT_CMD_SAVE_SETTINGS == 12 || (DSHOT_CMD_ROTATE_NORMAL >= 20 && DSHOT_CMD_ROTATE_REVERSE <= 21) ) {
repeats = 10;
} else {
repeats = 1;
Expand Down
20 changes: 20 additions & 0 deletions src/main/drivers/pwm_output.h
Expand Up @@ -28,6 +28,26 @@
#define MAX_SUPPORTED_SERVOS 8
#endif

typedef enum {
DSHOT_CMD_MOTOR_STOP = 0,
DSHOT_CMD_BEEP1,
DSHOT_CMD_BEEP2,
DSHOT_CMD_BEEP3,
DSHOT_CMD_BEEP4,
DSHOT_CMD_BEEP5,
DSHOT_CMD_ESC_INFO,
DSHOT_CMD_SPIN_ONE_WAY,
DSHOT_CMD_SPIN_OTHER_WAY,
DSHOT_CMD_3D_MODE_OFF,
DSHOT_CMD_3D_MODE_ON,
DSHOT_CMD_SETTINGS_REQUEST,
DSHOT_CMD_SAVE_SETTINGS,
DSHOT_CMD_ROTATE_NORMAL = 20, //Blheli_S only command
DSHOT_CMD_ROTATE_REVERSE = 21, //Blheli_S only command
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brycedjohnson It's unfortunate to have different commands for the same thing on different ESCs. The idea behind DSHOT is that it's a standard protocol that works the same across both blheli and kiss. Is the only reason for that because you can't test Kiss ESCs? I can help with that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@robertlacroix Does the "DSHOT_CMD_SPIN_OTHER_WAY" always make kiss escs spin the opposite way as they are configured (CW ->CCW and CCW->CW)? If so it would be easy to standardize, if not there is no way to tell what way the motor is spinning without telemetry or telling betaflight what each motor is doing ahead of time.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would assume it spins the other way than the configured direction. I might be able to try in the next couple of days.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@robertlacroix: These commands do different things indeed: DSHOT_CMD_SPIN_DIRECTION_1 and DSHOT_CMD_SPIN_DIRECTION_2 set the absolute motor direction, which is then persisted in the ESCs configuration. DSHOT_CMD_SPIN_DIRECTION_NORMAL and DSHOT_CMD_SPIN_DIRECTION_REVERSED temporarily reverse the motor direction, relative to what was configured before (with DShot commands, or through an ESC configuration tool). This seems to be redundant to some extent, but in the case of blheli_s, without the flight controller having any means to query the current setting for the spin direction, using an absolute change to effect a temporary reversal is not a good option.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mkeller @brycedjohnson Makes sense! Can we try to work with the Kiss guys and have that added as 20 and 21 on their end as well?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well... different versions have a bit different protocol... but it will get u going ;)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what other protocol versions are out there?

Also, does this new version of the version info frame have a checksum, or has this been dropped?

Copy link
Contributor

@ronlix ronlix Jul 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi,
for now there are only two versions. the first one sends 15 bytes:
1-12: ESC SN
13: EEprom/version (1.01 == 101)
14, bit 8-6: ESC Type
14, bit 5-1: ESC sub version (a-z)
15: crc (same crc as is used for telemetry)

after we worked on the dshot settings, we decided to not use the dshot setting request command as it just adds load to the FC and GUI to have more requests. so i streched the ESC info response a bit. its now 21 bytes:

1-12: ESC SN
13: now idicates if the new response is used. so if its 255 it is the new version.
14: EEprom/version (1.01 == 101)
15: ESC type
16: ESC sub version letter
17: rotation direction reversed by dshot command or not (1:0)
18: 3D mode active or not (1:0)
19: unused for now.. maybe used for new settings
20: unused for now.. maybe used for new settings
21: crc (same crc as is used for telemetry)

for now the rotation direction reversed byte only tells if the rotation is reversed and saved by dshot command 8, not when temporary reversed (21)

regards

Felix

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ronlix.

Thanks for the clarification. I will add this later on. Can you clarify some details please:

  • is there a list of ESC types?
  • 'ESC sub version letter' is ASCII?

I think it is correct for the command to return the direction that is saved, and not taking the temporary reversal (21) into account. After all the flight controller sets the reversal, so it should not have to query it.

Since this info block now includes the ESC config, am I right to assume that command 11 (send ESC settings) is now unused, and will not be implemented?

Also you ok with blheli_32 using the same format to dump ESC info over telemetry? For me, from the flight controller side, doing so would be a huge advantage, since only then will it be possible to reliably get ESC config info without the user having to provide some information. If this is ok, can I propose that we use one of the unused bytes to encode firmware type?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for now:
1 = KISS8A (KISSAIO)
2 = KISS16A (KISSCC)
3 = KISS24A RE
5 = KISS Ultralite (Tealdrones)

yes, the subversion is ASCII

command 11 ESC settings is unused.

im fine with BLheli32 using the same protocol, i would just say that blheli32 then should start at 0x7F with the ESC type, so we have some free for future ;)

regards

felix

DSHOT_CMD_MAX = 47
} dshotCommands_e;


typedef enum {
PWM_TYPE_STANDARD = 0,
PWM_TYPE_ONESHOT125,
Expand Down
21 changes: 20 additions & 1 deletion src/main/fc/fc_core.c
Expand Up @@ -106,7 +106,7 @@ int16_t magHold;
int16_t headFreeModeHold;

uint8_t motorControlEnable = false;

static bool reverseMotors;
static uint32_t disarmAt; // Time of automatic disarm when "Don't spin the motors when armed" is enabled and auto_disarm_delay is nonzero

bool isRXDataNew;
Expand Down Expand Up @@ -205,6 +205,20 @@ void mwArm(void)
return;
}
if (!ARMING_FLAG(PREVENT_ARMING)) {
#ifdef USE_DSHOT
if (!feature(FEATURE_3D) && !IS_RC_MODE_ACTIVE(BOX3DDISABLESWITCH)) {
reverseMotors = false;
for (unsigned index = 0; index < getMotorCount(); index++) {
pwmWriteDshotCommand(index, DSHOT_CMD_ROTATE_NORMAL);
}
}
if (!feature(FEATURE_3D) && IS_RC_MODE_ACTIVE(BOX3DDISABLESWITCH)) {
reverseMotors = true;
for (unsigned index = 0; index < getMotorCount(); index++) {
pwmWriteDshotCommand(index, DSHOT_CMD_ROTATE_REVERSE);
}
}
#endif
ENABLE_ARMING_FLAG(ARMED);
ENABLE_ARMING_FLAG(WAS_EVER_ARMED);
headFreeModeHold = DECIDEGREES_TO_DEGREES(attitude.values.yaw);
Expand Down Expand Up @@ -644,3 +658,8 @@ void taskMainPidLoop(timeUs_t currentTimeUs)
runTaskMainSubprocesses = true;
}
}

bool isMotorsReversed()
{
return reverseMotors;
}
1 change: 1 addition & 0 deletions src/main/fc/fc_core.h
Expand Up @@ -48,3 +48,4 @@ void updateLEDs(void);
void updateRcCommands(void);

void taskMainPidLoop(timeUs_t currentTimeUs);
bool isMotorsReversed(void);
4 changes: 1 addition & 3 deletions src/main/fc/fc_msp.c
Expand Up @@ -370,9 +370,7 @@ void initActiveBoxIds(void)

BME(BOXFPVANGLEMIX);

if (feature(FEATURE_3D)) {
BME(BOX3DDISABLESWITCH);
}
BME(BOX3DDISABLESWITCH);

if (feature(FEATURE_SERVO_TILT)) {
BME(BOXCAMSTAB);
Expand Down
1 change: 1 addition & 0 deletions src/main/fc/fc_rc.c
Expand Up @@ -46,6 +46,7 @@
#include "flight/failsafe.h"
#include "flight/imu.h"
#include "flight/pid.h"
#include "flight/mixer.h"

static float setpointRate[3], rcDeflection[3], rcDeflectionAbs[3];
static float throttlePIDAttenuation;
Expand Down
11 changes: 7 additions & 4 deletions src/main/flight/mixer.c
Expand Up @@ -41,6 +41,7 @@
#include "fc/config.h"
#include "fc/rc_controls.h"
#include "fc/runtime_config.h"
#include "fc/fc_core.h"

#include "flight/failsafe.h"
#include "flight/imu.h"
Expand Down Expand Up @@ -119,7 +120,6 @@ PG_REGISTER_ARRAY(motorMixer_t, MAX_SUPPORTED_MOTORS, customMotorMixer, PG_MOTOR

#define TRICOPTER_ERROR_RATE_YAW_SATURATED 75 // rate at which tricopter yaw axis becomes saturated, determined experimentally by TriFlight


static uint8_t motorCount;
static float motorMixRange;

Expand Down Expand Up @@ -576,11 +576,14 @@ void mixTable(pidProfile_t *pidProfile)
float motorMix[MAX_SUPPORTED_MOTORS];
float motorMixMax = 0, motorMixMin = 0;
const int yawDirection = GET_DIRECTION(mixerConfig()->yaw_motors_reversed);
int motorDirection = GET_DIRECTION(isMotorsReversed());


for (int i = 0; i < motorCount; i++) {
float mix =
scaledAxisPidRoll * currentMixer[i].roll +
scaledAxisPidPitch * currentMixer[i].pitch +
scaledAxisPidYaw * currentMixer[i].yaw * (-yawDirection);
scaledAxisPidRoll * currentMixer[i].roll * (motorDirection) +
scaledAxisPidPitch * currentMixer[i].pitch * (motorDirection) +
scaledAxisPidYaw * currentMixer[i].yaw * (-yawDirection) * (motorDirection);

if (vbatCompensationFactor > 1.0f) {
mix *= vbatCompensationFactor; // Add voltage compensation
Expand Down
12 changes: 11 additions & 1 deletion src/main/io/beeper.c
Expand Up @@ -28,6 +28,9 @@

#include "drivers/sound_beeper.h"
#include "drivers/time.h"
#include "drivers/pwm_output.h"

#include "flight/mixer.h"

#include "fc/config.h"
#include "fc/runtime_config.h"
Expand Down Expand Up @@ -153,7 +156,6 @@ static uint8_t beep_multiBeeps[MAX_MULTI_BEEPS + 2];
#define BEEPER_CONFIRMATION_BEEP_DURATION 2
#define BEEPER_CONFIRMATION_BEEP_GAP_DURATION 20


// Beeper off = 0 Beeper on = 1
static uint8_t beeperIsOn = 0;

Expand Down Expand Up @@ -338,6 +340,14 @@ void beeperUpdate(timeUs_t currentTimeUs)
return;
}

#ifdef USE_DSHOT
if (!ARMING_FLAG(ARMED) && currentBeeperEntry->mode == BEEPER_RX_SET) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this do?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sends the dshot beep command when not armed and with the beeper mode switch flipped

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. I think a lot of pilots use that switch as a 'lost craft indicator', so beeping the ESCs in case the beeper was smashed in the crash is a good thing.

(Also, the beeper code is a mess.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I tried to use the dshot beep for everything, but that was a little too much. I could see in the future you could use the 5 different kinds of beeps to signal different things much like the beeper has different patterns.

Also this has already saved me a few minutes finding my crashed quad in some tall grass! I don't have actual beepers on any of my quads.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using it for everything is a hard ask, since things like low voltage alarms make only sense if they work while armed, and you don't really want to waste motor update bandwidth on beeping in that situation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The loss of transmitter, blackbox erase completed, gyro calibration, acc calibration, maybe some others might be good ones to add in the future with different beep sounds... but that can be a separate PR .

for (unsigned index = 0; index < getMotorCount(); index++) {
pwmWriteDshotCommand(index, DSHOT_CMD_BEEP3);
}
}
#endif

if (!beeperIsOn) {
beeperIsOn = 1;
if (currentBeeperEntry->sequence[beeperPos] != 0) {
Expand Down