Vaivén de un flap con motor paso a paso

Buenos días!
Estoy trasteando los motores paso a paso, para mi ejemplo uso uno arduino uno y con un motor 12v paso a paso ssa512t045 y driver uln2003.
Lo que estoy intentando sin éxito, es que en función por ejemplo de recibir 1 o 2 en serial, haga una cosa repetitivamente (opcion1) o quedarse fijo en un grado predefinido. El problema en que me encuentro, es que la opción 1 debería mover desde la posición 0 del motor mover indefinidamente en modo "vano" de 0 a 90º por ejemplo, mientras que la opción 2 lo dejaría fijo en los grados 45º. No sé como hacerlo, pierdo la referencia del punto 0... Os agradecería algo de ayuda, además que probablemente se pueda simplificar muchísmo más o usar otras instrucciones. ahí va:

int retardo=5;          // Tiempo de retardo en milisegundos (Velocidad del Motor)
int dato_rx;            // valor recibido en grados
int numero_pasos = 0;   // Valor en grados donde se encuentra el motor
String leeCadena;       // Almacena la cadena de datos recibida
int input;
void setup() {                
Serial.begin(9600);     // inicializamos el puerto serie a 9600 baudios
pinMode(11, OUTPUT);    // Pin 11 conectar a IN4
pinMode(10, OUTPUT);    // Pin 10 conectar a IN3
pinMode(9, OUTPUT);     // Pin 9 conectar a IN2
pinMode(8, OUTPUT);     // Pin 8 conectar a IN1

}
//***************************************************************************
void paso_der(){         // Pasos a la derecha
 digitalWrite(11, LOW); 
 digitalWrite(10, LOW);  
 digitalWrite(9, HIGH);  
 digitalWrite(8, HIGH);  
   delay(retardo); 
 digitalWrite(11, LOW); 
 digitalWrite(10, HIGH);  
 digitalWrite(9, HIGH);  
 digitalWrite(8, LOW);  
   delay(retardo); 
 digitalWrite(11, HIGH); 
 digitalWrite(10, HIGH);  
 digitalWrite(9, LOW);  
 digitalWrite(8, LOW);  
  delay(retardo); 
 digitalWrite(11, HIGH); 
 digitalWrite(10, LOW);  
 digitalWrite(9, LOW);  
 digitalWrite(8, HIGH);  
  delay(retardo);  
}

void paso_izq() {        // Pasos a la izquierda
 digitalWrite(11, HIGH); 
 digitalWrite(10, HIGH);  
 digitalWrite(9, LOW);  
 digitalWrite(8, LOW);  
  delay(retardo); 
 digitalWrite(11, LOW); 
 digitalWrite(10, HIGH);  
 digitalWrite(9, HIGH);  
 digitalWrite(8, LOW);  
  delay(retardo); 
 digitalWrite(11, LOW); 
 digitalWrite(10, LOW);  
 digitalWrite(9, HIGH);  
 digitalWrite(8, HIGH);  
  delay(retardo); 
 digitalWrite(11, HIGH); 
 digitalWrite(10, LOW);  
 digitalWrite(9, LOW);  
 digitalWrite(8, HIGH);  
  delay(retardo); 
}
        
void apagado() {         // Apagado del Motor
 digitalWrite(11, LOW); 
 digitalWrite(10, LOW);  
 digitalWrite(9, LOW);  
 digitalWrite(8, LOW);  
 }

 


