How do I achieve smooth startup on a brushless motor?

I have a setup going where I can use a Bluetooth app called RemoteXY to control the speed of a Turnigy sk3 Aerodrive brushless motor. The slider maps almost perfectly to the spin speed of the motor, however, when I am at the low end of the slider (when the motor should startup spinning slowly), the motor doesn’t do anything, and then suddenly jolts and starts spinning after a certain threshold. I think this is known as hesitation or cogging, and it’s a common issue with brushless motors from what I can tell.

The question is, is there any way I can smooth out this initial jolt when I start raising the slider, or do I just have to deal with the fact that the startup will not be smooth? After the motor has started up everything seems to roll smoothly.

A video of the issue I am referring to here.

My code is below. The motor control section is near the end, I’ve indicated it in a comment

*/

//////////////////////////////////////////////
//        RemoteXY include library          //
//////////////////////////////////////////////

// RemoteXY select connection mode and include library 
#define REMOTEXY_MODE__SOFTSERIAL
#include <SoftwareSerial.h>

#include <RemoteXY.h>

//#include <Servo.h>
#include <PWMServo.h>

//Servo ESC; //create servo object
PWMServo ESC;
// RemoteXY connection settings 
#define REMOTEXY_SERIAL_RX 10
#define REMOTEXY_SERIAL_TX 11
#define REMOTEXY_SERIAL_SPEED 9600


// RemoteXY configurate  
#pragma pack(push, 1)
uint8_t RemoteXY_CONF[] =
  { 255,2,0,0,0,60,0,11,13,1,
  4,0,23,16,17,64,2,26,2,0,
  31,5,22,11,2,26,31,31,79,78,
  0,79,70,70,0,129,0,5,7,18,
  6,17,76,69,68,0,129,0,15,85,
  37,6,17,83,101,114,105,97,108,32,
  111,117,116,112,117,116,0 };
  
// this structure defines all the variables and events of your control interface 
struct {

    // input variables
  int8_t slider_1; // =0..100 slider position 
  uint8_t switch_1; // =1 if switch ON and =0 if OFF 

    // other variable
  uint8_t connect_flag;  // =1 if wire connected, else =0 

} RemoteXY;
#pragma pack(pop)

/////////////////////////////////////////////
//           END RemoteXY include          //
/////////////////////////////////////////////

int power = 8;
int ledPin = 2;

void setup() 
{
  RemoteXY_Init (); 

  digitalWrite(LED_BUILTIN, HIGH);
  // TODO you setup code

  pinMode (LED_BUILTIN, OUTPUT);
  pinMode (power, OUTPUT);
  pinMode (ledPin, OUTPUT);
  //pinMode (7, OUTPUT);
  //int ledMapping;

  ESC.attach(12, 1000, 2000); //attach ESC to output from pin 6
  //TIMSK5 = 0;
  
  Serial.begin(9600);
}

void loop() 
{ 
  RemoteXY_Handler ();

//THIS SECTION IS FOR BLUETOOTH APP
  //Serial.println(RemoteXY.slider_1);
  digitalWrite(power, HIGH); //supply power to Bluetooth module through pin 8
  //digitalWrite(7, HIGH);
  int ledMapping = map(RemoteXY.slider_1, 0, 100, 0, 255);
  //Serial.println(ledMapping);
  analogWrite(ledPin, ledMapping);

// Motor control starts here
  int spinMapping = map(RemoteXY.slider_1, 0, 100, 0, 20); //map the slider to the servo
  if (RemoteXY.switch_1 == 1){
  ESC.write(95+spinMapping); //write to the ESC the value of mapped slider, 90 being the neutral angle
  }
  else if (RemoteXY.switch_1 == 0){
  ESC.write(85-spinMapping); //the reverse direction
  }
  
}

Any advice would be greatly appreciated!

That's a sensorless motor and what you're seeing is just how sensorless motors work. They need to be turning at a reasonable speed for the electronic commutation in the ESC to start up smoothly.

About the only way you'll get it to run smoothly at low speeds is to change to a sensored motor and ESC as used in RC rock crawlers and some trucks.

Steve

So there's no way to do something where I manually accelerate the motor in small steps (using delay, something like I've posted below) in order to bypass the jittery startup?

This code is just an idea of how I can get the motor to start spinning slowly, and then maybe it'll be going fast enough so that the slider can take over?

const int angleIncrement = 1;
const int incrementDelay = 10;
for (int angle = 0; angle < 180; angle += angleIncrement) { // single "degree" increments
  myServo.write (angle);
  delay (incrementDelay); // so we'll take 10 * 180 milliseconds = 1.8 seconds for the traverse.
}

By all means give it a try but I think you'll still find that until it gets to a certain point it will either do nothing or just jiggle about and only then will it start moving. I've never used your exact motor and ESC so it may be good enough for your purposes but I wouldn't go all the way to 180 because that will be at full speed before you get out of the for loop.

Steve

You need a sensored motor and matching ESC to get low speed control (and torque) of a BLDC (ie closed-loop control). For instance all industrial BLDCs have Hall sensors, its only RC devices that cut costs this way. Gimbal motors often use a separate angle sensor for feedback and can avoid having Hall sensors, but they need a controller that understands how to do the feedback.