Como hacer funcionar un motor de Disco Duro

Hola, tengo un motor de disco duro que me gustaría hacer andar.

Hice la conexión como adjunté en la imagen, y con el Arduino controlo los transistores, así logro que las bobinas (las nombré A,B y C) tengan el siguiente orden:

  1. A+, B-
  2. A+, C-
  3. B+, C-
  4. B+, A-
  5. C+, A-
  6. C+, B-

Si lo hago con un delay de 1000 ms (1 segundo) funciona perfecto, se nota cada paso (de 15º) sin ninguna interrupción.

Ahora cuando lo acelero de a poco (disminuyo el delay) comienza a girar trabado y al llegar una velocidad de rotación directamente se para. (pero las bobinas se siguen alternando)

Estan conectados a 12 Volt.

¿Alguna idea? ¿que puedo hacer?
Gracias

Post datasheet for HD motor.
two motor wires are NOT connected
Without motor datsheet impossible to determine problem.

(neccitamos documento de factura de motor disco duro para saber qual son los dos primero conneciones de la motor ( negto y rojo)

Suena a problemas de atiempamiento.

El tiempo de un delay no es 100% exacto; en tiempo de ejecución la duración varía un poco a pesar de usar el mismo valor en código.
Esa ligera varianza es la que acaba trabando el movimiento del motor.

Para lograr una mejor precisión de encendido/apagado, tienes dos opciones:

  • Usar delayMicroseconds con manipulación de puertos.
  • Cambiar el estado de los pines mediante interrupciones por timer, y manipulación de puertos (la mejor precisión que un Arduino puede ofrecer).

Si no funciona ninguna de las anteriores, entonces habría que estudiar la "datasheet" de los transistores.

Gracias por las respuestas

Adjunto la imagen, es un motor como ese (no busqué el datasheet), No es el de la imagen que les pasé (el simulador no tenia el mismo modelo que yo).

Les dejo el código que utilicé:

[tr]
[td]
int t=200;
int AM=8;
int BM=9;
int CM=10;
int Am=3;
int Bm=4;
int Cm=5;

void setup(){  
pinMode(Am,OUTPUT);
pinMode(Bm,OUTPUT);
pinMode(Cm,OUTPUT);
pinMode(AM,OUTPUT);
pinMode(BM,OUTPUT);
pinMode(CM,OUTPUT);
}


void loop() {
digitalWrite(Am,LOW);
digitalWrite(Bm,HIGH);
digitalWrite(Cm,LOW);
digitalWrite(AM,HIGH);
digitalWrite(BM,LOW);
digitalWrite(CM,LOW);
delay(t);
digitalWrite(Am,LOW);
digitalWrite(Bm,LOW);
digitalWrite(Cm,HIGH);
digitalWrite(AM,HIGH);
digitalWrite(BM,LOW);
digitalWrite(CM,LOW);
delay(t);
digitalWrite(Am,LOW);
digitalWrite(Bm,LOW);
digitalWrite(Cm,HIGH);
digitalWrite(AM,LOW);
digitalWrite(BM,HIGH);
digitalWrite(CM,LOW);
delay(t);
digitalWrite(Am,HIGH);
digitalWrite(Bm,LOW);
digitalWrite(Cm,LOW);
digitalWrite(AM,LOW);
digitalWrite(BM,HIGH);
digitalWrite(CM,LOW);
delay(t);
digitalWrite(Am,HIGH);
digitalWrite(Bm,LOW);
digitalWrite(Cm,LOW);
digitalWrite(AM,LOW);
digitalWrite(BM,LOW);
digitalWrite(CM,HIGH);
delay(t);
digitalWrite(Am,LOW);
digitalWrite(Bm,HIGH);
digitalWrite(Cm,LOW);
digitalWrite(AM,LOW);
digitalWrite(BM,LOW);
digitalWrite(CM,HIGH);
delay(t);
}
[/td]
[/tr]

Muy ineficiente este código así. Tienes un problema de retraso al enviar las señales a las bobinas. Usa la manipulación de puertos para ser más rápido.

Dale, voy a probar y les aviso como fué

Te lo facilito, hay que buscar en google: Arduino hard disk controller

/*
 * BLDC_congroller 3.1.1
 * by David Glaser
 *
 * The 3.x series of programs is for the ST L6234 3-Phase Motor Driver IC
 * 
 * Runs a disk drive motor clockwise
 * With regenerative braking
 * Motor speed and braking is controlled by a single potentiometer
 * Motor position is determined with three Hall-Effect sensors

 * The Arduino receives outputs from 3 hall sensors (pins 2,3,4) 
 * and converts their combination to 6 different commutation steps
 * PWM outputs on pins 9,10,11, at 32 kHz (corresponding to EN 1,2,3 respectively
 * 3 DO on pins 5,6,7 (IN 1,2,3)
 * Analog in 0 is connected to a potentiometer to change the PWM duty and change
 * between motoring and regenerative braking.
  * 0-499: braking
  * 500-523: coasting
  * 524-1023: motoring
  * There are many lines commented out that were used for debugging by
  * printing various values to the serial connection. 
 */
 
int HallState1; //Variables for the three hall sensors (3,2,1)
int HallState2;
int HallState3;
int HallVal = 1; //binary value of all 3 hall sensors

int mSpeed = 0; //speed level of the motor
int bSpeed = 0; //braking level
int throttle = 0; //this variable is used with analog in to measure the position of the throttle potentiometer

void setup() {
  pinMode(2,INPUT);    // Hall 1
  pinMode(3,INPUT);    // Hall 2
  pinMode(4,INPUT);    // Hall 3
  
// Outputs for the L6234 Motor Driver
  pinMode(5,OUTPUT);   // IN 1 
  pinMode(6,OUTPUT);   // IN 2
  pinMode(7,OUTPUT);   // IN 3     
  pinMode(9,OUTPUT);   // EN 1
  pinMode(10,OUTPUT);  // EN 2 
  pinMode(11,OUTPUT);  //  EN 3
 
  //Serial.begin(9600); //uncomment this line if you will use the serial connection
  // also uncomment Serial.flush command at end of program.

  /* Set PWM frequency on pins 9,10, and 11
  // this bit of code comes from 
  http://usethearduino.blogspot.com/2008/11/changing-pwm-frequency-on-arduino.html
  */  
  // Set PWM for pins 9,10 to 32 kHz
  //First clear all three prescaler bits:
  int prescalerVal = 0x07; //create a variable called prescalerVal and set it equal to the binary number "00000111"                                                       number "00000111"                                                      number "00000111"
  TCCR1B &= ~prescalerVal; //AND the value in TCCR0B with binary number "11111000"

  //Now set the appropriate prescaler bits:
  int prescalerVal2 = 1; //set prescalerVal equal to binary number "00000001"
  TCCR1B |= prescalerVal2; //OR the value in TCCR0B with binary number "00000001"
  
  // Set PWM for pins 3,11 to 32 kHz (Only pin 11 is used in this program)
  //First clear all three prescaler bits:
  TCCR2B &= ~prescalerVal; //AND the value in TCCR0B with binary number "11111000"

  //Now set the appropriate prescaler bits:
 
  TCCR2B |= prescalerVal2; //OR the value in TCCR0B with binary number "00000001"//First clear all three prescaler bits:
  
}

void loop(){
  
   //time = millis();
  //prints time since program started
  //Serial.println(time);
  //Serial.print("\n");
  
  throttle = analogRead(0); //value of the throttle potentiometer
  mSpeed = map(throttle, 512, 1023, 0, 255); //motoring is mapped to the top half of potentiometer
  bSpeed = map(throttle, 0, 511, 255, 0);    // regenerative braking on bottom half of pot
  //mSpeed = 100; //used for debugging

  HallState1 = digitalRead(2);  // read input value from Hall 1
  HallState2  = digitalRead(3);  // read input value from Hall 2
  HallState3  = digitalRead(4);  // read input value from Hall 3
  //digitalWrite(8, HallState1);  // LEDs turned on when corresponding sensor is high - originally used for debugging
  //digitalWrite(9, HallState2);
  //digitalWrite(10, HallState3);
   
  HallVal = (HallState1) + (2*HallState2) + (4*HallState3); //Computes the binary value of the 3 Hall sensors


// Commutation for Motoring
// Each binary number has a case that corresponds to different transistors being turned on
// Bit Math is used to change the values of the output
// For tutorial on bitmath with the Arduino: http://www.arduino.cc/playground/Code/BitMath
// PORTD contains the outputs for the IN pins on the L6234 driver
// that determine whether the upper or lower transistor of each phase is used
// The outputs for the EN pins are controlled by the Arduino command analogWrite, which
// sets the duty of the PWM (0 = OFF, 255 = ON or throttle value that is controlled by the potentiometer).

  if (throttle > 511){
      switch (HallVal) 
       {
        case 3:
          //PORTD = B011xxx00;  // Desired Output for pins 0-7 xxx refers to the Hall inputs, which should not be changed
          PORTD  &= B00011111;
          PORTD  |= B01100000;  // 

          analogWrite(9,mSpeed); // PWM on Phase A (High side transistor)
          analogWrite(10,0);  // Phase B off (duty = 0)
          analogWrite(11,255); // Phase C on - duty = 100% (Low side transistor)
          break;
        case 1:
          //PORTD = B001xxx00;  // Desired Output for pins 0-7
          PORTD  &= B00011111;  // 
          PORTD  |= B00100000;  // 

          analogWrite(9,mSpeed); // PWM on Phase A (High side transistor)
          analogWrite(10,255); //Phase B on (Low side transistor)
          analogWrite(11,0); //Phase B off (duty = 0)
          break;
        case 5:
          //PORTD = B101xxx00;  // Desired Output for pins 0-7
          PORTD  &= B00011111;  //
          PORTD  |= B10100000;

          analogWrite(9,0);
          analogWrite(10,255);
          analogWrite(11,mSpeed); 
          break;
        case 4:  
          //PORTD = B100xxx00;  // Desired Output for pins 0-7
          PORTD  &= B00011111;
          PORTD  |= B10000000;  // 

          analogWrite(9,255);
          analogWrite(10,0);
          analogWrite(11,mSpeed);
          break;
        case 6:
        //PORTD = B110xxx00;  // Desired Output for pins 0-7
          PORTD  &= B00011111;
          PORTD = B11000000;  // 

          analogWrite(9,255);
          analogWrite(10,mSpeed);
          analogWrite(11,0);
          break;
        case 2:
          //PORTD = B010xxx00;  // Desired Output for pins 0-7
          PORTD  &= B00011111;
          PORTD  |= B01000000;  // 

          analogWrite(9,0);
          analogWrite(10,mSpeed);
          analogWrite(11,255);
          break;
       }  
     }
     
   // Commutation for Regenerative Braking
   // PORTD (Outputs for IN pins on L6234) pins are always low so only the
   // lower transistors on each phase are used
   // upper transistors are always off during regen. braking.
   else{
          //PORTD = B000xxx00;  // Desired Output for pins 0-7
            PORTD  &= B00011111;
            PORTD  |= B00000000;  //
          switch (HallVal) 
         {
          case 3:
            analogWrite(9,bSpeed);
            //analogWrite(9,0);
            analogWrite(10,0);
            analogWrite(11,0);
            break;
          case 1:
            analogWrite(9,bSpeed);
            analogWrite(10,0);
            analogWrite(11,0);
            break;
          case 5:
            analogWrite(9,0);
            analogWrite(10,0);
            analogWrite(11,bSpeed);
            break;
          case 4:  
            analogWrite(9,0);
            analogWrite(10,0);
            analogWrite(11,bSpeed);
            break;
          case 6:
            analogWrite(9,0);
            analogWrite(10,bSpeed);
            analogWrite(11,0);
          break;
        case 2:
          analogWrite(9,0);
          analogWrite(10,bSpeed);
          analogWrite(11,0);
          break;
       }
   }   
   //time = millis();
  //prints time since program started
  //Serial.println(time);
  //Serial.print("\n");
  //Serial.flush(); //uncomment this if you will use serial port for debugging
}

Hola surbyte, gracias por la ayuda pero prefiero hacerlo sin un controlador, la idea es gastar el mínimo posible

carlosjq10, empleé el método que me dijiste e hice lo siguiente:

int t=100;

void setup() {
DDRB=B111111;
}

void loop() {
PORTB=B100100;
delay(t);
PORTB=B100100;
delay(t);
PORTB=B101000;
delay(t);
PORTB=B000110;
delay(t);
PORTB=B011000;
delay(t);
PORTB=B100001;
delay(t);
}

Pero sigue sucediendo exactamente lo mismo, ningún cambio

Gracias por las respuestas

Carga el código que te suministro Surbyte y verifica si se te despeja el problema.

Con todo respeto, sería completamente en vano ya que el programa ese está diseñado para ser utilizado con el Circuito Integrado "ST L6234" el cuál yo no poseo y acá no venden

Lupax7:
carlosjq10, empleé el método que me dijiste [...]
Pero sigue sucediendo exactamente lo mismo, ningún cambio

Hombre, que sigues usando delay?
Ya te dije que la precisión no es 100%; que por eso se desatiempa.

Creo que es hora de que vayas generado el retraso mediante interrupción por timer.
No es difícil hacerlo gracias a la librería TimerOne.
Solo tienes que establecer cada cuántos microsegundos (milisegundos * 1000) se deben cambiar el estado de los pines, y la función que lo realiza.

Ah dale disculpá! no había interpretado bien esa parte, ahí lo pruebo

No, ningún cambio, probé utilizando la librería "Timer1" y control de puertos y todo sigue exactamente igual, para descartar probaré con otro motor.

Seguro? A menos que la interrupción la hayas creado demasiado larga, o el tiempo no haya sido el correcto.

Yo esperaba un código así:

#include <TimerOne.h>
volatile byte accion = 0;

void setup() {
  DDRB = B111111;
  Timer1.initialize();
  cli();
  Timer1.attachInterrupt(cambio, 100000); // Se supone que cambia cada 100 milisegundos
  sei();
}

void cambio() {
  switch (accion) {
    case 0:
      PORTB = B100100; break;

    case 1:
      PORTB = B100100; break;

    case 2:
      PORTB = B101000; break;

    case 3:
      PORTB = B000110; break;

    case 4:
      PORTB = B011000; break;

    case 5:
      PORTB = B100001;
  }
  accion ++;

  if (accion == 6)
    accion = 0;
}

void loop() {
  // Vacío a menos que tengas otros planes
}