void vaiven() {   //opcio vaiven
    dato_rx = (90 * 1.4222222222); // Ajuste de 512 vueltas a los 360 grados
    while (dato_rx>numero_pasos){   // Girohacia la izquierda en grados
       paso_izq();
       numero_pasos = numero_pasos + 1;
       
   }

  //leeCadena = "0";
   
   while (dato_rx<numero_pasos){   // Giro hacia la derecha en grados
        paso_der();
        numero_pasos = numero_pasos -1;
   }
  for(int cont=0; cont<150; cont++)
      paso_izq();
for(int cont=150; cont >= 0; cont--)
  paso_der();
 }

 void flap1() {   //opcio posiscio flap1
    dato_rx = (90 * 1.4222222222); // Ajuste de 512 vueltas a los 360 grados
    while (dato_rx>numero_pasos){   // Girohacia la izquierda en grados
       paso_izq();
       numero_pasos = numero_pasos + 1;
       
   }

  //leeCadena = "0";
   
   while (dato_rx<numero_pasos){   // Giro hacia la derecha en grados
        paso_der();
        numero_pasos = numero_pasos -1;
   }

while (75<numero_pasos){   // Giro hacia la derecha en grados
        paso_der();
        numero_pasos = numero_pasos -1;
}
while (75>numero_pasos){   // Girohacia la izquierda en grados
       paso_izq();
       numero_pasos = numero_pasos + 1;
       
   }

 }

//**************************************************************************

void loop() {
  
   if (Serial.available()>0){
 
    input=Serial.read();
 
    if (input=='1'){
 
      vaiven();}

        if (input=='2'){
 
     flap1();
 
    
    }
   }}
 
   

Estoy analizando tu código.

Asi que primera corrección es poner a cero numero_pasos antes de usarla en un while.
Mantener la orden requiere que transfieras la misma a una variable fuera del cambio que produce la lectura de un caracter serial.
entonces imagina que la variable la llamo accion.

// en las globales donde esta input modifica la linea asi
int input, accion;

// en el loop ahora usa esto
void loop() {
  
  if (Serial.available()>0){
      input = Serial.read();
      accion = input;
  }
  
  if (accion == '1'){
      vaiven();
  }
  if (accion == '2'){
      flap1();
  }
}

El código puede simplificarse, pero primero hazlo funcionar con los comentarios que te hice o veamos si sirven.
Esta es una versión mas simple
No veo que vaiven se diferencia de flap salvo por 150 y 75

#include <Arduino.h>

int retardo=5;          // Tiempo de retardo en milisegundos (Velocidad del Motor)
int dato_rx;            // valor recibido en grados
int numero_pasos = 0;   // Valor en grados donde se encuentra el motor
String leeCadena;       // Almacena la cadena de datos recibida
int input, accion;

void setup() {                
  Serial.begin(9600);     // inicializamos el puerto serie a 9600 baudios
  pinMode(11, OUTPUT);    // Pin 11 conectar a IN4
  pinMode(10, OUTPUT);    // Pin 10 conectar a IN3
  pinMode(9, OUTPUT);     // Pin 9 conectar a IN2
  pinMode(8, OUTPUT);     // Pin 8 conectar a IN1
}

//***************************************************************************
void paso_der(){         // Pasos a la derecha
  digitalWrite(11, LOW); 
  digitalWrite(10, LOW);  
  digitalWrite(9, HIGH);  
  digitalWrite(8, HIGH);  
  delay(retardo); 
  digitalWrite(11, LOW); 
  digitalWrite(10, HIGH);  
  digitalWrite(9, HIGH);  
  digitalWrite(8, LOW);  
  delay(retardo); 
  digitalWrite(11, HIGH); 
  digitalWrite(10, HIGH);  
  digitalWrite(9, LOW);  
  digitalWrite(8, LOW);  
  delay(retardo); 
  digitalWrite(11, HIGH); 
  digitalWrite(10, LOW);  
  digitalWrite(9, LOW);  
  digitalWrite(8, HIGH);  
  delay(retardo);  
}

void paso_izq() {        // Pasos a la izquierda
  digitalWrite(11, HIGH); 
  digitalWrite(10, HIGH);  
  digitalWrite(9, LOW);  
  digitalWrite(8, LOW);  
  delay(retardo); 
  digitalWrite(11, LOW); 
  digitalWrite(10, HIGH);  
  digitalWrite(9, HIGH);  
  digitalWrite(8, LOW);  
  delay(retardo); 
  digitalWrite(11, LOW); 
  digitalWrite(10, LOW);  
  digitalWrite(9, HIGH);  
  digitalWrite(8, HIGH);  
  delay(retardo); 
  digitalWrite(11, HIGH); 
  digitalWrite(10, LOW);  
  digitalWrite(9, LOW);  
  digitalWrite(8, HIGH);  
  delay(retardo); 
}
        
