Este proyecto combina las súper asombrosa Pixy CMUCam-5 que es un sistema de visión, con el Sumo Robot de alto rendimiento, un Mini Kit Pan/Tilt con Micro-servos y un Arduino Leonardo para el cerebro. La Pixy cámara dispone de potentes capacidades de procesamiento de imágenes y es capaz de rastrear objetos por color. Puede rastrear docenas de objetos simultáneamente y reportar sus ubicaciones para el Arduino Leonardo en tiempo real. El control de panorama incorporada e inclinación de los micro-servos es lo suficientemente rápido para seguir una pelota que rebota.
El Sumo Robot es un robot de seguimiento diseñado para un controlador de Arduino. Utiliza un moto reductor de precisión de metal para conducir bandas de caucho de silicona. Este Sumo Robot tiene buena tracción, con una velocidad máxima de aproximadamente 60 cm por segundo.
Juntando todo esto con un procesador Arduino Leonardo, se puede construir un divertido pequeño robot que perseguirá objetos o a ti como una mascota. El pequeño Pixy Pet Robot es simple de construir sin soldadura requerida, con herramientas comunes, puedes completar el montaje en menos de una hora.
Nota: Debido a las asignaciones de pin del Sumo Robot, este proyecto no funcionará con Arduino UNO u otro procesador basado en Atmega 328.
Materiales:
- Pixy CMUcam-5
- Mini Kit Pan/Tilt – Montado con micro-servos*
- Zumo Robot
- Arduino Leonardo
- Cinta adhesiva de espuma de doble cara
- 4 pilas AA.
* Si tienes algún servo motor, se pueden hacer algunas modificaciones para colocar el servo al Mini Kit Pan/Tilt.
Herramientas:
- Pinzas de corte
- Tijeras
- USB A to Mini-B cable (para conectar la cámara)
- USB A to Micro-B cable (para enviar información al micro controlador)
ENSAMBLANDO LA CÁMARA
Pixy únicamente es la cámara, sólo tenemos que conectar a la base del Kit Pan/Tilt con los servomotores.
ENSAMBLAMIENTO DEL KIT PAN/TILT CON LOS SERVOMOTORES
La base tiene soportes de montaje para un estilo diferente de módulo de cámara. No hay necesidad de quitar estos antes de acoplarse a la Pixy CMU-Cam.
Extrae las pestañas laterales de modo que queden a ras con la superficie para montaje de la cámara. El soporte está hecho de un nylon bastante blando, por lo que éstas son fáciles de quitar con un par de pinzas.
Hay dos pequeños soportes de alineación y un cable guía que deben recortarse también.
Corta una muesca para los conectores del cable que necesitamos para hacer espacio para los conectores del cable de la parte posterior del módulo de la cámara. Como se muestra en las fotos eliminará la parte superior izquierda de la escuadra.
Fija la cámara con un trozo de cinta adhesiva de espuma de doble cara y la posición de la parte posterior del módulo de la cámara como se muestra en la figura.
Retira el papel adhesivo y debes alinear el soporte de la cámara como se muestra en la figura.
Presiona hacia abajo con firmeza para adherir la cámara en el soporte de montaje. Su ensamblado final debe parecerse a la última foto.
Conecta los cables del Servomotor al cabezal de la cámara en la parte de atras. El cable del servomotor que controla el cabezal debe conectarse a la izquierda. El cable del servomotor de inclinación debe estar a la derecha. Asegúrate de que el cable marrón se encuentra en la parte inferior y el cable amarillo se encuentra en la parte superior.
Los dos conectores márcalos con cinta adhesiva juntos. Esto hará que sea más fácil para evitar que se mezclen si tienes que desconectar con ellos más tarde.
ENSAMBLADO FINAL
El Sumo Robot viene pre-montado, menos el procesador de Arduino Leonardo. Sólo tenemos que fijar el procesador y nuestra Pixy cámara y conecte los cables.
Fija a la cámara un trozo de cinta adhesiva de espuma de doble cara y la posición de la parte posterior del módulo de la cámara como se muestra en la figura.
Alinea el soporte de la cámara como se muestra en la figura. Los encabezados del conector en la parte posterior del módulo de la cámara encaja en la muesca se cortó en el paso anterior.
Presione hacia abajo con firmeza para adherir la cámara en el soporte de montaje. Su ensamblado final debe parecerse a la última foto.
Conecta el cable de datos gris
La parte que tiene 8 pines conectalas en la parte de atrás de tu cámara Pixy y el otro de 6 pines hacia el Arduino Leonardo, como se muestra en la figura.
Esta conexión está polarizado, por lo que sólo hay una manera de conectarlo. Asegúrate de alinear el cable rojo al borde asi poder manejar con facilidad tu Arduino Leonardo.
Fija la cámara y tu Arduino a los pines correctos a tu Sumo Robot. La cámara debe estar hacia delante, asegúrate esté fija al Sumo robot para evitar cualquier daño. Y eso es todo.
¡HORA DE JUGAR CON TU PIXY PET ROBOT!
Muestra a tu cámara Pixy la primera cosa que debe encontrar. La mejor manera de hacerlo es utilizando el software PixyMon así puedes ver exactamente lo que está encontrando tu PixyPet.
Encontrar un Pelotitas de colores brillantes es una buena idea para que tu PixyPet Robot persiga. Coloca tu bola de color o cualquier juguete llamativo a la vista de tu cámara Pixy.
CONECTA LA CÁMARA
Usa un cable mini-B USB para conectar la cámara Pixy a tu computadora.
Sugerencia: Si el software ya se ha cargado, ayuda a desconectar los servos durante el proceso de enseñanza.
EJECUTAR SOFTWARE PIXY MON
LINK DE DESCARGA PIXYMON
Descarga PixyMon desde el enlace de arriba. (Hay varias versiones, asegúrate de escoger el más adecuado para su sistema operativo.)
- Inicia la aplicación PixyMon.
- Seleccionar la opción “Cooket”; (haz clic en el icono con el chef del sombrero)
- Esta vista le mostrará exactamente lo que la cámara ve Pixy en tiempo real. Haz clic en Action ->Set signature1…; selecciona el área de la bola para enseñar un color a la cámara.
- Una vez aprendido, la cámara indicará que reconoció los objetos con un rectángulo.
- Utiliza un cable USB para conectar al Arduino Leonardo en el Pixy Pet y cargar el código.
Nota: Si la carga falló, intenta pulsar el botón reset en el lado izquierdo del zumo, poco antes de la compilación completa. Desconecta todos los cables USB y asegúrate de que los cables del servo están conectados a la cámara.
EL DISEÑO DEL CÓDIGO
El código del robot Pixy consiste en dos sistemas de control principales: el seguimiento de objetos con la Cámara Pixy y el mecanismo de movimiento horizontal / vertical y el seguimiento de objetos con la base del robot Sumo.
En conjunto, estos dos sistemas producen una respuesta aspecto muy natural, donde la «cabeza» se convierte en respuesta al movimiento y el «cuerpo» sigue. Ambos sistemas de control se basan en los bucles de realimentación de control . Para una explicación detallada de cómo funciona?
Seguimiento de objetos
El Seguimiento de objetos está implementado en la función TrackBlock. El duro trabajo de detección de objetos y la ubicación es manejado por el sistema de procesamiento de imagen dentro de la cámara Pixy. Se analiza la imagen e identifica los objetos que coinciden con las características de color del objeto que está siendo seguido. A continuación, informa del tamaño de la posición y los colores de todos los objetos detectados de nuevo a la Arduino. En el Arduino, utilizamos esta información para ajustar los servos de giro e inclinación para tratar de seguir el objeto en el centro del campo de visión
- //—————————————
- //Detección de los objetos con los servomotores
- (Basado en Pixy CMUcam5 ejemplo de giro e inclinación)
- //—————————————
- int TrackBlock (int blockCount)
- {
- int trackedBlock = 0;
- long maxSize = 0;
- Serial.print(«blocks =»);
- Serial.println(blockCount);
- for (int i = 0; i < blockCount; i++)
- {
- if ((oldSignature == 0) || (pixy.blocks[i].signature == oldSignature))
- {
- long newSize = pixy.blocks[i].height * pixy.blocks[i].width;
- if (newSize > maxSize)
- {
- trackedBlock = i;
- maxSize = newSize;
- }
- }
- }
- int32_t panError = X_CENTER – pixy.blocks[trackedBlock].x;
- int32_t tiltError = pixy.blocks[trackedBlock].y – Y_CENTER;
- update(panError);
- update(tiltError);
- setServos(panLoop.m_pos, tiltLoop.m_pos);
- oldX = pixy.blocks[trackedBlock].x;
- oldY = pixy.blocks[trackedBlock].y;
- oldSignature = pixy.blocks[trackedBlock].signature;
- return trackedBlock;
- }
El control del Kit Pan / Tilt se implementa utilizando 2 instancias de la clase ServoLoop – una para la sartén y una para la inclinación. ServoLoop es un bucle de control de retroalimentación usando tanto el control Proporcional + Derivativo (PD). Las mediciones son los grupos x (para pan) e Y (tilt) de las posiciones de los bloques reportados por la cámara Pixy. Las consignas son la posición x, y del centro de visión de la cámara. Y las salidas son las posiciones de los servos. En cada paso a través del bucle principal, calculamos los errores de los controles de giro e inclinación como la diferencia entre las mediciones y los puntos de ajuste. Entonces invocamos los algoritmos de control ServoLoop para calcular las salidas.
- //—————————————
- // Servo
- //Proporcional Derivado
- //Bucle de seguimiento de movimiento horizontal/ vertical de servomotor
- // (Basado en Pixy CMUcam5 Código ejemplo)
- //—————————————
- class ServoLoop
- {
- public:
- ServoLoop(int32_t proportionalGain, int32_t derivativeGain);
- void update(int32_t error);
- int32_t m_derivativeGain;
- int32_t m_proportionalGain;
- int32_t m_prevError;
- int32_t m_pos;
- };
- // Construcción de ServoLoop
- ServoLoop::ServoLoop(int32_t proportionalGain, int32_t derivativeGain)
- {
- m_pos = RCS_CENTER_POS;
- m_proportionalGain = proportionalGain;
- m_derivativeGain = derivativeGain;
- m_prevError = 0x80000000L;
- }
- // Servomotor Actulización
- // Calcula nueva salida en base a nuevos resultados
- // Error y el estado actual.
- void ServoLoop::update(int32_t error)
- {
- long int velocity;
- char buf[32];
- if (m_prevError!=0x80000000)
- {
- velocity = (error*m_proportionalGain + (error – m_prevError)*m_derivativeGain)>>10;
- m_pos += velocity;
- if (m_pos>RCS_MAX_POS)
- {
- m_pos = RCS_MAX_POS;
- }
- else if (m_pos<RCS_MIN_POS)
- {
- m_pos = RCS_MIN_POS;
- }
- }
- m_prevError = error;
- }
- // fin del código del servomotor
Siguiendo más objetos
El siguiente comportamiento del objeto se implementa en la función FollowBlock. FollowBlock utiliza el control solo proporcional. Pero tenemos dos mediciones (tamaño y posición PAN) y dos salidas (de izquierda y los motores de accionamiento derecha). El tamaño (altura por bloque de ancho) nos da una idea aproximada de lo lejos que está el objeto y lo utilizamos para calcular el » forwardSpeed ’. Esto hace que el robot actualice la medida en que se acerca el objeto. Si el objeto parece más grande que el valor designado, forwardSpeed llegará a ser negativo y el robot hará una copia de seguridad.
- // —————————————
- // Siguiendo objetos o bloques con el sumo robot
- //Hace girar la base del sumo robot
- //Hace girar el Kit Pan / Tilt.
- //Cabeza del Pixy Pet Robot
- // —————————————
- int32_t size = 400;
- void FollowBlock(int trackedBlock)
- {
- int32_t followError = RCS_CENTER_POS – panLoop.m_pos; //Busca el objeto en el centro
- //tamaño de detección del objeto
- size += pixy.blocks[trackedBlock].width * blocks[trackedBlock].height;
- size -= size >> 3;
- // La velocidad en que avanza disminuye a medida de que se acerca al objeto
- (el objeto se hace grande para la cámara pixy)
- int forwardSpeed = constrain(400 – (size/256), -100, 400);
- //La dirección es proporcional a los tiempos de error de la velocidad de avance.
- int32_t differential = (followError + (followError * forwardSpeed))>>8;
- //Ajustar la velocidad de izquierda y derecha dependiendo de la diferencial de dirección.
- int leftSpeed = constrain(forwardSpeed + differential, -400, 400);
- int rightSpeed = constrain(forwardSpeed – differential, -400, 400);
- // Establece la velocidad del motor
- setLeftSpeed(leftSpeed);
- setRightSpeed(rightSpeed);
- }
La posición de movimiento horizontal (una de las salidas del control de seguimiento) nos dice hasta qué punto se gira la cabeza lejos del punto de ajuste (en línea recta). Este valor se utiliza para controlar el diferencial de velocidad entre los motores izquierdo y derecho – haciendo que el robot volverse hacia el objeto que está siguiendo.
EL CÓDIGO
Copia el siguiente código en el IDE de Arduino. Asegúrate de que haz seleccionado «Arduino Leonardo» en Herramientas-> Placa:
- Pixy Pet Robot
- Partes de éste código se basaron en giro e inclinación del ejemplo de código Pixy CMcam-5
- Ejemplo de código
- #include <SPI.h>
- #include <Pixy.h>
- #include <ZumoMotors.h>
- #define X_CENTER 160L
- #define Y_CENTER 100L
- #define RCS_MIN_POS 0L
- #define RCS_MAX_POS 1000L
- #define RCS_CENTER_POS ((RCS_MAX_POS-RCS_MIN_POS)/2)
- //—————————————
- // Servomotor
- //Proporcional Derivado
- //Bucle se seguimiento de movimiento horizontal/ vertical.
- // (Basado en Pixy CMUcam5 Código ejemplo)
- //—————————————
- class ServoLoop
- {
- public:
- ServoLoop(int32_t proportionalGain, int32_t derivativeGain);
- void update(int32_t error);
- int32_t m_pos;
- int32_t m_prevError;
- int32_t m_proportionalGain;
- int32_t m_derivativeGain;
- };
- // Construcción ServoLoop
- ServoLoop::ServoLoop(int32_t proportionalGain, int32_t derivativeGain)
- {
- m_pos = RCS_CENTER_POS;
- m_proportionalGain = proportionalGain;
- m_derivativeGain = derivativeGain;
- m_prevError = 0x80000000L;
- }
- // Servomotor Actualización
- // Calcula los nuevos resultado
- // Error y el estado actual del sumo .
- void ServoLoop::update(int32_t error)
- {
- long int velocity;
- char buf[32];
- if (m_prevError!=0x80000000)
- {
- velocity = (error*m_proportionalGain + (error – m_prevError)*m_derivativeGain)>>10;
- m_pos += velocity;
- if (m_pos>RCS_MAX_POS)
- {
- m_pos = RCS_MAX_POS;
- }
- else if (m_pos<RCS_MIN_POS)
- {
- m_pos = RCS_MIN_POS;
- }
- }
- m_prevError = error;
- }
- //Fin de código del servo
- //—————————————
- Pixie pixie; // declarando los objetos a la cámara
- ServoLoop panLoop(200, 200); // Regulacion de la cabeza
- ServoLoop tiltLoop(150, 200); // Regulación de la inclinación
- ZumoMotors motors; // declara motores del sumo
- //—————————————
- // Configura y se ejecuta
- //—————————————
- void setup()
- {
- Serial.begin(9600);
- Serial.print(«Starting…\n»);
- init();
- }
- uint32_t lastBlockTime = 0;
- //—————————————
- // Bucle principal- se ejecuta continuamente
- //—————————————
- void loop()
- {
- uint16_t blocks;
- blocks = pixy.getBlocks();
- // Si se tienen objetos enfrente, el pixy robot lo seguirá
- if (blocks)
- {
- int trackedBlock = TrackBlock(blocks);
- FollowBlock(trackedBlock);
- lastBlockTime = millis();
- }
- else if (millis() – lastBlockTime > 100)
- {
- setLeftSpeed(0);
- setRightSpeed(0);
- ScanForBlocks();
- }
- }
- int oldX, oldY, oldSignature;
- //—————————————
- // Seguidor de objetos
- // basado en el ejemplo de PIXY cmuCAM5
- //—————————————
- int TrackBlock(int blockCount)
- {
- int trackedBlock = 0;
- long maxSize = 0;
- Serial.print(«blocks =»);
- Serial.println(blockCount);
- for (int i = 0; i < blockCount; i++)
- {
- if ((oldSignature == 0) || (pixy.blocks[i].signature == oldSignature))
- {
- long newSize = pixy.blocks[i].height * pixy.blocks[i].width;
- if (newSize > maxSize)
- {
- trackedBlock = i;
- maxSize = newSize;
- }
- }
- }
- int32_t panError = X_CENTER – pixy.blocks[trackedBlock].x;
- int32_t tiltError = pixy.blocks[trackedBlock].y – Y_CENTER;
- update(panError);
- update(tiltError);
- setServos(panLoop.m_pos, tiltLoop.m_pos);
- oldX = pixy.blocks[trackedBlock].x;
- oldY = pixy.blocks[trackedBlock].y;
- oldSignature = pixy.blocks[trackedBlock].signature;
- return trackedBlock;
- }
- //—————————————
- // se acciona el sumo bot para seguir los bloques
- //
- // Este código hace girar la base del sumo robot
- // y que se mueva para seguir los objetos
- // Mueve la base deL kit pan/ tilt.
- //La cabeza del Pixy Pet Robot
- //—————————————
- int32_t size = 400;
- void FollowBlock(int trackedBlock)
- {
- int32_t followError = RCS_CENTER_POS – panLoop.m_pos; //Busca el centro del objeto
- // Detecta el área del yamaño del objeto
- size += pixy.blocks[trackedBlock].width * pixy.blocks[trackedBlock].height
- size -= size >> 3;
- // La velocidad disminuye a medida de que se acerca al objeto
- int forwardSpeed = constrain(400 – (size/256), -100, 400);
- // La dirección es proporcional a los tiempos de error de la velocidad de avance.
- int32_t differential = (followError + (followError * forwardSpeed))>>8;
- // Adjusta las velocidades de la izquierda y derecha
- int leftSpeed = constrain(forwardSpeed + differential, -400, 400);
- int rightSpeed = constrain(forwardSpeed – differential, -400, 400);
- //Establece la velocidad del motor
- motors.setLeftSpeed(leftSpeed);
- motors-setRightSpeed(rightSpeed);
- }
- //—————————————
- // seguidor de objetos
- //
- //Este código hace girar la cabeza del robot hasta que detecte los objetos y los siga.
- //—————————————
- int scanIncrement = (RCS_MAX_POS – RCS_MIN_POS) / 150;
- uint32_t lastMove = 0;
- void ScanForBlocks()
- {
- if (millis() – lastMove > 20)
- {
- lastMove = millis();
- m_pos += scanIncrement;
- if ((panLoop.m_pos >= RCS_MAX_POS)||(panLoop.m_pos <= RCS_MIN_POS))
- {
- m_pos = random(RCS_MAX_POS * 0.6, RCS_MAX_POS);
- scanIncrement = -scanIncrement;
- if (scanIncrement < 0)
- {
- setLeftSpeed(-250);
- setRightSpeed(250);
- }
- else
- {
- motors.setLeftSpeed(+180);
- motors.setRightSpeed(-180);
- }
- delay(random(250, 500));
- }
- pixy.setServos(panLoop.m_pos, tiltLoop.m_pos);
- }
- }
JUGAR A LA PELOTA
- Desconecta todos los cables USB y asegúrate de que los cables de servo están conectados a la cámara.
- Asegúrate de que las baterías estén instaladas en la base del robot Sumo.
- Enciende el Sumo usando el interruptor ON / OFF situado en la parte trasera del Sumo.
Una vez que el bootloader ha terminado (el LED amarillo se detendrá intermitente), Pixy comenzará a buscar la pelota. Una vez que se ve la pelota se moverá hacia ella y comenzará seguir a su alrededor.
CONCEPTOS BÁSICOS DE CONTROL DE REALIMENTACIÓN
Mediciones, puntos de ajuste, errores y salidas
Para empezar, vamos a definir algunos términos comúnmente utilizados para describir sistemas de control:
- Medición – Este suele ser el valor del parámetro que se está tratando de controlar. Podría ser la temperatura, presión, velocidad, posición o cualquier otro parámetro. Antes de que pueda controlar cualquier cosa, usted tiene que ser capaz de medirlo.
- Punto de ajuste – Este es el valor deseado para el parámetro que está tratando de controlar.
- Error – Esta es la diferencia entre el valor deseado y el valor medido.
- Salida – Este es un valor calculado basado en el error. Se alimenta de nuevo en el sistema para «corregir» el error y llevar la medición más cerca del punto de ajuste.
Hay muchas maneras en las que el valor de salida se puede calcular. Vamos a discutir algunas de las más comunes.
TIPOS DE CONTROL
Hay muchas maneras en las que el valor de salida se puede calcular. Vamos a discutir algunas de las más comunes.
CONTROL ON/OFF
En este tipo de control, los únicos valores para la salida están encendidos o apagados. Así es como el termostato de tu casa funciona. Si la medida de temperatura está por debajo del punto de ajuste de la temperatura, se enciende el calor. Si la medidade temperatura está por encima del punto de ajuste , que lo apaga. Para prevenir el cambio rápido que pueda dañar el sistema, por lo general hay alguna diferencia entre el «on» y el «apagado». Esto se llama «histéresis».
Un controlador de encendido / apagado con histéresis s a veces llamado un «controlador de espacio diferencial». Eso suena muy sofisticado, pero sigue siendo un tipo muy primitivo de controlador. De control de encendido / apagado funciona bien para controlar la temperatura de su casa, pero no es muy bueno para aplicaciones como el control de movimiento del robot.
CONTROL PID
Es probable que hayas oído hablar de PID controladores.
PID- Significa P roporcional, I ntegral y D de control de la derivada. Por lo que un controlador PID es en realidad 3 tipos de controlador en uno. Debido a esto, el control PID es bastante versátil. Sin embargo, no todas las aplicaciones requieren las tres formas de control.
Muchos controladores llamados PID son en realidad sólo funcionan como PI , PD o incluso sólo P controladores tipo. Las aplicaciones de control de movimiento como el Duende de mascotas generalmente usan mayormente P o PD control.
CONTROL PROPORCIONAL
El control proporcional permite una respuesta mucho más suave que un simple control de encendido / apagado. El control proporcional calcula una salida de valor que es proporcional a la magnitud del error . Los pequeños errores yeild una pequeña respuesta. Los errores más grandes resultan en una respuesta más agresiva.
El control proporcional se puede usar sola, o completa con el control integral o derivado según sea necesario. El código objeto Pixy siguiente utiliza control sólo proporcional. El código de seguimiento de objeto utiliza tanto el control proporcional y derivativo.
MANDO INTEGRAL
El control integral se integra el error en el tiempo. Si la medición no está convergiendo en el punto de ajuste, la salida integral sigue aumentando para conducir el sistema hacia el punto de ajuste.
El control integral es bueno para empujando procesos estables y predecibles más a la perfección. Desde Pixy de mascotas debe responder siempre rápidamente a los movimientos impredecibles al azar, control integral no es apropiado.
CONTROL DE LA DERIVADA
Derivado de control se ve en la tasa de cambio en el error. Si el error se acerca rápidamente a cero, la salida del cálculo derivado de los intentos de frenar las cosas para evitar el sobre paso del punto de ajuste. El algoritmo de seguimiento de objetos Pixy utiliza el control derivado en conjunción con el control proporcional para ayudar a prevenir el exceso de corrección cuando el seguimiento de objetos.