Controlar velocidad Servo 360º

Buenas, tengo un servo de 360º al que quiero controlar la velocidad en el momento del inicio del giro para que sea lo mas lenta posible y a continuacion pasa a velocidad maxima.

El codigo es el siguiente:

#include <Servo.h>

Servo myservo1;  // Creea el objeto myservo1 que es de 360º
Servo myservo2;  // Creea el objeto myservo2 que es de 360º

//Define las conexiones de los pines

int subir_brazo = 42;
int bajar_brazo = 43;
int subir_cabre = 40;
int bajar_cabre = 41;

void setup() {
  Serial.begin(9600);           // Configura el puerto serie a 9600 bps
  Serial.println("Servo_360");
  myservo1.attach(9);  // Conecta el servo del pin 9 al objeto myservo1
  myservo2.attach(8);  // Conecta el servo del pin 8 al objeto myservo2

  pinMode(subir_brazo, INPUT);
  pinMode(bajar_brazo, INPUT);
  pinMode(subir_cabre, INPUT);
  pinMode(bajar_cabre, INPUT);
  digitalWrite(subir_brazo, HIGH);
  digitalWrite(bajar_brazo, HIGH);
  digitalWrite(subir_cabre, HIGH);
  digitalWrite(bajar_cabre, HIGH);

}

void loop() {

  //  Desde aqui se controla Brazo el de la Grua
  int up_brazo = digitalRead(subir_brazo);
  int down_brazo = digitalRead(bajar_brazo);
  if (up_brazo == LOW)
  {
    Serial.println("Sube Brazo: ");
    myservo1.write(80);              // Entre 0 y 89 gira en sentido horario, la velocidad se reduce conforme nos acercamos a 89
    delay(100);
    myservo1.write(10);              // Entre 0 y 89 gira en sentido horario, la velocidad se reduce conforme nos acercamos a 89
    delay(30);
    myservo1.write(90);              // Para el servo de 360º
  }

  if (down_brazo == LOW)
  {
    Serial.println("Baja Brazo: ");
    myservo1.write(91);              // Entre 91 y 180 gira en sentido horario, la velocidad se reduce conforme nos acercamos a 91
    delay(2000);
    myservo1.write(180);              // Entre 91 y 180 gira en sentido horario, la velocidad se reduce conforme nos acercamos a 91
    delay(2000);
    myservo1.write(90);              // Para el servo de 360º
  }
  //  Hasta aqui se controla el Brazo de la Grua


  //  Desde aqui se controla el Cabrestante de la Grua
  int up_cabre = digitalRead(subir_cabre);
  int down_cabre = digitalRead(bajar_cabre);
  if (up_cabre == LOW)
  {
    Serial.println("Sube Cabrestante: ");
    myservo2.write(85);              // Entre 0 y 89 gira en sentido horario, la velocidad se reduce conforme nos acercamos a 89
    delay(2000);
    myservo2.write(0);              // Entre 0 y 89 gira en sentido horario, la velocidad se reduce conforme nos acercamos a 89
    delay(2000);
    myservo2.write(90);              // Para el servo de 360º
  }

  if (down_cabre == LOW)
  {
    Serial.println("Baja Cabrestante: ");
    myservo2.write(100);              // Entre 91 y 180 gira en sentido horario, la velocidad se reduce conforme nos acercamos a 91
    delay(2000);
    myservo2.write(170);              // Entre 91 y 180 gira en sentido horario, la velocidad se reduce conforme nos acercamos a 91
    delay(2000);
    myservo2.write(90);              // Para el servo de 360º
  }
  //  Hasta aqui se controla el Cabrestante de la Grua
}

Los delay son para que se vea el efecto mejor, el caso es que si pulso el boton de bajada o de subida solo una vez arranca lento y luego va a tope y despues se detiene, hasta aqui bien, pero si mantengo el boton pulsado empieza lento, pasa a rapido, pasa a lento, pasa a rapido y asi sucesivamente.
Y yo lo que quiero es que manteniendo el boton pulsado empieze lento vaya a rapido y se mantenga asi hasta que suelte el boton.
Y no veo como hacerlo.

PD: ¿Se puede subir un video en el que se vea el efecto?

Sube el video a Youtube y comparte el link. No hagas otra cosa porque el repositorio no lo tolera.
Tampoco uses google drive porque se tiende a pensar que se trata de un spam.

Respondo:
Con delays es imposible que las cosas se comporten como esperas.
Hablas de que si mantienes presionado debe hacer algo, que puede hacer si tu presionas y el código le dice haz esto, no hace nada, haz lo otro, no hace nada...
Debes cambiar todo por millis() o mas simple usa Bounce2.h que tiene soporte para estados cortos o largos. Es decir ya tienes resuelto el problema, pero sin usar delay.

Aca va el video:

Video Velocidad Servo

Mirare lo de millis() y la libreria que me recomiendas.

Lo de los delays es para que se pueda ver el efecto como si fuera a camara lenta, lo que quiero es cuando pulso el boton o lo mantengo pulsado el servo arranque al minimo de velocidad y pasado 1 segundo (mas o menos ya vere una vez montado con sus correspondientes engranajes y/o correa de transmision) pase a velocidad maxima hasta que suelte el boton.

Pero como se ve en el video arranca lento (osea correcto) y a continuacion pasa a velocidad maxima (tambien correcto) pero como lo matengo pulsado repite el ciclo y vuelve a modo lento (mal) y yo quiero que siga a velocidad maxima mientras no suelte el boton.

#define subir 180
#define bajar 0
#define parar 90
#define presionado LOW
#define suelto HIGH

double pausalineal=0.9;
double pausamillsratio=100;
double pausaminima=10;
...

int down_brazo = digitalRead(bajar_brazo);
pausamillsratio=100;
while  (up_brazo == presionado)
{
   myservo1.write(subir);
    delay(pausaminima+(pausamillsratio*pausalineal)); //ToDo: cambiar por mills
    pausamillsratio=pausamillsratio*pausalineal;
  
}
myservo1.write(parar);



No tengo motores para probar pero la idea supongo que pasa en hacer un sistema lineal/logarítmico de movimiento según tú necesites.
Lineal es que la velocidad va incrementando siempre la misma tasa, (1,2,3,4,5...) logarítmico que va acelerando cada vez el doble (1,2,4,8,16...)
Mientras esté pulsado el botón, que la pausa vaya siendo más corta cada vez...
Si quieres aceleración lineal podría hacer un int pausa=200; y en el while decir delay(pausa) y pausa--;
No sé si entiendes la idea.
Saludos.

1 Like

Hay una librería que hace esto con mucha facilidad, me refiero a controlar el boton sea por un cambio, un flanco, una presion larga, etc.
Se llama Button.h y te la dejo para que la examines.
Defines de este modo varios comportamientos con el boton, aunque la otra variante es la expuesta por @DanX3

1 Like

Gracias a ambos, necesitare unos dias para asimilar esa informacion y hacer pruebas

De momento he probado con los while de @DanX3 y he simplificado al maximo el codigo con un solo servo, pero en cuanto pulso uno de los botones no sale del while y el servo se queda girando a velocidad constante y no sale del while pulse lo que pulse.

#include <Servo.h>

Servo myservo1;  // Creea el objeto myservo1 que es de 360º

//Define las conexiones de los pines

int subir_brazo = 42;
int bajar_brazo = 43;

#define subir 180
#define bajar 0
#define parar 90
#define presionado LOW
#define suelto HIGH

double pausalineal = 0.9;
double pausamillsratio = 100;
double pausaminima = 10;


void setup() {
  Serial.begin(9600);           // Configura el puerto serie a 9600 bps
  Serial.println("Servo_360 con while");
  myservo1.attach(9);  // Conecta el servo del pin 9 al objeto myservo1

  pinMode(subir_brazo, INPUT_PULLUP);
  pinMode(bajar_brazo, INPUT_PULLUP);
}

void loop() {

  //  Desde aqui se controla Brazo el de la Grua
  int up_brazo = digitalRead(subir_brazo);
  int down_brazo = digitalRead(bajar_brazo);

  pausamillsratio = 100;

  while  (up_brazo == presionado)
  {
    Serial.println("Sube brazo: ");
    myservo1.write(subir);
    delay(pausaminima + (pausamillsratio * pausalineal)); //ToDo: cambiar por mills
    pausamillsratio = pausamillsratio * pausalineal;
  }

  while  (down_brazo == presionado)
  {
    Serial.println("Baja brazo: ");
    myservo1.write(bajar);
    delay(pausaminima + (pausamillsratio * pausalineal)); //ToDo: cambiar por mills
  }
  myservo1.write(parar);

  
  //  Hasta aqui se controla el Brazo de la Grua


  //  Desde aqui se controla el Cabrestante de la Grua
  //  Hasta aqui se controla el Cabrestante de la Grua
}

Mete

up_brazo = digitalRead(subir_brazo);

antes de cerrarla llave del while

Bueno con la idea de @DanX3 y algunas modificaciones he conseguido lo que queria, ya veremos luego cuando lo aplique al mundo real :slight_smile:

#include <Servo.h>

Servo myservo1;  // Creea el objeto myservo1 que es de 360º

//Define las conexiones de los pines

int subir_brazo = 42;
int bajar_brazo = 43;

int subir = 85;
int bajar = 96;
#define parar 90
#define presionado LOW
#define suelto HIGH

double pausalineal = 0.9;
double pausamillsratio = 100;
double pausaminima = 10;


void setup() {
  Serial.begin(9600);           // Configura el puerto serie a 9600 bps
  Serial.println("Servo_360 con while");
  myservo1.attach(9);  // Conecta el servo del pin 9 al objeto myservo1

  pinMode(subir_brazo, INPUT_PULLUP);
  pinMode(bajar_brazo, INPUT_PULLUP);
}

void loop() {

  //  Desde aqui se controla Brazo el de la Grua
  int up_brazo = digitalRead(subir_brazo);
  int down_brazo = digitalRead(bajar_brazo);

  pausamillsratio = 100;

  while  (up_brazo == presionado)
  {
    Serial.print("Sube brazo: ");
    Serial.println(subir);
    myservo1.write(subir);
    delay(pausaminima + (pausamillsratio * pausalineal)); //ToDo: cambiar por mills
    pausamillsratio = pausamillsratio * pausalineal;
    up_brazo = digitalRead(subir_brazo);
    subir = subir - 1;
}

  while  (down_brazo == presionado)
  {
    Serial.print("Baja brazo: ");
    Serial.println(bajar);
    myservo1.write(bajar);
    delay(pausaminima + (pausamillsratio * pausalineal)); //ToDo: cambiar por mills
    pausamillsratio = pausamillsratio * pausalineal;
    down_brazo = digitalRead(bajar_brazo);
    bajar = bajar + 1;
  }
  myservo1.write(parar);
  subir = 85;
  bajar = 96;
  
  //  Hasta aqui se controla el Brazo de la Grua


  //  Desde aqui se controla el Cabrestante de la Grua
  //  Hasta aqui se controla el Cabrestante de la Grua
}

Lo de millis() no lo veo, entiendo se puede medir intervalos en milisegundos pero no veo como aplicarlos para producir algo parecido al delay()

Gracias @Surbyte por las librerias Bounce2.h y Button.h pero voy a necesitar bastantes dias para deglutirlas y hacer bastantes practicas para entenderlas, si hago algo con ellas en este proyecto lo posteare.

Ve a documentación y lee Entender millis y no morir en el intento - #5 by victorjam

Cambio mi recomendación de Button.h por este EasyButton.h

1 Like

Gracias nuevamente @Surbyte ahora si veo el uso de Millis(), es a base de comparaciones con if.

Ahora me toca empaparme del funcionamiento de la libreria EasyButton.h, se me amontona la faena :smile: :smile: