RepRap Brushless DC Spindle Control

I need a tiny spindle for a CNC Build Club project I am working on.  I decided to use a Brushless DC  Hobby motor.  These motors have a huge amount of power for their size and cost.   I want the machine to be able to turn the spindle on and set the speed via GCode so I spent some time testing this out.

You need to power these motor with special 3 phase controller.  These are typically controlled like a hobby servo, so the interface is a little different than a typical spindle motor.  The machine is going to be a delta type machine, so I will be using RepRap firmware.  Marlin was selected over Repetier because it has built in servo control.

Part Used

The motor is a Turnigy Track Star motor.  I like it because it is sealed and air cooled and it is 550W.  That is over 2/3hp.

ttsmn

This is the Brushless Electronic Speed Control (BESC) I used.  It is a Turnigy Plush 30A.  It has a battery eliminator circuit, which is basically a 5V output to eliminate the need for a battery for the RF receiver and servos.  This is the thin red wire on the 3 wire connector.  This should not be used because the Arduino has it’s own 5V supply.

TR-P30A

 

The controller I used is an Azteeg X3.

800px-Azteeg_x3

 Hobby Servo PWM

Hobby servos use pulse width to control the position of the servo.  You basically use a pulse from about 1ms (off) to 2ms (full speed) to control the servo.  This must be repeated about every 20ms.

untitled

 

The BESC has a safety feature where you must turn it on in a special sequence.  You must set the pulse length to minumum (1ms), turn on the motor power supply, wait until you hear the startup beeps, then a few more beeps which tell you the count of batteries connected.  You can then vary the pulse length to control the speed.

Basic Arduino Control.

schm1

schm2

The first thing I worked on was basic manual control using an Arduino.  I started with the “Servo…Knob” example that comes the Arduino IDE.  I modified it a bit to match the pins I was using.  It reads the voltage on a potentiometer and uses the value to set the pulse length.  The sequence was, turn the knob to the minimum, turn on the power supply, wait for the startup beeps, then use the pot to control the speed.  At first it did not work.  I looked at the servo library code and found it used 540 microseconds for the minimum pulse and 2400 microseconds for the maximum pulse length.  I switched from myservo.write(val) to myservo.writeMicroseconds(val) to use the actual time values and it worked.

Here is the code.

// based on the servo...knob example.
#include <Servo.h> 

// define the min and max because the servo library has a wider range 
#define MIN_PULSE 1000
#define MAX_PULSE 2000

Servo myservo; // create servo object to control a servo 

int potpin = 0; // analog pin used to connect the pot
int val; // variable to read the value from the analog pin 

void setup() 
{ 
 Serial.begin(9600); 
 myservo.attach(3); // attaches the servo on pin 3

} 

void loop() 
{ 
 val = analogRead(potpin); // reads potentiometer (value between 0 and 1023) 
 val = map(val, 0, 1023, MIN_PULSE, MAX_PULSE); // scale between 1ms and 2ms
 Serial.println(val); // show the values
 myservo.writeMicroseconds(val); // sets the servo using microseconds 
 delay(20); // wait a bit
}

Automatic Startup Using Arduino

The next step was to try semi-automate the startup sequence.  In the previous step, I found that holding the pulse to the minimum length for about 4 seconds was long enough.  This code would test that.  After startup the Arduino output the minimum pulse, lit an LED as a signal to turn on the power supply, then wait for 4 seconds.

// based on the servo...knob example.
#include <Servo.h> 

// define the min and max because the servo library has a wider range 
#define MIN_PULSE 1000
#define MAX_PULSE 2000

Servo myservo; // create servo object to control a servo 

int potpin = 0; // analog pin used to connect the potentiometer
int val; // variable to read the value from the analog pin 
int led = 13; // led pin

void setup() 
{ 
 pinMode (led, OUTPUT);

 myservo.attach(3); // attaches the servo on pin 3 to the servo object
 delay(1000); // wait a bit for the human to get ready

 myservo.writeMicroseconds(MIN_PULSE); // go to the low end
 digitalWrite(led, HIGH); // signal p/s turn on
 delay(4000); // wait a bit
 digitalWrite(led, LOW); // ok to control with pot
} 

void loop() 
{ 
 val = analogRead(potpin); 
 val = map(val, 0, 1023, MIN_PULSE, MAX_PULSE); 
 myservo.writeMicroseconds(val);
}

RepRap Control

schm3

The plan was to use the servo control feature to adjust the speed and the heater control circuit to control the power. Here are the changes I had to make to Marlin. Search for these lines in the files indicated and change them.

Overview: The temp sensors are all disabled.  You need to remove HEATER_BED_PIN from the array of SENSITIVE_PINS or the M42 command will ignore it.  Setup what pin you want for the servo output.  I changed the default pulses to comply with what the BESC wanted.

in file configuration.h
#define MOTHERBOARD 67  //azteeg X3
#define TEMP_SENSOR_0 0
#define TEMP_SENSOR_1 0
#define TEMP_SENSOR_2 0
#define TEMP_SENSOR_BED 0
NUM_SERVOS = 1
in file pins.h
#define SERVO0_PIN         31
remove HEATER_BED_PIN, from SENSITIVE_PINS
in file servo.h
#define MIN_PULSE_WIDTH 1000 // the shortest pulse sent to a servo
#define MAX_PULSE_WIDTH 2000 // the longest pulse sent to a servo
#define DEFAULT_PULSE_WIDTH 1000 // default pulse width

I used Repetier host to talk to the controller.   Here is the GCode I used to test.  It runs the motor for 10 seconds.

; set speed to zero
M280 P0 S0
; power up speed controller
M42 P8 S254
; wait for startup tones
G4 P4000
; go to full speed
M280 P0 S180
; run for 10 secs
G4 P10000
; turn speed to 0
M280 P0 S0
; turn off power
M42 P8 S0

Problems

It turns out I was not able to get the bed heater circuit to directly control the power to the BESC.  The bed heater circuit switches the ground side of the the circuit and the positive voltage is always present.  The controller would not turn off.  It was using the servo ground wire, which is probably not rated for that.  I had to find a way to switch the positive voltage.

Solution

The easiest way to do this was with a relay.  I wired an automotive relay to the bed circuit.  I put a flyback diode across the relay to protect the bed heater circuit.  It all works perfectly now.

Update

12-/27/2013 I tried hooking both grounds to the heater power circuit and it pulled ground from the servo signal pin.  That can’t be good for the BESC or the CPU, so back the the ugly relay.

 

Share and Enjoy:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks

3 Responses to “RepRap Brushless DC Spindle Control”


  1. Adam

    This is really cool, have you looked into how to attach the chuck to the motor as well? Also this is a 2400 Kv motor, you will end up with incredible RPMs, have you looked at ways to reduce this to something more reasonable?

  2. bdring

    The motor has a 1/8″ shaft and the end mills I plan to use are all 1/8″, so I am just going to use a simple shaft coupler.

    The speed is OK for what I plan to do, but I did make this thing a while ago.

    http://www.buildlog.net/blog/2011/09/new-brushless-dc-router-spindle/

  3. Mike

    Using a higher-torque, lower Kv motor would mean you get more control without having to worry too much about runaway RPM – or having to gear it down.

    Some of the water-cooled boat motors are ideal – with voltages up to 40V (11S) at 730kv, you can drive it at 30kRPM for ever.

*