void apagado() {         // Apagado del Motor
  digitalWrite(11, LOW); 
  digitalWrite(10, LOW);  
  digitalWrite(9, LOW);  
  digitalWrite(8, LOW);  
}

void muevo_izq(int tmp){
  for (int cont=0; cont<tmp; cont++)
       paso_izq();
}

void muevo_der(int tmp){
  for (int cont=tmp; cont>0; cont--)
       paso_der();
}

void vaiven() {   //opcio vaiven
  dato_rx = 128;      // (90 * 1.4222222222); // Ajuste de 512 vueltas a los 360 grados
  muevo_izq(dato_rx);
  muevo_der(dato_rx);
  muevo_izq(150);
  muevo_der(150);
}

void flap1() {   //opcio posiscio flap1
  dato_rx = 128;        //   (90 * 1.4222222222); // Ajuste de 512 vueltas a los 360 grados
  muevo_izq(dato_rx);
  muevo_der(dato_rx);
  muevo_izq(75);
  muevo_der(75);
}

//**************************************************************************
void loop() {
  
  if (Serial.available()>0){
      input = Serial.read();
      accion = input;
  }
  
  if (accion == '1'){
      vaiven();
  }
  if (accion == '2'){
      flap1();
  }
}

muchas gracias Surbyte, la rutina vaiven me gira el eje 150 grados mientras que la flap 1 sólo 75. La diferencia está en como aplico estas rutinas, lo que intento hacer es que el vaiven esté repetidamente girando 150 y volviendo a 0, para volver a repetir el proceso hasta que lo pare. Mientras que flap 1 sólo va a buscar la posición de 75 grados para quedarse allí. creo que mi error está en como implementar eso el el loop.
gracias de antemano

Bueno ahora debería, mas alla de los cambios cosméticos, funcionar indefinidamente.
Lo has probado?

edito el anterior comentario que no lo expliqué bien... la opción 1 hace el vaivén completo dos ciclos, mientras que la opción 2 hace un vaivén completo de 150º para posteriormente hacer un ciclo correcto y pararse...

Modifica esto:

if (Serial.available()>0){
      input = Serial.read();
      accion = input;
     Serial.println("accion = " + String(accion));
  }
if (accion == '1'){
      Serial.println("Inicio vaiven");
      vaiven();
  }
  if (accion == '2'){
      Serial.println("Inicio flap1");
      flap1();
  }

Ahora podrás ver si accion se mantiene o no.

gracias de nuevo Surbyte, el resultado que me arroja es el siguiente:

accion = 49
Inicio vaiven
accion = 13
accion = 10

me pregunto si en vez de if no seria mejor un while?

Ya veo el problema
El problema es que cada vez que envias 1 2 ... 9, tmb se envia 0x0d y 0x13 que son unos caracteres de retorno de carro y fin de linea.
Asi que vamos a corregir esto asi

if (Serial.available()>0){
      input = Serial.read();
     if (input  != 0x0d || input =! 0x13)  {
         accion = input;
         Serial.println("accion = " + String(accion));
     }
  }
if (accion == '1'){
      Serial.println("Inicio vaiven");
      vaiven();
  }
  if (accion == '2'){
      Serial.println("Inicio flap1");
      flap1();
  }

muchas gracias por tu tiempo Surbyte, de veras... he probado el código nuevamente, corriguiendo el

input =! 0x13)

por

input != 0x13)

que al principio no lo veía! :slight_smile:
Pero se sigue comportando igual, es decir, al enviar "1", el flap se mueve 150º y retorna y ahí se queda quieto nomás. Si envío "2", el flap se mueve 75º y retorna y ya está :frowning:
Pero llegados a este punto, dudo si estoy planteando correctamente el código, es decir, lo que pretendo es tener la referencia 0 del motor, y al enviar "1" que haga vaivenes hasta 150º, si en mitad del proceso envío "2", el flap irá a buscar la posición de 75º. No entiendo que me falta o que estoy haciendo mal.

Se le deslizaron un par de errores, prueba

if (input  != 0x0D || input != 0x0A) {

Los caracteres a filtrar son '\r' (CR) y '\n' (LF) con código 0x0D (13 dec) y 0x0A (10 dec) respectivamente.

Otras formas de escribir las comparaciones serían

if (input  != 13 || input != 10) {
if (input  != '\r' || input != '\n') {

Entre otras.

Saludos

Hola.
Siempre ayuda que expongan lo más posible del proyecto o idea del conjunto de lo que se trata de hacer. No sé si va a formar parte de algo más complejo o si simplemente se trata de hacer lo que se ha planteado y no más. Si sólo se trata de lo que se ha planteado, sin que se busque hacer otras cosas a la vez, diré que no veo problema por usar delay() tal como se está usando. Pero si se quiere en un futuro integrarlo con más cosas, entonces puede que los delay() «molesten» en un futuro y habría que implementarlo con millis().

Otra duda que me asalta, es que no veo cómo se «posiciona en cero» o cómo sabe en qué posición está inicialmente. Es decir, cuando el Arduino arranca, no veo cómo sabe en qué posición o paso está el motor. Normalmente se suele utilizar un final de carrera que se acciona cuando el motor se encuentra al final de uno de sus recorridos. Lo que se hace inicialmente es mover el mecanismo hacia ese final de carrera y cuando se detecta que acciona el final de carrera, ya sabemos dónde está y digamos que se pone «a cero». A partir de ahí ya podemos mover el motor a las posiciones que deseemos.

Yo buscaría la forma de poner un final de carrera para posicionar el sistema en una posición conocida y a partir de ahí hacer el resto de cosas. Asimismo, usaría una máquina de estados para controlarlo.

La máquina de estado tendría un estado inicial de «posicionamiento inicial» que lo que haría es mover el motor en busca de accionar el final de carrera. Una vez encontrado el final de carrera establece que numero_pasos es cero y se puede quedar en espera a que le llegue la instrucción por el puerto serie. Si da igual dónde está ubicado inicialmente, entonces al inicio puede asumir que está en la «posición inicial» (numero_pasoses cero) y la máquina de estados quedar «a la espera a que le llegue una instrucción».

A la vez que tenemos la variable numero_pasos deberíamos de tener otra variable, llamémosla destino, que debería de tener el número del paso al que queremos que se mueva.

Inicialmente destino valdrá lo mismo que numero_pasos ya que el motor está donde queremos que esté (en la «posición inicial»). Una vez establecida de una forma u otra la «posición inicial», en todo momento se mira si numero_pasos es diferente de destino ya que si así fuera, habría que mover el motor en un sentido y otro e incrementar o decrementar numero_pasos para que se igualara al valor de destino. Con ello controlamos «fácilmente» el movimiento del motor. Sólo basta con establecer el valor deseado en destino en los momentos adecuados.

Cuando llega una instrucción, si se trata de la opción 2, podemos establecer el valor de destino con número adecuado para que se posicione en 45º y dejar que el motor se mueva mientras numero_pasos sea distinto de destino. Curiosamente, no hace falta cambiarlo de estado, puede continuar «a la espera a que le llegue una instrucción» ya que el motor se mueve mientras numero_pasos y destino tengan valores diferentes.

Pero si nos llega la opción 1, si la máquina de estados está «a la espera a que le llegue una instrucción» entonces ponemos en destino el valor para que el motor se posicione en 90º y la máquina de estados paras a «posicionando a 90º». Mientras está en ese estado, se espera a que numero_pasosy destino tengan el mismo valor. Entonces, cuando tengan el mismo valor, se cambia el valor de destino acorde a los 0º y la máquina de estados pasa al estado «posicionando a cero grados». Mientras está en ese estado, espera nuevamente a que numero_pasosy destino tengan el mismo valor y entonces vuelta a los 90º. Así consigues el vaivén.

Importante, mientras está en alguno de los estados «posicionando a 90º» o «posicionando a cero grados», cualquier petición de la opción 1 se ha de leer y descartar, sin hacerle caso, porque ya se encuentra «ejecutando» esa opción. Pero si llega la opción 2, entonces se ha de establecer el valor de los 45º en destino y se pasa al estado «a la espera a que le llegue una instrucción».

Te recomiendo que los veas y mires a ver si con ellos y con lo que he dicho te da idea de cómo hacerlo.

A mi me "suena" a persiana de aire acondicionado split. :thinking:

Saludos

Efectivamente, estoy mirando de recuperar mi bomba de calor, que por suerte no es inverter y quiero sustituir toda la electrónica y control por Arduino. De todos los controles los demás más o menos los tengo claros y creo que sabré hacerlos, el que más dificultades tenía por que nunca había trabajado con motores paso a paso es el flap, por eso mimso he empezado por lo que más dudas tenía. Obviamente no irá controlado por el serial, si no por IR, pero en plan pruebas para ir probando lo hago por serial... pues en eso estamos!

sigue sin funcionar correctamente... :pensive:

muchas gracias! la posición 0 siempre será la misma, obviamente imaginemos que se va la luz a media operación, está claro que al arrancar, arduino tomará como 0 allá dónde esté el flap. pero eso no es problema ya que de forma manual se puede recolocar en su posición... me miraré lo de los estados para ver si me encaja... yo hasta dónde sé, he llegado hacerlo funcionar en vaivén y que se quede fijo en su posición, lo que pasa que al intercanviar opciones se vuelve inestable y pierde la posición 0....

Tienes que hacer lo mismo que hace la controladora del aire, ni bien enciende mueve la persiana buscando el fin de carrera, ya ubicado mueve tantos pasos como sean necesarios (y que son conocidos) para volver a la posición 0 (cerrada).

Saludos

no tiene final de carrera...

Me confundí con otro tema similar que si tiene finales de carrera. :man_facepalming:t2:

Igualmente agregar uno no es nada complicado.

Saludos

Por lo que entiendo, para «posicionar en cero» el mecanismo cuando el Arduino arranca, bastaría con mover el motor una cantidad «grande» de pasos en un sentido. Ya que al llegar el flap al límite, algún tipo de «embrague» hará que el motor siga girando pero no se verá bloqueado ni forzado porque el flag haya llegado al final de su recorrido. Si es así, entonces el primer estado al que ha de pasar la «máquina de estados» es el de «posicionamiento inicial» que bien pudiera ser «forzarlo» a ir al destino cero cuando numero_pasos se ha forzado a que sea 1000, por ejemplo. Eso haría que el motor girase en un sentido todo el rato hasta que de 1000 llegue a cero. (Lo de 1000 es un valor de ejemplo, lo ideal es calcular el número máximo de pasos que lleva recorrer todo el movimiento posible del flap de un extremo a otro y usar ese valor).

Una vez llegue a la posición de destino, ya podemos asumir que el motor está en una posición conocida, y que esa posición es el cero. Entonces es cuando pasamos al estado «a la espera a que le llegue una instrucción» que comenté anteriormente. Y de esta forma no hace falta ningún fin de carrera para ubicar el sistema en una posición conocida.

¿Me puedes confirmar que no hay problema si se «fuerza» el motor a poner el flap más allá del final de recorrido? Que es esa la forma normal de operar de ese aparato.

Yo estoy estimando que no tiene el embrague pero si la parte mecánica del flap está en buen estado, sí, es claro que no necesita el final de carrera.
Llevas el flap más allá de lo que puede y el embrague se encarga de dejarlo en el tope, luego lo regresas a "cero", tal como lo dice @IgnoranteAbsoluto.

Saludos

Esta es mi propuesta con una «máquina de estados». Para posicionar «en cero» se fuerza a que el motor se mueva hacia el cero, para asegurarnos que está en el cero. Para ello hacemos creer al sistema que está en la posición ANGULO_POSICIONAMIENTO_INCIAL (que inicialmente lo he configurado como 99º) y que ha de posicionarse en cero. Esto debería hacer que el motor se mueva más de lo necesario y asegurarse que llegue al tope del cero. Todo esto asumiendo de que no se rompe nada por tratar de mover el flag más allá del tope.

Además de la instrucción 1 y 2, he añadido soporte para si se recibe un 0 (cero) el motor vuelva al ángulo cero, como si se hubiera apagado.

He definido la macro PASAR_GRADOS_A_PASOS() para hacer más legible y fácil la conversión de grados a pasos del motor.

#define PASAR_GRADOS_A_PASOS(grados) ((((long)grados) * 512) / 360) // Ajuste de 512 vueltas a los 360 grados (1.4222222222)

const int ANGULO_MAXIMO_VAIVEN          = PASAR_GRADOS_A_PASOS(90); // Ajuste de 512 vueltas a los 360 grados
const int ANGULO_MINIMO_VAIVEN          = PASAR_GRADOS_A_PASOS( 0); // Ajuste de 512 vueltas a los 360 grados
const int ANGULO_FIJO                   = PASAR_GRADOS_A_PASOS(45); // Ajuste de 512 vueltas a los 360 grados
const int ANGULO_POSICIONAMIENTO_INCIAL = PASAR_GRADOS_A_PASOS(99); // Ajuste de 512 vueltas a los 360 grados

const int INSTRUCCION_APAGADO = '0';
const int INSTRUCCION_ANGULO  = '1';
const int INSTRUCCION_VAIVEN  = '2';

enum estado_t { // Control de la máquina de estados
  ESTADO_INICIAL,
  ESTADO_POSICIONANDO_EN_CERO,
  ESTADO_ESPERANDO_INSTRUCCION,
  ESTADO_POSICIONANDO_MAXIMO_VAIVEN,
  ESTADO_POSICIONANDO_MINIMO_VAIVEN
} estado = ESTADO_INICIAL;

int retardo = 5;        // Tiempo de retardo en milisegundos (Velocidad del Motor)
int dato_rx;            // valor recibido en grados
int numero_pasos = 0;   // Valor en pasos donde se encuentra el motor
int destino = 0;        // Valon en pasos en que se ha de posicionar el motor
String leeCadena;       // Almacena la cadena de datos recibida
int input;

void setup() {                
  Serial.begin(9600);     // inicializamos el puerto serie a 9600 baudios
  pinMode(11, OUTPUT);    // Pin 11 conectar a IN4
  pinMode(10, OUTPUT);    // Pin 10 conectar a IN3
  pinMode(9, OUTPUT);     // Pin 9 conectar a IN2
  pinMode(8, OUTPUT);     // Pin 8 conectar a IN1
}

//***************************************************************************
void paso_der(){         // Pasos a la derecha
  digitalWrite(11, LOW); 
  digitalWrite(10, LOW);  
  digitalWrite(9, HIGH);  
  digitalWrite(8, HIGH);  
  delay(retardo); 
  digitalWrite(11, LOW); 
  digitalWrite(10, HIGH);  
  digitalWrite(9, HIGH);  
  digitalWrite(8, LOW);  
  delay(retardo); 
  digitalWrite(11, HIGH); 
  digitalWrite(10, HIGH);  
  digitalWrite(9, LOW);  
  digitalWrite(8, LOW);  
  delay(retardo); 
  digitalWrite(11, HIGH); 
  digitalWrite(10, LOW);  
  digitalWrite(9, LOW);  
  digitalWrite(8, HIGH);  
  delay(retardo);  
}

void paso_izq() {        // Pasos a la izquierda
  digitalWrite(11, HIGH); 
  digitalWrite(10, HIGH);  
  digitalWrite(9, LOW);  
  digitalWrite(8, LOW);  
  delay(retardo); 
  digitalWrite(11, LOW); 
  digitalWrite(10, HIGH);  
  digitalWrite(9, HIGH);  
  digitalWrite(8, LOW);  
  delay(retardo); 
  digitalWrite(11, LOW); 
  digitalWrite(10, LOW);  
  digitalWrite(9, HIGH);  
  digitalWrite(8, HIGH);  
  delay(retardo); 
  digitalWrite(11, HIGH); 
  digitalWrite(10, LOW);  
  digitalWrite(9, LOW);  
  digitalWrite(8, HIGH);  
  delay(retardo); 
}

void apagado() {         // Apagado del Motor
  digitalWrite(11, LOW); 
  digitalWrite(10, LOW);  
  digitalWrite(9, LOW);  
  digitalWrite(8, LOW);  
}

//**************************************************************************

void loop() {
  input = Serial.read();  // Si no se ha recibido nada, imput valdrá -1
  if ((estado != ESTADO_INICIAL) && (estado != ESTADO_POSICIONANDO_EN_CERO)) {
    // Procesamos la instrucción recibida sólo si no está inicializandose
    switch (input) {
      case INSTRUCCION_APAGADO :
        destino = 0;
        estado = ESTADO_ESPERANDO_INSTRUCCION; // Pasa al estado que espera instrucciones (si no lo estaba ya)
        break;
      case INSTRUCCION_ANGULO :
        destino = ANGULO_FIJO;
        estado = ESTADO_ESPERANDO_INSTRUCCION; // Pasa al estado que espera instrucciones (si no lo estaba ya)
        break;
      case INSTRUCCION_VAIVEN :
        if ((estado != ESTADO_POSICIONANDO_MAXIMO_VAIVEN) && (estado != ESTADO_POSICIONANDO_MINIMO_VAIVEN)) {
          // Procesamos la instruccion recibida sólo si no está realizando el vaivén
          destino = ANGULO_MAXIMO_VAIVEN; // Queremos que se mueva al ángulo máximo del vaivén
          estado = ESTADO_POSICIONANDO_MAXIMO_VAIVEN; // Pasa al estado que controla cuando el vaivén llega al máximo
        }
        break;
    }
  }

  // Control de la máquina de estado
  switch (estado) {
    case ESTADO_INICIAL :
      // Para mover el motor, forzamos un movimiento para que se posicione en el cero
      numero_pasos = ANGULO_POSICIONAMIENTO_INCIAL; // Asumimos que está en el máximo ángulo posible
      destino = 0;                                  // Lo hacemos ir al cero
      // Esperamos a que se posicione en el cero
      estado = ESTADO_POSICIONANDO_EN_CERO;
      break;
    case ESTADO_POSICIONANDO_EN_CERO :
      // Mientras se está posicionando no hace caso a ninguna instrucción recibida sólo se espera a que se situe
      if (numero_pasos == destino) {
        // Una vez situado en el punto inicial, pasa al modo de espera de instrucciones
        estado = ESTADO_ESPERANDO_INSTRUCCION;
      }
      break;
    case ESTADO_ESPERANDO_INSTRUCCION :
      // Mientras espera una nueva instrucción no se hace nada
      break;
    case ESTADO_POSICIONANDO_MAXIMO_VAIVEN :
      if (numero_pasos == destino) {
        // Ya ha llegado a la posición deseada
        destino = ANGULO_MINIMO_VAIVEN; // Ahora queremos que se mueva al ángulo mínimo del vaivén
        estado = ESTADO_POSICIONANDO_MINIMO_VAIVEN; // Pasa al estado que controla cuando el vaivén llega al mínimo
      }
      break;
    case ESTADO_POSICIONANDO_MINIMO_VAIVEN :
      if (numero_pasos == destino) {
        // Ya ha llegado a la posición deseada
        destino = ANGULO_MAXIMO_VAIVEN; // Ahora queremos que se mueva al ángulo máximo del vaivén
        estado = ESTADO_POSICIONANDO_MAXIMO_VAIVEN; // Pasa al estado que controla cuando el vaivén llega al máximo
      }
      break;
  }

  // Control del movimiento del motor
  // Si numero_pasos es distinto de destino, se moverá hacia el destino
  if (numero_pasos < destino) {
    paso_izq();
    numero_pasos = numero_pasos + 1;
  }
  else if (numero_pasos > destino) {
    paso_der();
    numero_pasos = numero_pasos -1;
  }
  else {
    apagado(); // Si no se ha de mover, podemos "apagar" el motor para que no comsuma
  }
}

Aquí otros enlaces que pueden resultar de interés: