SparkFun Forums 

Where electronics enthusiasts find answers.

For the discussion of Arduino related topics.
By navillus5
#142252
Hi -

I am spending some time looking at how an Arduino can be used to control a brushless motor. I am using an Arduino Duemilanove, a Hacker x-5 Pro ESC, and a Hacker A-10 brushless motor.

I am able to both arm the ESC and use it to operate the motor, but I am running into a few items that I don't quite understand that are mostly related to using the Servo library.

I have read through a previous discussion and have most items figured out, but I wanted to post my sketches and get some feedback.

This first sketch is used to arm the ESC and works as expected:
Code: Select all
// This sketch arms the Hacker X-5 Pro ESC

int escPin = 9;
int arm = 1000; // pulse width in microseconds (Start Signal)

void setup() 
{  
// It appears that the ESC will accept a range of values for the arming
// sequence. This provides 10 pulses with a pulse width of 1000 us with
// with a 20 ms delay between pulses.

  pinMode(escPin, OUTPUT);
  for (int count = 0; count < 10; count++){
  digitalWrite(escPin, HIGH);
  delayMicroseconds(arm);
  digitalWrite(escPin, LOW);
  delay(20);
  }
}

void loop()
{


}
This second sketch adds to the first one and both arms the ESC and then provides a pulse train to operate the motor at a constant speed. This also works as expected.
Code: Select all
// This sketch arms the Hacker X-5 Pro ESC and
// then runs the attached A-10 Hacker brushless motor
// at a constant speed.

int escPin = 9;
int arm = 1000; // pulse width in microseconds for arming
int speedvalue = 1350; // pulse width in microseconds for operation

void setup() 
{
  
// It appears that the ESC will accept a range of values for the arming
// sequence. This provides 10 pulses with a pulse width of 1000 us with
// with a 20 ms delay between pulses.

  pinMode(escPin, OUTPUT);
  for (int count = 0; count < 10; count++){
  digitalWrite(escPin, HIGH);
  delayMicroseconds(arm);
  digitalWrite(escPin, LOW);
  delay(20);
  }
}

void loop()
{

// Once armed the ESC needs to receive a pulse train to operate the 
// the motor. The motor speed is controlled by the duration of the
// pulse width.
// This simple loop provides a pulses width a width of 1350 us and a 
// separation of 20 ms.

    digitalWrite(escPin, HIGH);
    delayMicroseconds(speedvalue);
    digitalWrite(escPin, LOW);
    delay(20);

}
I would be happy with this, but I have looked over some forums and find many mentions of using the Servo library to control the ESC/motor combination. The only problem is that the only sketches that I can find refer to the Servo Sweep sketch that runs the motor speed up and down. If I arm the ESC using the above sketch and then upload the Sweep sketch to the Arduino, the motor runs as expected with the speed oscillating up and down.

I then wrote the following sketch to use the servo function to arm the ESC. This code works, but does not behave as the arm sketch above. This sketch arms the ESC, but if I then turn the power to the ESC off and then on, the ESC rearms without the sketch being run again. So something going on with the myservo.write that I am not getting...
Code: Select all
// This sketch uses the servo library to arm the Hacker X-5 Pro ESC.
// Once loaded this code will rearm the ESC after its power has been 
// turned off and on without being re-run. 
// What is going on????

#include <Servo.h> 
 
Servo myservo;
 
int arm = 46;    // supplies a pulse width of approximately 1000 us
 
void setup() 
{ 
  myservo.attach(9);  
  for (int count = 0; count < 10; count++){
    myservo.write(arm);              
  }
} 

void loop() 
{

} 
  
This last sketch arms the ESC using the servo functions but does not result in operation of the motor. I would be okay with this except that when I look at the pulse train on a scope, they look virtually identical. I have just read that the ESC may need to run from zero up to the desired speed which mimics the action of an RC controller - this makes sense and I will try it later today.
Code: Select all
// This sketch uses the servo library to arm the Hacker X-5 Pro ESC.
// Once loaded this code will rearm the ESC after its power has been 
// turned off and on without being re-run. 
// What is going on????

#include <Servo.h> 
 
Servo myservo;
 
int arm = 46;    // supplies a pulse width of approximately 1000 us
int speedvalue = 100; // supplies a pulse width of approximatley 1350 us
 
void setup() 
{ 
  myservo.attach(9);  
  for (int count = 0; count < 10; count++){
    myservo.write(arm);              
  }
} 

void loop() 

// This loop produces a pulse train but it does not result in 
// the ESC operating the brusless motor.

{
  myservo.write(speedvalue);  

} 
  

  
If any one has any insight to what is going one within the code, I would appreciate your feedback. I would also be interested in seeing a sketch that uses the servo library to operate the ESC/motor at a constant speed.
By navillus5
#142312
As a follow up to my questions. I think I have solved most of my issues. The attached code controls the ESC/motor setup using the servo library.
Code: Select all
// This sketch uses the servo library to arm the Hacker X-5 Pro ESC.

#include <Servo.h> 
 
Servo esc; // Define the ESC as a servo object
 
int arm = 1000;    // defines pulse width of 1000 us
int speedvalue;
int steady = 300;
int initiate = 0;
 
void setup() 
{
  esc.attach(9);  
  esc.writeMicroseconds(arm); // This command sends a pulse train
                              // from pin 9 that continues until 
                             // the pin is called to do something else. 
 
 /*  Once armed the setup could also be used to specify the 
     run speed of the motor. The commented out lines provide 
     a 2 second delay between changes in speed.
  delay(2000);
  esc.writeMicroseconds(1200);
  delay(2000);
  esc.writeMicroseconds(1300);
  delay(2000);
  esc.writeMicroseconds(1400);
  delay(2000);
 */
} 

void loop() 
{
  
/*
  Calls a sub to throttle up motor from 0 rpm to a steady running value.
  The if statement is used to run the throttle up once.
*/ 
  if (initiate < 1){
    throttleUp();
    initiate = 1;
  }
 
 /*
    You can then change the speed in the main loop by changing the pulse width.
    If nothing else is going on in the loop, a delay must be included otherwise
    the servo writeMicroseconds is called to fast and there is not the proper
    time delay between pulses (I think this is the case...need to check this 
    on a scope. The minimum delay is 15 ms. The lines below use a 1 second delay
    between speed settings. The loop also causes this to be run once
*/ 

  if (initiate < 2){
    for (int count = 0; count < 5; count++){
      speedvalue = speedvalue+50;
      esc.writeMicroseconds(speedvalue);
      delay(1000);
    }
    for (int count = 0; count < 12; count++){
      speedvalue = speedvalue-50;
      esc.writeMicroseconds(speedvalue);
      delay(1000);
    }
    initiate = 2;
  }
  
  esc.detach();  // Disengage ESC from pin

}  
  
  
//**************************************************

void throttleUp(){
  speedvalue = arm;
  for (int count = 0; count < steady; count++){
    esc.writeMicroseconds(speedvalue);
    speedvalue = speedvalue + 1;
    delay(15);
  }}
   
By afar
#143121
i am friends with the same dilemma that you: Controls brusheless motor with arduino. I have some codes here that works with an engine speed ranging from 0 to 100% as this:
Code: Select all
#include <Servo.h>

Servo myservo;

void arm(){
  // arm the speed controller, modify as necessary for your ESC  
  setSpeed(0);
  delay(1500); //delay 1 second,  some speed controllers may need longer
}

void setSpeed(int speed){
  // speed is from 0 to 100 where 0 is off and 100 is maximum speed
  //the following maps speed values of 0-100 to angles from 0-180,
  // some speed controllers may need different values, see the ESC instructions
  int angle = map(speed, 0, 100, 0, 180);
  myservo.write(angle);    
}

void setup()
{
  myservo.attach(2);
  arm();  
}


void loop()
{
  int speed;

  // sweep up from 0 to to maximum speed in 20 seconds
  for(speed = 0; speed <= 100; speed += 5) {
    setSpeed(speed);
    delay(1000);
  }
  // sweep back down to 0 speed.
  for(speed = 95; speed > 0; speed -= 5) {
    setSpeed(speed);
    delay(1000);
  }
  setSpeed(0);  
  delay(5000); // stop the motor for 5 seconds
}  
but I want to control 4 brushless motors for my quadricoptero: I'm working on sketches:
Code: Select all
int motorPin = 8;
int motor2Pin = 6;
int motor3Pin = 4;
int motor4Pin = 2;

#define MINCOMMAND 1000
#define MAXCOMMAND 1600
#define DIRCOMMAND 2000

void setup()  
{ 
  Serial.begin(9600);

  pinMode(motorPin , OUTPUT);
  pinMode(motor2Pin , OUTPUT);
  pinMode(motor3Pin , OUTPUT);
  pinMode(motor4Pin , OUTPUT); 
  arm();
} 


void arm()
{
  analogWrite(motorPin, MINCOMMAND / 8);
  analogWrite(motor2Pin, MINCOMMAND / 8);
  analogWrite(motor3Pin, MINCOMMAND / 8);
  analogWrite(motor4Pin, MINCOMMAND / 8);
}


void loop()  { 
  for(int MC = MINCOMMAND ; MC <= MAXCOMMAND; MC +=10) { 
    analogWrite(motorPin, MC / 8);  
    analogWrite(motor2Pin, MC / 8); 
    analogWrite(motor3Pin, MC / 8);
    analogWrite(motor4Pin, MC / 8); 

    delay(500);              
  } 



  int dir,a=10;


  Serial.println(" D para direita, E para esquerda F para frente e W para traseira ");

  if (Serial.available() >0) { //existem caracteres para ler

    dir=Serial.read();

    Serial.println(a);
    //altera a velocidade consoante o caracter. 
  }


  if (dir == 'a') 
  {
    for(int MC = MAXCOMMAND ; MC <= DIRCOMMAND ; MC +=10)
    { 
      analogWrite(motorPin, MC / 8);  
      Serial.println(dir);
    }
  }

  if (dir == 's') 
  {
    for(int MC = MAXCOMMAND ; MC <= DIRCOMMAND ; MC +=10)
    { 
      analogWrite(motor2Pin, MC / 8);
      Serial.println(dir);
    }
  }

  if (dir == 'w')
  {
    for(int MC = MAXCOMMAND ; MC <= DIRCOMMAND ; MC +=10)
    { 
      analogWrite(motor3Pin, MC / 8); 
      Serial.println(dir);
    }
  }

  if (dir == 'd') 
  {
    for(int MC = MAXCOMMAND ; MC <= DIRCOMMAND ; MC +=10)
    { 
      analogWrite(motor4Pin, MC / 8); 
      Serial.println(dir); 
    }
  }
} 




it contains an error in the loop that still can not understand.