Servo

Hola a todos!

Tengo una pregunta con la que podeis ayudarme.
Me gustaría programar un servo para que, a partir de la lectura de un potenciómetro, gire más rápido o más lento y en una dirección o en otra.

Este es el código:

#include <Servo.h>

Servo servo;
int posicion; //variable que define la posición del servo
int velocidad; //variable que define la velocidad de giro del servo
int pot = 0; //variable que tomará el valor del potenciómetro

void setup() {
  servo.attach(3);
  servo.write(90);
  posicion = 90;
  delay(1500);
  pinMode(A0, INPUT);
  
}

void loop() {
  int pot0 = pot; //definimos una variable que tenga el mismo valor que pot y que empiece valiendo 0 para detectar cualquier cambio en la variable pot
  pot = analogRead(A0); //la variable pot toma el valor leído en A0
  velocidad = map(pot, 0, 1023, -90, 90); //se asigna un rango de valores que correspoderán a los valores de velocidad de giro del servo
  int vel0 = velocidad;//definimos una variable que tenga el mismo valor que velocidad para detectar cualquier cambio en dicha variable

  if (pot > pot0){     //si se gira el potenciómetro hacia la derecha
    
    if (velocidad > 0){      //si el valor de la velocidad es positivo
      while (posicion < 180){  //hasta que el servo llegue a la posición máxima (180º)
        posicion++;     //aumentamos en 1 el valor de posicion
        servo.write(posicion); //el servo gira una unidad
        delay(500/velocidad); //cuanto mayor sea el valor de velocidad el bucle se repetirá más rápido
        velocidad = map(pot, 0, 1023, -90, 90); //leer el valor de la velocidad
        if(velocidad != vel0){  //si el valor de la velocidad ha cambiado
          break;  //salir del bucle
        }
      }
    }

    if (velocidad < 0){      //si el valor de la velocidad es negativo
      while (posicion > 0){  //hasta que el servo llegue a la posición mínima (0º)
        int vel0 = velocidad;//definimos una variable que tenga el mismo valor que velocidad para detectar cualquier cambio en dicha variable
        posicion--;     //disminuímos en 1 el valor de posicion
        servo.write(posicion); //el servo gira una unidad
        delay(-500/velocidad); //cuanto mayor sea el valor de velocidad el bucle se repetirá más rápido
        velocidad = map(pot, 0, 1023, -90, 90); //leer el valor de la velocidad
        if(velocidad != vel0){  //si el valor de la velocidad ha cambiado
          break;  //salir del bucle
        }
      }
    }
  }
  if (pot < pot0){     //si se gira el potenciómetro hacia la izquierda
    
    if (velocidad > 0){      //si el valor de la velocidad es positivo
      while (posicion < 180){  //hasta que el servo llegue a la posición máxima (180º)
        int vel0 = velocidad;//definimos una variable que tenga el mismo valor que velocidad para detectar cualquier cambio en dicha variable
        posicion++;     //aumentamos en 1 el valor de posicion
        servo.write(posicion); //el servo gira una unidad
        delay(500/velocidad); //cuanto mayor sea el valor de velocidad el bucle se repetirá más rápido
        velocidad = map(pot, 0, 1023, -90, 90); //leer el valor de la velocidad
        if(velocidad != vel0){  //si el valor de la velocidad ha cambiado
          break;  //salir del bucle
        }
      }
    }

    if (velocidad < 0){      //si el valor de la velocidad es negativo
      while (posicion > 0){  //hasta que el servo llegue a la posición mínima (0º)
        int vel0 = velocidad;//definimos una variable que tenga el mismo valor que velocidad para detectar cualquier cambio en dicha variable
        posicion--;     //disminuímos en 1 el valor de posicion
        servo.write(posicion); //el servo gira una unidad
        delay(-500/velocidad); //cuanto mayor sea el valor de velocidad el bucle se repetirá más rápido
        velocidad = map(pot, 0, 1023, -90, 90); //leer el valor de la velocidad
        if(velocidad != vel0){  //si el valor de la velocidad ha cambiado
          break;  //salir del bucle
        }
      }
    }
  }
}

No se por qué no funciona. Puede que sea por los “break” (no los había usado aun).

Gracias por la ayuda!!

probaste con un ejemplo simple de la librería servo? Funciona?

Sí, hice un programa que según se movía el potenciómetro, el servo se movía igual, y me funcionaba bien.

  • La velocidad del servo no la puedes cambiar salvo que cambies el voltaje o hagas un timer ya sea con millis o microdelay que haga pequeñas paradas.
  • ¿Tu servo es de rotación contínua sí o no?
  • Si tu potenciómetro controla el "ángulo" cómo pretendes que también ajuste ¿la velocidad? Tú servo irá la posisción designada en función de cómo de rápido gires el potenciómetro (y tus delays)
  • Tras lo dicho en el punto anterior ¿No necesitarías un componente para el ángulo y otro para la velocidad? Y digo componente porque lo mismo te sirve un [u]encoder rotativo[/u]. Al menos yo usaría eso. Uno para la velocidad otro para el ángulo. Y lo que te comenta surbyte es porque es u ejemplo tan básico que basta "googlear" para encontrar ejemplos hasta la saciedad. Máxime si los has probado y te funcionan.

Saludos.

Edito: por aquí un enlace sobre el encoder que comento: https://www.luisllamas.es/arduino-encoder-rotativo/

Primero, la variable velocidad del servo equivale a las veces que avanza por cada medio segundo, es decir, velocidad 90 sería 90/0,5 º/s, o sea 180º/s. De modo que sí que puedo variar la velocidad del servo.

Segundo, el potenciómetro solo controla la velocidad. El ángulo lo controla el propio programa al definir la posición inicial en 90º:

servo.write(90)
int posicion = 90

Y tercero, hay creada una variable que controla la posición (int posicion) y otra que controla la velocidad y que viene dada por el potenciómetro (int velocidad).

Aun así, gracias por tus sugerencias.

¿Porque no comienzas explicando detalladamente el objetivo que quieres conseguir o que quieres que haga tu sketch? Asi podran darte respuestas mas concretas...

El objetivo es hacer que un Servo gire más rápido o más lento en una dirección o en otra según la posición de un potenciómetro:

  • Si está en el centro, velocidad = 0 y se mantiene la posición

  • Si está hacia la derecha, velocidad > 0 y el servo gira hacia la derecha (sea cual sea la posición en la que esté el Servo); cuanto más girado esté el potenciómetro, más rápido girará el Servo.

  • Si está hacia la izquierda, velocidad < 0 y pasa al contrario que arriba.

Tienes un problema porque la velocidad de giro en el servo es constante. No puedes modificarla hasta donde yo se.

Eso la había intentado aclarar en una respuesta anterior:

(...) La variable velocidad del servo equivale a las veces que avanza por cada medio segundo, es decir, velocidad 90 sería 90/0,5 º/s, o sea 180º/s (...)

A lo que me refiero con eso es lo siguiente:

Si la variable velocidad vale 4, por ejemplo, el servo se mueve 1 paso y espera 500/4 (que es 500 entre la variable velocidad) antes de dar el siguiente. Entonces, realmente no cambia la velocidad pero lo parece.

¿Alguien podría revisar el código, por favor? Soy relativamente nuevo y aun no había usado el comando break. ¿Podríais decirme si el fallo está ahí o si está en otro sitio? Os lo agradecería mucho.

mirando un poco por encima,cuando la velocidad es negativa usas un delay(-500/velocidad) y eso no te va a funcionar porque delay solo acepta unsined long como parametro,osea una variable tipo long sin signo,no se si lo has puesto por error.. .Luego esta el tema de la lectura del potenciometro ,si haces un simple sketch que lea el potenciometro y lo muestre por el serial monitor,veras que la lectura a veces varia aun cuando no toques el potenciometro,en ese caso tu sketch saldria por el break.Tambien dices que si el valor es 0 deberia quedarse en la posicion ,pero no veo como vas a saber si el potenciometro esta en el centro o el servo se mueve muy lento y crees que esta en el centro...

Bueno había escrito todo un código pero me doy cuenta que no servirá tal como lo has planteado.
solo te sugiero esto

#include <Servo.h>

Servo servo;
int posicion;        //variable que define la posición del servo
int velocidad = 1;   //variable que define la velocidad de giro del servo
int pot = 0;         //variable que tomará el valor del potenciómetro
int potAnt;          // definimos una variable que tenga el mismo valor que pot y que empiece valiendo 0 para detectar cualquier cambio en la variable pot
int vel0;

void setup() {
  servo.attach(3);
  servo.write(90);
  posicion = 90;
  delay(1500);
  pinMode(A0, INPUT);
  
}

void loop() {
  
  if (velocidad > 0) {
      while (posicion < 180){  //hasta que el servo llegue a la posición máxima (180º)
        posicion++;     //aumentamos en 1 el valor de posicion
        servo.write(posicion); //el servo gira una unidad
        delay(vel0); //cuanto mayor sea el valor de velocidad el bucle se repetirá más rápido
        leoVelocidad();
        if (pot != potAnt)
            break;
      }
   }
   else {      //si el valor de la velocidad es negativo
      while (posicion > 0) {  //hasta que el servo llegue a la posición mínima (0º)
        posicion--;     //disminuímos en 1 el valor de posicion
        servo.write(posicion); //el servo gira una unidad
        delay(vel0); //cuanto mayor sea el valor de velocidad el bucle se repetirá más rápido
        leoVelocidad();
        if (pot != potAnt)
            break;
      }
   }
}

void leoVelocidad() {
  
   potAnt = pot;
   pot = analogRead(A0); //la variable pot toma el valor leído en A0
  
   velocidad = map(pot, 0, 1023, -90, 90); //se asigna un rango de valores que correspoderán a los valores de velocidad de giro del servo
  
   if (velocidad > 0)
      vel0 = 500/velocidad;//definimos una variable que tenga el mismo valor que velocidad para detectar cualquier cambio en dicha variable
   else 
      vel0 = -500/velocidad;
}

veras que aunque te resuelvo varias cosas, no consideré que tu miras el movimiento del potenciometro respecto de la posicion relativa, algo que no expresaste en tus comentarios y que luego me di cuenta.
Asi que mi código funciona como del 2.5V en adelante y de 2.5 hacia 0. eso es Derecha e izquierda, que salvo constantes es lo mismo que velocidad.

a ver si algo de lo hecho te sirve