Proyecto Cardrone Con PINGUINO – OPEN HARDWARE / SOFTWARE / MIND
Menú Close

Proyecto Cardrone Con PINGUINO

Este proyecto intenta la reutilización de un vehículo radio controlado, reemplazando toda la electrónica con un micro-controlador PINGUINO, y el medio de transmisión, reemplazarlo con el protocolo de comunicación 802.15.4 ( XBEE/ZigBee), ofreciendo la capacidad de control a una distancia mayor a un kilometro.

Adicionando a esta mejora, y entendiendo que a esta altura se podría controlar el vehículo con cualquier ordenador con un módulo XBEE conectado por USB… podríamos agregar la facilidad de controlarlo mediante un teléfono móvil o ipad IPHONE/ANDROID”, mediante la utilización de PROCESSING y con la librería de comunicación OSCnet (para el caso de los dispositivos móviles se utiliza el programa TouchOSC).

Nota: la versión de touchOSC para ANDROID es 100% gratis y de libre distribución.

La de IPHONE tiene un precio de $5.- dólares por única vez en la tienda de APPELSTORE

Video del proyecto finalizado.

Video de funcionamiento

.

HERRAMIENTAS NECESARIAS PARA ESTA APLICACIÓN:

PROCESSING _ link general http://processing.org/

Link de descarga http://processing.org/download/

LIBRERÍA OSC incluida en el paquete original (OSC OpenSoundControl)

Pensada principalmente para controlar equipos de música profesionales de forma remota.

LIBRERÍA SERIAL incluida en el paquete original

TOUCH OSC _ link general y link de descarga http://hexler.net/software/touchosc

Touch OSC versión de prueba para IPHONE desde el APPLE STORE ($5 dolares)

http://itunes.apple.com/us/app/touchosc/id288120394?mt=8

Touch OSC versión para ANDROID (totalmente gratis)

http://hexler.net/software/touchosc-android

PINGUINOPIC

Se utiliza un pingüino modelo 18f4550 adquirido en el KIT armado de la web http://pinguino.walii.es

GUI PINGUINO PIC

Utilizamos la versión de PINGÜINO en este momento la 9.04

http://www.hackinglab.org/pinguino/download/latestpinguino/

XBEE pro & XBEE explorer USB

Se utilizan dos XBEEs PRO de 60mW y un adaptador USB “XBEE Explorer” adquiridos en sparkfun.com

http://www.sparkfun.com/products/8742

http://www.sparkfun.com/products/8687

IDEA DEL PROYECTO:

Lo primero que debemos tener en cuenta es: ¿qué es lo que queremos controlar?…

En principio son dos motores uno de dirección izquierda/derecha y otro de movimiento delante/atrás. Ambos necesitan una inversión de tensión en sus extremos y encontrarse sin energía en su punto de reposo. Al mismo tiempo necesitamos 2 tipos de luces, una blanca para la iluminación general y otra infrarroja para la adición futura de una cámara wifi.

También se nos ocurrió agregarle un Buzzer tipo bocina o alarma…

En total deberíamos tener 2 puertos digitales para los motores, más otros 3 para luces y buzzer.

5 puertas digitales comandadas vía serie. Por ejemplo con teclas identificadas para cada acción.

NOTA: también es posible reenviar vía serie, parámetros como temperatura, posición GPS, nivel de señal wifi, iluminación y humedad. Para esto utilizaríamos los puertos analógicos, esto lo he dejado para más adelante…


INICIO PROYECTO (COMUNICACIÓN SERIE)

El proyecto comienza con el kit PINGUINO programándolo para ser controlado vía Puerto serie, esto se genera fácilmente, utilizando el siguiente código. En modo de prueba puede ser comandado con un adaptador RS232 a TTL conectado en nuestro ordenador y con cualquier programa de consola… para verificar que enviamos y recibimos los datos.

Nota: cabe la aclaración que esto no funciona con un adaptador USB/SERIE, necesitamos un puerto serie propietario para que funcione… si no poseemos un puerto serie propietario deberíamos tener un adaptador directo USB/TTL

