Arduino: Control de servo motores

  1. Servomotores
    1. Servomotor 9g SG 90 de Tower Pro
    2. Control con Arduino IDE
    3. Control con ArduinoBlocks
  2. Práctica 1: Movimiento con monitor serie
    1. Comunicación de Arduino con Puerto serie
    2. Movimiento de un servo con monitor serie (IDE)
  3. Práctica 2: Movimiento secuencial directo (1 servo)
  4. Práctica 3: Movimiento secuencial «while» (1 servo)
  5. Práctica 4: Movimiento secuencial directo (4 servos)
  6. Práctica 5: Movimiento secuencial while (4 servos)
  7. Práctica 6: Control con pulsadores
  8. Práctica 7: Control con potenciómetros
  9. Práctica 8: Guardar posiciones
  10. Práctica 9: Movimiento por sensor de ultrasonido
  11. Práctica 10: Movimiento por joystick
    1. Mejoras al código
    2. Código completo

Servomotores

La mejor manera para implementar articulaciones de rotación en robótica educativa, es utilizar Servomotores de modelismo, conocidos coloquialmente como Servos.

Hay servos de todos los tamaños y gustos. Estos son algunos de los servos más utilizados: El Futaba 3003 o compatible, y los micro-servos Tower-Pro SG90 y Emax ES08A.

A diferencia de otros tipos de motores en los que controlamos la velocidad de giro, en un servo indicamos directamente el ángulo deseado y el servo se encarga de posicionares en este ángulo.

Típicamente los servos disponen de un rango de movimiento de entre 0º a 180º. Es decir, no son capaces de dar la vuelta por completo (de hecho disponen de topes internos que limitan el rango de movimiento).

Internamente un servo frecuentemente consta de un mecanismo reductor:


Por tanto proporcionan un alto par y un alto grado de precisión (incluso décimas de grado). Por contra, las velocidades de giro son pequeñas frente a los motores de corriente continua.

Los servos se admiten una tensión de alimentación entre 4,8V a 7,2V, siendo el valor más adecuado es 6V. Con tensiones inferiores el motor tiene menos fuerza y velocidad. Con tensiones superiores a 6,5V los servos empiezan a oscilar demasiado, lo cual los hace poco útiles.

Se usan para abrir y cerrar pinzasorientar sensores, o mover articulaciones. Están formados por tres partes: cuerpocabeza (o Corona) y cable de conexión.

Fuente

El cuerpo es la parte más grande, que alberga en su interior el motor, la electrónica y los engranajes. La cabeza es la pieza que va atornillada al eje de salida, y que es la que gira con respecto al cuerpo. En inglés se llama horn (cuerno). El cable está formado por tres hilos de colores que terminan en un conector hembra.

Frecuentemente simplemente se dispone de un potenciómetro unido al eje del servo, que permite al servo para conocer la posición del eje. Esta información es tratada por un controlador integrado que se encarga de ajustar actuar sobre el motor para alcanzar la posición deseada.

La comunicación de la posición deseada se realiza mediante la transmisión de un señal pulsada con periodo de 20ms. El ancho del pulso determina la posición del servo.

La relación entre el ancho del pulso y el ángulo depende del modelo del motor. Por ejemplo, algunos modelos responden con 0º a un pulso de 500 ms, y otros a un pulso de 1000 ms

En general, en todos los modelos:

  • Un pulso entre 500-1000 us corresponde con 0º
  • Un pulso de 1500 ms corresponde con 90º (punto neutro)
  • Un pulso entre 2000-2500us corresponde con 180º

Por tanto, variando la señal en microsegundos podemos disponer de una precisión teórica de 0.18-0.36º, siempre que la mecánica del servo acompañe.

Servomotor 9g SG 90 de Tower Pro

Esta es la hoja de características del fabricante:

Aunque el servo puede moverse con una resolución de más de 1 grado, este es el máximo de resolución que vamos a conseguir debido a la limitación de la señal PWM que es capaz de generar Arduino UNO.

Estos motores funcionan con una señal PWM, con un pulso de trabajo entre 1 ms y 2 ms y con un periodo de 20 ms (50 Hz). ¿Qué quiere decir todo esto? Este dato nos indica la velocidad máxima a la que podemos mover el servomotor con Arduino. Solo podremos cambiar de posición cada 20 ms. Esto dependerá del tipo y marca de nuestro servo.

