Friday, February 21, 2014

Revitalizing old hard drive motors using Arduino

Hard drives use brushless motors (BLDC motors) 

Brushless motors are more durable than ordinary carbon brush motors because they lack a commutator (which is a brush rubbing a pair of cyclic magnets to reverse the direction of current)

For brushless motors they use electronic switches to reverse the current.
In BLDC motors the coils are wrapped on the stator, while the rotor has a permanent magnet attached to it.

However, it should be noted that a brushless motor cannot be driven by ordinary Direct Current.

This article tries to demonstrate how to run a Hard drive scraped BLDC motors by using a microcontroller/ rapid prototyping board Arduino.

This method is based on this video
http://www.youtube.com/watch?v=CMz2DYpos8w

Principles

Use Arduino sends pulses to Darlington Transistors.
There are 3 phases in the motor. Each phase is controlled by one Arduino Pin. 
For example, 

---------time---------------->
phase1pin:100100100
phase2pin:010010010
phase3pin:001001001
Fig 1

where 1 = High signal in Arduino pin, causing Darlington Transistor to supply current to the motor.

Scraping hard drive motors

You need:

Torx screw drivers (especially T8)
common screw drivers

Technique: No special attentions needed. Just unscrew them all. Some screws may be hidden under the label.


(There is a ribbon connected to the drive; DO NOT PULL it off because there are very thin wires which are connected to the coils of the motor inside. I suggest soldering additional wires like the photo above)

Testing which lead is common

Fig 2
Usually a hard disk BLDC is a 3-phase BLDC, which has 3 phases + 1 common = 4 wires

Use a multimeter to test for resistance on those 4 points:

A common lead + coil = 1x ohm
A coil + a coil = 2x ohm (Fig.2)

Then solder extending wires. In Fig. 1, the common wire is in black color.

Connecting to Arduino

Arduino:
- We need 3 digital pins to send the signal, say pin 2,3,4

Breadboard components:
- 1k ohm resistors *3
- TIP122 darlington pairs *3
- diode 1N4004 *3
- battery power 5 to 12V

Connect them as shown in Fig. 3 and Fig 4

Fig 3


Fig 4




Coding Arduino

Simple switching


const int phase1pin = 2;
const int phase2pin = 3;
const int phase3pin = 4;
const int delayTime = 6000; // microsecs

void setup(){
  Serial.begin(9600);
  pinMode(phase1pin, OUTPUT);
  pinMode(phase2pin, OUTPUT);
  pinMode(phase3pin, OUTPUT);
}

void loop(){
  switchStep(1);
  switchStep(2);
  switchStep(3);
}

void switchStep(int stage){
  switch(stage){
    case 1:
      digitalWrite(phase1pin, HIGH);
      digitalWrite(phase2pin, LOW);
      digitalWrite(phase3pin, LOW);
      delayMicroseconds(delayTime);
      break;
    case 2:
      digitalWrite(phase1pin, LOW);
      digitalWrite(phase2pin, HIGH);
      digitalWrite(phase3pin, LOW);
      delayMicroseconds(delayTime);
      break;
    case 3:
      digitalWrite(phase1pin, LOW);
      digitalWrite(phase2pin, LOW);
      digitalWrite(phase3pin, HIGH);
      delayMicroseconds(delayTime);
      break;
  }
}

Improved version

The phases overlap with the previous phase by 1/4 cycle to improve the rotation transition.
In this version the motor is slowly accelerating to the max speed.

Improved switching



const int phase1pin = 2;
const int phase2pin = 3;
const int phase3pin = 4;
float holdTime = 50000; // microsecs
const unsigned long minHoldTime = 1300;

unsigned long p1start,
              p1end,
              p2start,
              p2end,
              p3start,
              p3end;

void setup(){
  Serial.begin(9600);
  pinMode(phase1pin, OUTPUT);
  pinMode(phase2pin, OUTPUT);
  pinMode(phase3pin, OUTPUT);
  p1start = micros();
  digitalWrite(phase1pin, HIGH);
}


void chkP1(){
  unsigned long currentTime = micros();
  unsigned long td = currentTime - p1start;
  unsigned long refractory = 2.25*holdTime;
  if(digitalRead(phase1pin)){
    if(td > holdTime){
      digitalWrite(phase1pin, LOW);
      p1end = currentTime;
    }
  }else if(td > refractory){
    digitalWrite(phase1pin, HIGH);
    p1start = currentTime;
  }
}

void chkP2(){
  unsigned long currentTime = micros();
  unsigned long td = currentTime - p1start;
  if(digitalRead(phase2pin)){
    if(td > 1.75*holdTime || td < 0.75*holdTime){
      digitalWrite(phase2pin, LOW);
      p2end = currentTime;
    }
  }else if(td > 0.75*holdTime && td < 1.75*holdTime){
    digitalWrite(phase2pin, HIGH);
    p2start = currentTime;
  }
}

void chkP3(){
  unsigned long currentTime = micros();
  unsigned long td = currentTime - p1start;
  if(digitalRead(phase3pin)){
    if(td > 0.25*holdTime && p3start < p1start){
      digitalWrite(phase3pin, LOW);
      p3end = currentTime;
    }
  }else if(td > 1.5*holdTime){
    digitalWrite(phase3pin, HIGH);
    p3start = currentTime;
  }
}

void loop(){
  chkP1();
  chkP2();
  chkP3();
  delayMicroseconds(100);
  if(holdTime >= minHoldTime){
    holdTime -= 0.5;
  }
}


That's it.

For my 5400rpm hard disk motor, I used 3.7*3 = 11.1V
The min cycle period = 1.3ms
i.e. it takes about 1.3*2.25*2 = 5.85ms for 1 rev
=> about 10k rpm

Any further decrease in cycle period leads to an halt.

Increasing voltage allows shorter cycle period (prabably due to a stronger torque => higher rotation speed)

Addition info:

I dismantled / disassembled one of the BLDC motor, shown below:
The 4 wires were accidentally broken by me. So I punched the center of the axle to separate the rotor   
              

Please ignore the bearing in the middle. It is totally irrelevant and it belongs to my other projects.