jueves, 6 de junio de 2013

Controlar un servomotor con Arduino: magia


Y ahora que ya nos hemos hecho mayores, vamos a empezar a ver cosas más divertidas. La primera de ellas, controlar un servomotor HS-311 con Arduino.

Este servo, muy conocido y usado, suele venir al comprar el kit de iniciación básico de Arduino con sus accesorios.

Antes de empezar, comentar que he tomado prestada la información básica de esta entrada desde aquí (NOOBotics), y también de la página de Arduino UNO, y que las dos me han sido muy útiles.

Para empezar, lo básico es conectar el servo al Arduino. Es sencillito, podéis conectarlo directamente (como en esta imagen de ejemplo), o utilizar la protoboard (como he hecho yo, ver ejemplo abajo), pero lo que hay que hacer es lo mismo:

  • Cable rojo del servo al positivo (pin marcado como 5V de Arduino)
  • Cable negro del servo al negativo (uno de los marcados como GND de Arduino)
  • Cable amarillo del servo al PIN 9 de Arduino (o a cualquiera de los PINs marcados como PWM: Pulse Width Modulation, o modulación por ancho de pulsos), por donde se enviará la señal de control al servo.

Pero..., ¿Cómo funciona el servomotor?. Me gusta que te hagas esta pregunta. :-D  Solo con preguntas como esta conseguirás hacer frente a los robots cuando lleguen..., esto... Trataré de explicarlo con lo que he ido leyendo y aprendiendo por ahí.

De entrada, para que funcione hace falta cargar un programa al Arduino, cosa que más abajo veremos. Pero para entender lo que hará el programa es necesario antes entender como funciona un servo de estos. Un poco de teoría, vamos.

Los que venimos de la nada, o en el mejor de los casos del mundo Lego, un servomotor es un motor en el que le programas la potencia, la dirección del movimiento, y le dices cuanto tiempo ha de estar girando en esa situación. Esa base, aun no siendo mala, no sirve para enfrentarse a un servomotor de modelismo típico como puede ser el HS-311.

Este tipo de servos (como el HS-311) ni siquiera están diseñados para girar continuamente en una misma dirección, de hecho en muchos modelos no son capaces ni siquiera de dar una vuelta completa en una misma dirección. Por el contrario el diseño de los motores ofrece un muy buen control del numero de grados entre 0 y 360 (o el limite menor a 360 que cada fabricante fija) en que puede moverse el eje del motor.
Para hacer una analogía gráfica, podríamos decir que el servo que utilizábamos en Lego WeDo nos permitía directamente mover continuamente las ruedas de un coche, pero no nos permitía moverlas 15 grados. Por el contrario los servos como el HS-311 no nos permiten (directamente) mover las ruedas de un coche, pero si nos permiten decirle a nuestro robot exterminador que levante su brazo ejecutor unos 45º antes de volarnos la cabeza... Para un robot de verdad, al final necesitaremos saber controlar tanto un tipo de motores como otros.

Hasta aquí todo fantástico, Los mundos de Yupi!. Le dices al servo los grados en los que ha de situarse y el va y se sitúa. Pero no. No es tan fácil. Y no es tan fácil porque ¿como le dices al motor la posición en grados en la que ha de situarse?. Pues de entrada hay que saber que todo servo tiene una posición de ángulo mínimo (0 grados) y una posición de ángulo máximo (180 grados). Así que de entrada olvídate de momento de los 360º.
Bueno, pues de lo primero que habrá que hacer por código es establecer los anchos de pulso en microsegundos que se corresponderán con la posición mínima y con la máxima del servo.

¿Y que es el ancho de pulso o PWM?. Pues una buena explicación la he encontrado aquí. Pero yo trataré de explicarlo de nuevo a mi manera para cuando se me haya olvidado (pasado mañana) y tenga que volverlo a leer..., a ver si soy capaz de entenderme... :-).

Pues como dice en esa página la modulación por ancho de pulsos es una técnica para transferir energía mediante una señal cuadrada. En esta imagen podéis ver un buen detalle. La tensión máxima (el valor alto de la señal) que aplicaremos serán unos 5V (volts) puesto que Arduino utiliza ese voltaje con el USB que lo alimenta, y el valor bajo pues serán 0V.

Estos servos, y generalmente por especificaciones del fabricante (o eso creo, y si no pues búscalo por un servicio que han abierto ahora nuevo que se llama internet...) definen según cada modelo cual es el ancho de pulso mínimo que hay que enviar para que se sitúe en el ángulo mínimo (0º) y cuál es el máximo (180º). En nuestro caso (servo HS-311) esos valores de ancho de pulso son 600 microsegundos y 2400 microsegundos respectivamente para min y max (más o menos, vamos, que total esto de la electrónica no es una ciencia exacta... ¿¿¿???).

 Afortunadamente no estamos solos para mover el servomotor. Tenemos un aliado importante, que se llama Arduino. Y arduino tiene un conjunto de PINs (entre ellos el PIN 9) llamados PWM que están justamente diseñados para cosas como esta de mover un servo. Y además de tener Arduino tenemos unas herramientas más, como es un entorno y lenguaje de programación y además una API o librería de servos!!!. Esto nos va a ayudar muchísimo, ya que solo queda realizar un programa como el que se ve más abajo y cargarlo al Arduino.

#include <Servo.h> Servo myservo;  //create servo object int pos = 0;    //servo position int positions[] = {0, 45, 90, 135, 180};  //positions (in degrees) to send to the servo int numPositions = 5; void setup() {   //control servo via pin 9   myservo.attach(9, 650, 2350);   //start serial comm. for debugging   Serial.begin(9600); } void loop() {   int i = 0;   //iterate over positions   for(i = 0; i < numPositions; i++)   {             pos = positions[i];     //print debug output     Serial.println("SETTING:");     Serial.println(pos);     //tell servo to set the new position     myservo.write(pos);     //wait for two seconds     delay(2000);   } }
Básicamente lo que hace el programa es:
  • Incluye la librería "Servo.h"
  • Inicia unas variables, entre ellas un objeto "myservo"
  • Asocia (con attach) el control del servo al PIN 9, y establece los anchos de pulso mínimo y máximo para los grados mínimo (0 grado) y máximo (180 grados) que admite el motor.
  • Establece (con Serial.begin) la velocidad en baudios a 9600 por segundo. Esto ya lo explicare otro día..., si me entero de para que vale aquí... :-( 
  • Y luego entra en un bucle donde (con write) le indica directamente al servo a qué posición en grados a de situarse. En el ejemplo itera continuamente en el mismo bucle pasando el motor continuamente a los grados 0, 45, 90, 135 y 180 de forma indefinida, y esperando un par de segundos en cada posición.
A parte de lo que veis (el programa) esta lo que no veis: la librería "Servo.h" y lo que hay detrás "Servo.cpp" (que si podéis verlo si lo buscáis dentro de la instalación del software de Arduino) y el propio Arduino (que vale!, de verlo lo ves, pero como no te metas en los chips cuesta de pillar que hace y como exactamente... ;-)

Esta librería es la que se encarga de comunicar y transformar a bajo nivel los grados que le indicas a los que quieres que se ponga el servo, a señales específicas (un porron de señales cuadradas tipo PWM) a los PINs de Arduino, y que este hará llegar al servo a través del PIN 9 indicado. Es decir, la magia es lo que no ves. Y lo que solo los magos pueden ver.

Ala!. Y ponlo ya en marcha que por hoy ya esta!.
;-)