El programa de PINGÜINO que creamos a tal efecto es el siguiente:

[sourcecode language=»py»]

/*
*
* IPHONE+TouchOSC+PROCESSING+XBEE+PINGUINO
*
* Example to control a remote control card
* with all the PINGUINO PIC electronic
* And received all the control information
* from a XBEE
*/

uchar key;
int i;
void setup()
{
for ( i=0 ; i <8; i++){
pinMode(i,OUTPUT);
digitalWrite(i,LOW);
}
Serial.begin(9600);
}

void loop()
{
if (Serial.available()>0) //only apply if we have information into the serial port { key=Serial.read();
if (key==’l’) digitalWrite(4,digitalRead(4)^1);//change the status of port 4 to invert value
if (key==’i’) digitalWrite(5,digitalRead(5)^1);//change the status of port 4 to invert value
if (key==’b’) digitalWrite(7,digitalRead(7)^1);//change the status of port 4 to invert value
if (key==’a’) digitalWrite(0,HIGH); //go a head
if (key==’s’) digitalWrite(1,HIGH); //go back
if (key==’d’) digitalWrite(2,HIGH); //left
if (key==’f’) digitalWrite(3,HIGH); //right
if (key==’z’) digitalWrite(0,LOW); //stop move a head
if (key==’x’) digitalWrite(1,LOW); //stop move back
if (key==’c’) digitalWrite(2,LOW); //stop turn left
if (key==’v’) digitalWrite(3,LOW); //stop turn right

Serial.print("received… OK!!!"); //debug serial answer
Serial.print("\n\r");
Serial.flush();//clear the serial buffer }

}
[/sourcecode]

NOTA: AL ser una comunicación serie, tenemos que entender que recibiríamos carácter tras carácter a una velocidad de 9600, para convertir esta comunicación en multitarea para nuestro pinguino, entonces se nos ocurrió cambiar el estado de las puertas digitales con diferentes teclas, por tal motivo si presionamos la tecla “a” elevaríamos el estado de la puerta “0”, y este no bajaría hasta no recibir un carácter “x”.

¿Por qué hacemos esto? Básicamente si elevaríamos el estado de alguna puerta “solo al recibir un carácter “a” ”, cuando querremos ir recto y girar al mismo tiempo, no podríamos, ya que cuando recibimos el carácter “a” el vehículo circularía hacia delante, pero en el siguiente siclo si recibiéramos un carácter “d” (para girar la dirección), al no recibir más el carácter “a” el motor se detendría y no giraríamos.

Esto lo podremos probar mediante una consola serie (RS232 to TTL) conectada directamente con el pingüino.

Verificando que cada vez que enviamos un comando, nos responde la consola con el mensaje “received…OK!!!”, y al mismo tiempo verificamos la activación de las salidas digitales, esto se puede hacer con LEDs colocados en cada puerta.


Tras verificar que todo funciona utilizando la comunicación serie tradicional, pasaremos a transformar esta comunicación a protocolo 802.15.4, para convertir la comunicación serie vía cable, en una conexión inalámbrica.


¿COMO PROGRAMAMOS LOS MÓDULOS XBEE?

Cuando reseteamos o conectamos un modulo XBEE, si dentro de los primeros 10 segundos este reciben por su RX tres signos de sumar “+++” ingresaremos en el modo de configuración, y podremos escribir lo que deseemos en nuestro modulo.

Básicamente el único parámetro que necesitamos configurar es el PAN ID, ya que todos los módulos dentro del mismo PanID se hablaría y escucharían, sin necesidad de hacer nada mas, quizás más adelante podríamos configurarlo con mayor seguridad, indicando las direcciones MAC para los interlocutores, pero con esta modificación ya tendríamos funcionando nuestros módulos.

NOTA: también existe una opción de configurarlos en Windows con el programa XCTU, el cual es gratuito y se descarga del siguiente vínculo. http://www.digi.com/support/productdetl.jsp?pid=3352&osvid=57&s=316&tp=5&tp2=0

Hay que escribirle el mismo PanID a los dos módulos, y automáticamente funcionarían como un BRIDGE (PUENTE) “todo lo que recibo en el puerto serie lo envío por mi conexión inalámbrica, y de la forma inversa, todo lo que recibo en la conexión inalámbrica lo transmito a mi puerto serie”.

Para escribir la configuración deberemos conectar cada modulo al adaptador serie (Xbee Explorer USB), en la consola serie configuraremos el puerto en cuestión… y antes que pasen los 10 segundos presionaremos tres veces seguidas el signo de sumar “+++”

Entrando en el modo de configuración.

Para ver el PanID actualmente configurado haremos lo siguiente.

“ATID [enter]” lo que nos devolverá el PanID original de fabrica siempre es “1111

Para modificar el PanID:

“ATID1234 [enter]” por ejemplo en este caso el PanID será “1234

Para verificar que lo ha cogido deberemos hacer nuevamente:

“ATID” con resultado “1234”, si lo ha configurado correctamente.

Para finalmente escribir la configuración en la memoria del modulo haremos:

“ATWR”

Y por último para salir del modo de configuración, podremos esperar 10 segundos o escribir:

“ATCN”


Comandos de consola del modulo XBEE

Command Description Valid Values Default Value
ID The network ID of the Xbee module. 0 – 0xFFFF 3332
CH The channel of the Xbee module. 0x0B – 0x1A 0X0C
SH and SL The serial number of the Xbee module (SH gives the high 32 bits, SL the low 32 bits). Read-only. 0 – 0xFFFFFFFF
(for both
SH and SL)
different for each module
MY The 16-bit address of the module. 0 – 0xFFFF 0
DH and DL The destination address for wireless communication (DH is the high 32 bits, DL the low 32). 0 – 0xFFFFFFFF
(for both
DH and DL)
0 (for both DH and DL)
BD The baud rate used for serial communication with the Arduino board or computer. 0 (1200 bps)
1 (2400 bps)
2 (4800 bps)
3 (9600 bps)
4 (19200 bps)
5 (38400 bps)
6 (57600 bps)
7 (115200 bps)
RE Restore factory default settings (note that like parameter changes, this is not permanent unless followed by the WRcommand).
WR Write newly configured parameter values to non-volatile (long-term) storage. Otherwise, they will only last until the module loses power.
CN Exit command mode now. (If you don’t send any commands to the module for a few seconds, command mode will timeout and exit even without a CN command.)

Ahora conectaremos ambos módulos, uno en el pinguino y otro en el ordenador mediante el adaptador “XBEE EXPLORER USB”


Procederemos a verifica la comunicación, con un programa de consola y pulsando caracteres en la consola, deberíamos recibir el mensaje de respuesta “received… OK”

Imagen ilustrativa.


En este momento tenemos una comunicación inalámbrica entre el ordenador y el PINGÜINO, lo bueno de esta comunicación es su distancia de alcance y su fiabilidad a la hora de interrupciones e interferencias, ya que es un protocolo de comunicación.

Llegados a este punto podríamos encender LEDs remotamente desde un ordenador hasta un PINGÜINO a casi un kilometro de distancia, en este momento continuaremos realizando el nivel de electrónica de potencia para poder comandar los motores y luces en cuestión.




CIRCUITOS ELECTRÓNICOS DE POTENCIA

Los siguientes circuitos pueden ayudarnos a realizar la tarea. Ya sea para comandar RELES como para encender luces y buzzer, sin exceder el nivel de potencia de salida del micro controlador.

Circuito para comandar RELES


Circuito para encender LUCES y el BUZZ


Tras construir el circuito propuesto, podremos comandar a distancia las funciones de nuestro vehículo remoto.

Esto con solo presionar unas teclas en una consola serie en nuestro ordenador, y sin ningún cable de por medio, gracias a XBEE.





TOUCHOSC

Ahora vamos un paso más allá, intentando controlar el vehículo mediante un teléfono o tablet (IPHONE o ANDROID), conectada en la misma red WIFI en la cual tendremos nuestro ordenador con el XBEE conectado.

Lo primero será crear una plantilla para controlar nuestro vehículo en formato táctil. Esto lo hacemos con el programa TouchOSC editor.

Se descargar desde el siguiente link. http://hexler.net/software/touchosc


Configurando en cada caso, que es lo que necesitaríamos recibir en cada botón y plantilla.

El archivo de configuración de TouchOSC que hemos creado se puede descargar del siguiente vínculo. (Hay que estar registrado y logeado)

http://pinguino.walii.es/download/TouchOSC-CAR-drone.touchosc

Con esto obtendremos las siguientes plantillas en el teléfono.

Una para el control via teclado y para el control vía acelerómetros.




Con esto ya instalado en el teléfono, procederemos a realizar la interfaz de enlace entre TouchOSC (el teléfono o IPAD) con el ordenador, esto lo hacemos con PROCESSING, ya que actualmente posee las librerías necesarias para realizar el trabajo, por un lado posee las librerías de OSC (OpenSoundControl), la cual interpreta los mensajes del TouchOSC enviados al puerto TCP 8000 de nuestro ordenador, y por otro lado la librería de comunicación SERIE “librería ProcessingSerial” para convertir los datos recibidos en el puerto 8000 en información entendible por el puerto serie, en este caso el modulo XBEE (que más tarde transmitirá esta información al PINGÜINO).

PROCESSING

Código de Processing para realizar la interlocución de la información.

[sourcecode language="py"]

/**
 * IPHONE+TouchOSC+PROCESSING+XBEE+PINGUINO
 *
 * Example displaying a way to modify a remote toy
 * and used it with IPHONE
 * http://pinguino.walii.es
 * pinguino@walii.es  walii@walii.es walterleonardo@gmail.com
 */

import oscP5.*;
import netP5.*;
OscP5 oscP5;
import processing.serial.*;
Serial port; // The serial port object

float xrot = 0;
float zrot = 0;
float xrot_targ = 0;
float zrot_targ = 0;
float orientation = 0;
float v_up = 0.0f;
float v_down = 0.0f;
float v_left = 0.0f;
float v_right = 0.0f;
float v_light = 0.0f;
float v_ir = 0.0f;
float v_buzz = 0.0f;
float vl_up = 0.0f;
float vl_down = 0.0f;
float vl_left = 0.0f;
float vl_right = 0.0f;
float vl_light = 0.0f;
float vl_ir = 0.0f;
float vl_buzz = 0.0f;
float valor= 0.0f;
float calx;
float calz;
String serial;

void setup() {
  size(500,500);
  frameRate(25);
  /* start oscP5, listening for incoming messages at port 8000 */
  oscP5 = new OscP5(this,8000);
  /* start Serial, sending messages to PINGUINO port via XBEE */
  port = new Serial(this, Serial.list()[2], 9600);
  serial = Serial.list()[2];//force to connect with XBEE
  println(Serial.list()); //debug serial ports
  println(serial);//serial port selected
}
//Messages from OSCTOUCH=IPHONE
void oscEvent(OscMessage theOscMessage) {

    String addr = theOscMessage.addrPattern();
    float  val  = theOscMessage.get(0).floatValue();

//detect buttons from screen "CONTROL TACTIL" value /1
if(addr.equals("/1/up"))  { v_up = val; }
    else if(addr.equals("/1/down"))  { v_down = val; }
    else if(addr.equals("/1/left"))  { v_left = val; }
    else if(addr.equals("/1/rigth"))  { v_right = val; }
    else if(addr.equals("/1/ligth"))  { v_light = val; }
    else if(addr.equals("/1/ir"))  { v_ir = val; }
    else if(addr.equals("/1/buzz"))  { v_buzz = val; }

//data from IPHONE's accelerometer screen "Accelerometro" velue /2
//only receive data if press the button into this screen
if(addr.equals("/2/activate")){ valor = val;}
if(valor==1.0f){
  if(theOscMessage.checkAddrPattern("/accxyz")==true) {
      xrot_targ = (theOscMessage.get(0).floatValue()*90)-calx;
      zrot_targ = ((theOscMessage.get(1).floatValue()*90)*-1)-calz;
      orientation = theOscMessage.get(2).floatValue();
  print("x= " + xrot_targ + " z= " + zrot_targ + " Rot= " + orientation +"\n\r");
  }
}
//calibration button for accelerometer
if(addr.equals("/1/info")){calx=xrot_targ;calz=zrot_targ;}

//debug for accelerometer from IPHONE
//if (addr=="/accxyz"){}else{print(addr);print(" "+ val);print("\n\r");}
//debug for buttons of the IPHONE
print("val_up" + v_up + " val_down" + v_down + " val_left" + v_left + " val_right" + v_right + "\n\r");
print("val_light" + v_light + " val_ir" + v_ir + " val_buzz" + v_buzz + "\n\r");
}

//paint
void draw() {
    background(0);
    fill(0, 196, 168);
    stroke(0, 196, 250);
    //up arrow
    if(v_up == 1.0f) {triangle(200,100,250,50,300,100);rect(225,100,50,50);}
    fill(168);
    //down arrow
    if(v_down == 1.0f) {triangle(200,150,250,200,300,150);rect(225,100,50,50);}
    fill(0,0,255);
    //left arrow
    if(v_left == 1.0f) {triangle(175,125,225,75,225,175);rect(225,100,50,50);}
    fill(255,0,0);
    //right arrow
    if(v_right == 1.0f) {triangle(275,75,325,125,275,175);rect(225,100,50,50);}
    fill(0,168,0);
    //buzz indicator
    if(v_buzz == 1.0f) {
    triangle(250,300,270,345,250,390);
    triangle(260,290,300,345,260,400);
    rect(225,300,20,5);
    rect(225,320,20,5);
    rect(225,340,20,5);
    rect(225,360,20,5);
    rect(225,380,20,5);
    }
    fill(0,0,255);
    stroke(255,0,0);
    //ir light indicator
    if(v_ir == 1.0f) {
    line(110,400,170,350);
    line(170,350,160,340);
    line(160,340,220,300);
    line(220,300,190,340);
    line(190,340,200,350);
    line(200,350,110,400);
    }
    fill(0,0,0);
    stroke(0,0,255);
    //light indicator
    if(v_light == 1.0f) {
    line(10,400,70,350);
    line(70,350,60,340);
    line(60,340,120,300);
    line(120,300,90,340);
    line(90,340,100,350);
    line(100,350,10,400);
    }
    //paint with accelerometers's values
    stroke(0);
    fill(0);
    if(valor==1.0f){
    if(xrot_targ>=40) {
    v_up=1.0f;
    }else{
    v_up=0.0f;
    };
    if(xrot_targ<=-40) {
    v_down=1.0f;
    }else{
    v_down=0.0f;
    };
    if(zrot_targ<=-20) {
    v_left=1.0f;
    }else{
    v_left=0.0f;
    };
    if(zrot_targ>=20) {
    v_right=1.0f;
    }else{
    v_right=0.0f;
    };
    if(zrot_targ<=20 && zrot_targ>=-20) {
    v_right=0.0f;
    v_left=0.0f;
    };
    if(xrot_targ<=20 && xrot_targ>=-20) {
    v_up=0.0f;
    v_down=0.0f;
    };
    }
 //write serial port from the information obtain with TOUCHOSC
  if(v_up==1.0f && vl_up==0.0f){port.write("a");delay(100);port.write("a");vl_up=1.0f;}
  if(v_up==0.0f && vl_up==1.0f){port.write("z");delay(100);port.write("z");vl_up=0.0f;}
  if(v_down==1.0f && vl_down==0.0f){port.write("s");delay(100);port.write("s");vl_down=1.0f;}
  if(v_down==0.0f && vl_down==1.0f){port.write("x");delay(100);port.write("x");vl_down=0.0f;}
  if(v_left==1.0f && vl_left==0.0f){port.write("f");delay(100);port.write("f");vl_left=1.0f;}
  if(v_left==0.0f && vl_left==1.0f){port.write("v");delay(100);port.write("v");vl_left=0.0f;}
  if(v_right==1.0f && vl_right==0.0f){port.write("d");delay(100);port.write("d");vl_right=1.0f;}
  if(v_right==0.0f && vl_right==1.0f){port.write("c");delay(100);port.write("c");vl_right=0.0f;}

  if(v_light==1.0f && vl_light==0.0f){port.write("l");delay(100);vl_light=1.0f;}
  if(v_light==0.0f && vl_light==1.0f){port.write("l");delay(100);vl_light=0.0f;}
  if(v_ir==1.0f && vl_ir==0.0f){port.write("i");delay(100);vl_ir=1.0f;}
  if(v_ir==0.0f && vl_ir==1.0f){port.write("i");delay(100);vl_ir=0.0f;}
  if(v_buzz==1.0f && vl_buzz==0.0f){port.write("b");delay(100);vl_buzz=1.0f;}
  if(v_buzz==0.0f && vl_buzz==1.0f){port.write("b");delay(100);vl_buzz=0.0f;}
port.clear();//clear serial port, to clean the buffer.
}
[/sourcecode]

 

He agregado un poco de grafica al interlocutor, en este caso PROCESSING, para indicarnos que es lo que recibe y como lo interpreta, esto es más que nada como debug, no es necesario ni siquiera mirarlo…

En donde observaremos las flechas de dirección, y el encendido de las luces y el buzzer.

Identificando delante y atrás.


Izquierda y derecha



Bueno, con esto ya tendríamos control de nuestro vehículo remoto. Y lo bueno es que no necesitamos estar delante del ordenador para controlarlo, aunque sí con el teléfono dentro del rango del WIFI.

Video demostrativo.

http://www.youtube.com/watch?v=2ja9bCb-puU

FUTURO

Más adelante procederemos a instalarle algunos sensores y una cámara wifi, lo cual nos reduce el rango de distancia a una red WIFI tradicional, pero nos otorga una característica muy particular a nuestro invento.

Nota: para mantener el rango de distancia de nuestro vehículo (mayor a 1 kilómetros), podríamos colocarle en vez de una cámara wifi, un teléfono móvil con cámara y realizando en tiempo real una video conferencia 3g.


DIAGRAMA COMPLETO DEL CIRCUITO PROPUESTO



Related Posts

7 Comments

  1. paulo

    Obrigado pela oportunidade. Como converter arquivo index.xml para index.touchosc ? Até breve.

  2. damian

    Hola, excelente trabajo, yo me estoy iniciando hace poco en la electronica y me he decidido a implementar el Cardrone, ya tendo todo ok hasta la comunicación con los xBee, mi problema nace con la parte del iphone, he descargado el TouchOSC editor y luego la plantilla del proyecto la cual al descomprimir queda un archivo index.xml, el cual no es reconocido por el TouchOSC editor. Además no me queda claro lo de las librerias OSC y Serial, estas bienen con el processing o debo descargarlas aparte, y como se instalan o donde se guardan.

    La otra duda es que tipo de reles son recomendable para usar, desde ya muchas gracias.

    Damián
    damianwg@gmail.com

  3. walterleonardo

    tienes que cargarle los drivers al processing para entender al TOUCHOSC:.. en la web de este ultimo tienes las librerías para instalarlas en el Processing.
    el archivo de touchOSC no entiendo porque es asi… tengo que revisarlo… pero creía que estaba completo… y tiene que ser un nombre.touchosc

    Luego lo verifico…

  4. Haks01

    Buenas tardes, oye ya no subiste el archivo, me harías el gran favor de subirlo, ya que me estoy adentrando en un proyecto muy parecido y me serviría mucho para comprender el funcionamiento, y solo me falta la plantilla de TouchOSC.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.