El elegir una salida PWM u otra da lo mismo, todas las salidas de este tipo funcionan igual.

Para conectarlo a Arduino UNO:

También se puede usar un shield, como el proporcionado por Microlog. Observa que tenemos un aspa colocada, y que se tienen que realizar tres conexiones:

  • Marrón o negro: Conectar a GND.
  • Rojo: Conectar a 5V.
  • Naranja o blanco: Conectar a un PIN digital, en este caso el 13.

Control con Arduino IDE

El control de servos en Arduino es muy sencillo, ya que el IDE Standard proporciona la librería “servo.h”, que permite controlar simultáneamente hasta 12 servos en Arduino Uno/Nano y hasta 48 servos en Arduino Mega.

Entre los ejemplos típicos para ilustrar el funcionamiento de servos tenemos el Sketch “Sweep”, que realiza un barrido continuo con el servo.

Para ello incrementa el ángulo de 0º a 180º a razón de 1º cada 15ms, posteriormente realiza la operación contraria de 180º a 0º, para finalmente reiniciar el bucle.

Dentro de la librería servo.h tienes Servo – attach () y Servo-Write ()

Control con ArduinoBlocks

Si no lo has hecho, regístrate en ArduinoBlocks y elige la placa ArduinoUNO. En el apartado Motor, encontramos los bloques para el control de servo:

Aquí tenemos la explicación de cada uno de los parámetros configurables:

Aquí tenemos un programa similar al realizado en el IDE, con el idioma del programa en Inglés:

Aquí está la «traducción» a código que realizar arduinoblocks. ¿Qué diferencias aprecias con el que has realizado en el IDE?

Añade los comentarios pertinentes al código para que aparezca de la siguiente manera:

También serviría así:

Práctica 1: Movimiento con monitor serie

El programa consiste en mover un sermotor a la posición deseada, introduciendo el valor a través del monitor serie.

Comunicación de Arduino con Puerto serie

Los puertos serie son la principal forma de comunicar una placa Arduino con un ordenador.

  • Un puerto es un interfaz (físico o virtual) que permite comunicación entre dos ordenadores o dispositivos.
  • Un puerto serie envía la información mediante una secuencia de bits. Necesita, al menos, un conector para recepción de datos (RX) y otro para la transmisión (TX). El más conocido es el Universal Serial Port (USB). Otros son el I2C, Serial ATA, Ethernet o FireWire.
  • Un puerto paralelo envía la información mediante múltiples canales de forma simultánea. Necesita muchos más conductores de comunicación.

Los puertos serie están físicamente unidos a distintos pines de la placa Arduino: 0 (RX) y 1 (TX). Mientras usamos estos puertos de serie no podemos usar como entradas o salidas digitales los pines asociados con el puerto serie en uso.

Nuestra placa de Arduino tiene un conector USB conectado a uno de los puertos serie, lo que simplifica el proceso de conexión con un ordenador.

Nota: No debemos acostumbrarnos a usar el puerto serie si realmente no necesitamos comunicar con el ordenador. Las librerías empleadas para el uso de puerto serie ocupan un tamaño considerable, y sólo debemos emplearlas si realmente las necesitamos. Además, supone inhabilitar de forma innecesaria los pines digitales asociados.

Una vez cargado el programa en el Arduino UNO, abrimos el monitor serie.

El monitor de puerto es una pequeña utilidad integrada dentro de IDE Standard que nos permite enviar y recibir información a través del puerto serie. Tiene dos zonas; una muestra los datos recibidos y otra para enviarlos:

Ejemplo: Empleo del puerto serie para encender o apagar el LED integrado de la placa de Arduino, enviando un carácter.

Movimiento de un servo con monitor serie (IDE)

y vamos introduciendo el ángulo donde deseamos posicionar el servo y pulsamos Intro.

Con este programa podemos colocar los servos en la posición que deseamos, para el correcto funcionamiento del brazo robótico.

Práctica 2: Movimiento secuencial directo (1 servo)

El programa consiste en una secuencia de movimientos que se realizan de forma directa.

Práctica 3: Movimiento secuencial «while» (1 servo)

El programa consiste en una secuencia de movimientos que se realizan poco a poco utilizando la instrucción while.

Práctica 4: Movimiento secuencial directo (4 servos)

El programa consiste en una secuencia de movimientos que se realizan de forma directa.

Práctica 5: Movimiento secuencial while (4 servos)

El programa consiste en una secuencia de movimientos que se realizan poco a poco utilizando la instrucción while.

Práctica 6: Control con pulsadores

El programa consiste en un control en tiempo real de cada servo mediante dos pulsadores por cada servo, uno para cada sentido de giro.

Práctica 7: Control con potenciómetros

El programa consiste en un control en tiempo real de cada servo mediante dos potenciómetros, una por cada servo, de manera que el eje del miniservo gire en relación al recorrido del potenciómetro.

Se puede usar GPTChat de OpenIA para preguntar acerca de este código:

Esta es la respuesta:

Práctica 8: Guardar posiciones

Práctica 9: Movimiento por sensor de ultrasonido

Práctica 10: Movimiento por joystick

Para esta práctica necesitaremos:

  • 4 miniservos
  • 2 joysticks

Este código de Arduino controla cuatro servomotores que están conectados a los pines 13, 11, 9 y 7 del Arduino. Los servomotores se utilizan para controlar la posición de la base, el hombro, el codo y la pinza de un brazo robótico, respectivamente. El control se realiza mediante dos joysticks, conectados a los pines analógicos A0, A1, A3 y A4 del Arduino.

La primera parte del código incluye la biblioteca Servo.h y declara cuatro objetos de la clase Servo para controlar los cuatro servomotores. También se definen cuatro variables enteras que se utilizan para almacenar los ángulos de cada servo.

La función setup() se utiliza para inicializar los objetos Servo y configurar los ángulos iniciales de los servomotores en 90 grados para la base, 170 grados para el hombro, 50 grados para el codo y 150 grados para la pinza. Además, la velocidad de la comunicación en serie se establece en 9600 baudios.

La función loop() es el bucle principal del programa, que se ejecuta continuamente mientras el Arduino está encendido. El primer comando en el bucle es delay(10), que introduce una pequeña pausa en la ejecución para evitar que el bucle se ejecute demasiado rápido.

Luego se leen los valores de los joysticks en los pines analógicos A0, A1, A3 y A4 mediante la función analogRead(). Estos valores se utilizan para controlar los ángulos de los servomotores.

El siguiente bloque de código utiliza las condiciones if() para comprobar si los joysticks se han movido hacia la derecha o hacia la izquierda. Si el joystick se mueve hacia la derecha y el ángulo del servo correspondiente es menor que 180º, se aumenta el ángulo del servo en una unidad. Si el joystick se mueve hacia la izquierda y el ángulo del servo correspondiente es mayor que 0, se disminuye el ángulo del servo en una unidad. Los cuatro servomotores se controlan de forma independiente utilizando las variables anguloB, anguloH, anguloC y anguloP.

Mejoras al código

Para mejorar este código, se podría añadir una función que limite los ángulos de los servomotores para evitar que se muevan más allá de los límites físicos del brazo robótico. Además, se podría incluir una función de calibración que permita ajustar los ángulos iniciales de los servomotores de forma precisa y fácil. También se podría añadir una interfaz gráfica de usuario para controlar el brazo robótico utilizando un ordenador o un dispositivo móvil.

  1. Función que limite los ángulos de los servomotores:

Actualmente, el código permite que los ángulos de los servomotores excedan los límites físicos del brazo robótico. Es decir, los ángulos pueden ser mayores que 180 grados o menores que 0 grados. Esto puede dañar los servomotores y reducir la vida útil del brazo robótico. Para solucionar esto, se puede implementar una función que limite los ángulos de los servomotores.

La función puede ser algo así:

int limitarAngulo(int angulo, int angulo_min, int angulo_max) {
  if (angulo > angulo_max) {
    return angulo_max;
  }
  else if (angulo < angulo_min) {
    return angulo_min;
  }
  else {
    return angulo;
  }
}

Esta función toma como entrada un ángulo, un ángulo mínimo y un ángulo máximo y devuelve el ángulo limitado dentro de los límites especificados. Se puede usar esta función en el código original para limitar los ángulos de los servomotores, de esta forma:

anguloB = limitarAngulo(anguloB, 0, 180);
anguloH = limitarAngulo(anguloH, 0, 180);
anguloC = limitarAngulo(anguloC, 80, 170);
anguloP = limitarAngulo(anguloP, 40, 120);
  1. Función de calibración:

Otra mejora útil sería agregar una función de calibración que permita establecer los ángulos mínimos y máximos para cada servomotor. Esto puede ser útil cuando se cambia el brazo robótico o se sustituye un servomotor. La función de calibración puede ser algo así:

void calibrarServomotores() {
  Serial.println("Calibrando servomotores...");
  Serial.println("Mueve cada servo a su posición mínima y presiona ENTER.");
  while (!Serial.available()) {
    // Espera a que se presione ENTER
  }
  anguloB = Base.read();
  anguloH = Hombro.read();
  anguloC = Codo.read();
  anguloP = Pinza.read();
  
  Serial.println("Mueve cada servo a su posición máxima y presiona ENTER.");
  while (!Serial.available()) {
    // Espera a que se presione ENTER
  }
  anguloB_max = Base.read();
  anguloH_max = Hombro.read();
  anguloC_max = Codo.read();
  anguloP_max = Pinza.read();
  
  Serial.println("Calibración finalizada.");
}

Esta función solicita al usuario que mueva cada servo a su posición mínima y máxima, y luego lee los ángulos actuales de cada servo. Luego, estos valores se pueden usar para limitar los ángulos de los servos en el código principal, usando la función limitarAngulo() propuesta anteriormente.

Para llamar a esta función desde el código principal, se puede agregar un condicional en la función setup() que verifique si hay datos disponibles en el puerto serie, como se muestra.

Código completo

#include <Servo.h>

Servo Base;
Servo Hombro;
Servo Codo;
Servo Pinza;

int anguloB = 90;
int anguloH = 170;
int anguloC = 50;
int anguloP = 150;
int minAnguloB = 0;
int maxAnguloB = 180;
int minAnguloH = 0;
int maxAnguloH = 180;
int minAnguloC = 80;
int maxAnguloC = 170;
int minAnguloP = 40;
int maxAnguloP = 120;

void setup() {
  Base.attach(13);
  Hombro.attach(11);
  Codo.attach(9);
  Pinza.attach(7);
  Serial.begin(9600);
  Base.write(anguloB);
  Hombro.write(anguloH);
  Codo.write(anguloC);
  Pinza.write(anguloP);
  
  // Calibración de los ángulos mínimos y máximos
  Serial.println("Calibrando el brazo robótico...");
  Serial.println("Mueva cada servo a su posición límite y manténgalo allí durante la calibración.");
  Serial.println("Presione cualquier tecla para comenzar...");
  while (!Serial.available());
  Serial.read();
  calibrarServo(Base, minAnguloB, maxAnguloB);
  calibrarServo(Hombro, minAnguloH, maxAnguloH);
  calibrarServo(Codo, minAnguloC, maxAnguloC);
  calibrarServo(Pinza, minAnguloP, maxAnguloP);
  Serial.println("Calibración finalizada.");
}

void loop() {
  delay(10);
  if (analogRead(A0) > 600 && anguloB < maxAnguloB) { // Derecha
    anguloB++;
    Base.write(anguloB);
  }
  if (analogRead(A0) < 400 && anguloB > minAnguloB) { // Izquierda
    anguloB--;
    Base.write(anguloB);
  }
  if (analogRead(A1) < 400 && anguloH < maxAnguloH) { // Derecha
    anguloH++;
    Hombro.write(anguloH);
  }
  if (analogRead(A1) > 600 && anguloH > minAnguloH) { // Izquierda
    anguloH--;
    Hombro.write(anguloH);
  }
  if (analogRead(A4) < 400 && anguloC < maxAnguloC) { // Derecha
    anguloC++;
    Codo.write(anguloC);
  }
  if (analogRead(A4) > 600 && anguloC > minAnguloC) { // Izquierda
    anguloC--;
    Codo.write(anguloC);
  }
  if (analogRead(A3) < 400 && anguloP < maxAnguloP) { // Derecha
    anguloP++;
    Pinza.write(anguloP);
  }
  if (analogRead(A3) > 600 && anguloP > minAnguloP) { // Izquierda
    anguloP--;
    Pinza.write(anguloP);
  }
}

void calibrarServo(Servo servo, int &minAngulo, int &maxAngulo) {
  int minValor = 1023

Deja un comentario

Comments (

0

)

Diseña un sitio como este con WordPress.com
Comenzar