Complemento de informática I Proyecto integrador: Adquisición de datos utilizando dispositivo con Sistema Operativo Android Amarfil, Federico Reg. 19460 2014 Introducción Con la gran cantidad de dispositivos celulares inteligentes disponibles en el mercado, y los distintos sensores que los mismos poseen, es interesante la adquisición de datos con los mismos para luego ser utilizados en distintas aplicaciones. El objetivo del presente proyecto en particular es utilizar un dispositivo celular con sistema operativo Android para la adquisición de los datos del sensor Vector de Giro y transmitirlo a una computadora a través del puerto USB. Desarrollo Hardware Los sensores, como se los describe en la página de desarrollo de Android, o bien pueden ser una pieza de hardware, que adquiere los datos, o una combinación de piezas que indirectamente conforman los datos. Por ejemplo, en un dispositivo podría haber un sensor de Vector de Rotación, o bien el mismo sensor podría ser una combinación de otros (acelerómetro y sensor magnético). El celular utilizado es un Samsung Galaxy Y GT-B5510L el cual tiene los siguientes sensores: - Acelerómetro - Sensor Magnético - Sensor de Orientación - Sensor de Proximidad - Sensor de Gravedad - Acelerómetro Lineal - Vector de Rotación De los cuales se decidió por sencillez utilizar el sensor Vector de Rotación cuya descripción de hace a continuación: El vector de Rotación representa la orientación del dispositivo como una combinación de ángulos y ejes, alrededor de los cuales el dispositivo ha rotado un ángulo θ. Los 3 elementos del Vector de Rotación se expresan de la siguiente manera: x*sin(θ/2) y*sin(θ/2) z*sin(θ/2) Donde la magnitud del Vector de Rotación es igual a sin( θ/2), y la dirección del vector es igual a la dirección del eje de rotación. Los 3 elementos del Vector de Rotación son iguales a lo últimos 3 componentes de un cuaternión unitario (cos(θ/2), x*sin(θ/2), y*sin( θ/2), z*sin( θ/2). Los elementos de este vector son adimensionales. El sistema de coordenadas de referencia se define en una base ortonormal directa el cual tiene las siguientes características: • X es el producto vectorial Y x Z. Es tangencial a suelo en la ubicación del dispositivo y apunta aproximadamente al este. • Y es tangencial al suelo en la ubicación actual del dispositivo y apunta hacia el polo norte geomangnético. • Z apunta hacia el cielo y es perpendicular al plano de suelo. Implementación Al no encontrar en la documentación de Android Developer lo necesario para realizar una comunicación via Puerto USB, se decicdió consultar otras fuentes en la Web. En ellas se expresaba que no existían los medios para hacerlo de forma directa, sin embargo proponían la siguiente solución: La creación de una comunicación TCP con ayuda de un programa (adb.exe) incluido en el sdk de Android. Adb es una aplicación para comunicación por medio de comandos desde el ordenador al pc. Se utiliza por ejemplo para abrir un Shell del dispositivo y manejarlo desde nuestro ordenador. El comando es: <ruta_adb>\adb.exe forward tcp:Puerto_elegido tcp: Puerto_elegido Entonces, la Aplicación Android se posiciona como servidor a la espera de una conexión a traves del puerto creado con el Adb. server = new ServerSocket(); server.setReuseAddress(true); server.bind(new InetSocketAddress(ADDRESS,PUERTO)); server.setSoTimeout(30000); Toast.makeText(getApplicationContext(), "Esperando Conexion", Toast.LENGTH_SHORT); client = server.accept(); El programa de PC usa el puerto como cliente conectándose al celular de esta manera. Inmediatamente comienza la espera de adquisición de datos, los cuales son colocados en un contenedor, hasta que se recibe un dato determinado (0, 0, 0) marcando el fin de la transmisión. Luego, se puede dar a los datos cualquier tratamiento requerido: Ordenar con diferentes criterios. Guardar en un archivo. Recuperar los datos guardados previamente desde un archivo. Las fuentes generadas son se detallan en los siguientes Anexos: - Anexo I: Definición e implementación de clase - Anexo II: Archivo Main. Bibliografía - Apuntes de Cátedra - Documentación Android Developers - Androides Verdes Fritos – Comunicación entre Ordenador y dispositivo Android mediante USB. Anexo I : Definición e implementación de clase /* * VectGiro.h * * Created on: 15/08/2014 * Author: Alumno */ #ifndef VECTGIRO_H_ #define VECTGIRO_H_ #include #include #include #include <iostream> <fstream> <winsock.h> <string> using namespace std; class VectGiro { private: int orden; float x,y,z; public: friend friend friend friend ostream& operator << (ostream &out, VectGiro &dato); VectGiro& operator >> (SOCKET &socket, VectGiro &dato); istream& operator >> (istream &in, VectGiro &dato); ofstream& operator << (ofstream &out, VectGiro &dato); void SetValores(char *in); int VerOrden(); float VerX(); float VerY(); float VerZ(); void Orden(int ord); void Show(); }; bool PorOrden( VectGiro &eme, VectGiro &ene); bool PorX( VectGiro &eme, VectGiro &ene); #endif /* VECTGIRO_H_ */ /* * VectGiro.cc * * Created on: 15/08/2014 * Author: Alumno */ #include "vectgiro.h" using namespace std; ostream& operator<< (ostream &out, VectGiro &dato){ out << endl << "Orden: " << dato.orden<< endl << dato.x << "\n" << dato.y << "\n" << dato.z << "\n"; return out; } ofstream& operator << (ofstream &out, VectGiro &dato){ out << dato.orden << " " << dato.x << " " << dato.y << " " << dato.z<< "!" << endl; return out; } istream& operator>> (istream &in, VectGiro &dato){ string check; in >> dato.orden; in >> dato.x; in >> dato.y; in >> dato.z; in >> check; if (check != "!") { cout << "Error de formato" << endl; } return in; } VectGiro& operator>> (SOCKET &socket,VectGiro &dato){ char in[256]; float tmpx, tmpy, tmpz; if (recv(socket, in, 256, 0) != 0){ sscanf(in, "%f %f %f",&tmpx,&tmpy,&tmpz); dato.x=tmpx; dato.y=tmpy; dato.z=tmpz; } else { dato.x= dato.y = dato.z =0; } return dato; } void VectGiro::Show(){ cout << *this; cout.flush(); } void VectGiro::SetValores(char *in){ float tmpx,tmpy,tmpz; sscanf(in, "%f %f %f",&tmpx,&tmpy,&tmpz); this->x=tmpx; this->y=tmpy; this->z=tmpz; } void VectGiro::Orden(int ord){ orden = ord; } int VectGiro::VerOrden () { return orden;} float VectGiro::VerX () { return x;} float VectGiro::VerY () { return y;} float VectGiro::VerZ () { return z;} bool PorOrden(VectGiro &eme, VectGiro &ene){ //float ret; //ret =eme.VerOrden() - ene.VerOrden(); //return (ret < 0); return ( eme.VerOrden() < ene.VerOrden()); } bool PorX(VectGiro &eme, VectGiro &ene){ return eme.VerX() < ene.VerX(); } Anexo II : Archivo Main. /* * main.cpp * * Created on: 17/07/2014 * Author: Alumno */ #include #include #include #include #include <winsock.h> <list> <fstream> <string> <iostream> #include "vectgiro.h" using namespace std; #define SOCK_STREAM 1 #define AF_INET 2 #define IPPROTO_TCP 6 //Defino para mi poryecto #define ADDRESS "127.0.0.1" #define PUERTO 10000 int menu(); bool ConnectToHost (int puerto , string ipAddress);//Conectar host void CloseConnection();//Cerrar conexiones SOCKET cliente; //(otras declaraciones?) SOCKET PASCAL socket(int,int,int); int PASCAL closesocket(SOCKET); //Comienza main ---------------int main (){ VectGiro datos; list<VectGiro> lista; list<VectGiro>::iterator ii; bool exit = false; bool conectado; int ord=0; ofstream guardar ; ifstream leer; string temp; while (!exit){ switch (menu()){ case 1: cout << "Intentando conexion..."; cout.flush(); conectado = ConnectToHost(PUERTO,ADDRESS); if (conectado == false) { cout << "No se puede conectar a host"; return 0; }else { cout << "Conexion exitosa!"; } while (datos.VerX() != 0 && datos.VerY() != 0 && datos.VerZ() != 0){ datos.Orden(ord); ord++; cliente >> datos; lista.push_back(datos); datos.Show(); } lista.pop_back(); break; case 2: guardar.open("Datos.dat"); if (!guardar){ cerr << "Error al abrir archivo para escritura"; break; } for (ii=lista.begin();ii != lista.end() ;ii++){ guardar << *ii; guardar.flush(); } guardar.close(); if (guardar.is_open()) cout << "Error al cerrar archivo" << endl; break; case 3: for (ii=lista.begin(); ii != lista.end() ; ii++){ cout << *ii; } cout << endl <<endl; break; case 4: lista.sort(PorOrden); break; case 5: lista.sort(PorX); break; case 6: leer.open("Datos.dat",ios::in); if (!leer){ cout << endl << "Error al leer archivo" << endl; break; } leer.seekg(0,ios::beg); while(!leer.eof()){ leer >> datos; lista.push_back(datos); } leer.close(); break; case 9: exit = true; break; default: cout << "Elija una opcion correcta" << endl; break; } } CloseConnection(); return 0; } //Termina main ------------------- int menu(){ int opcn; cout << "Ejija Opcion:\n" <<"1- Obtener Datos\n" <<"2- Guardar Datos\n" <<"3- Mostrar \n" <<"4- Ordenar (Por onden de llegada)\n" <<"5- Ordenar (Por X)\n" << "6- Recuperar desde archivo\n" <<endl<<endl<<endl<<"9-Salir\n"; cin >> opcn; return opcn; } bool ConnectToHost (int puerto , string ipAddress){ //Arrancar Winsock WSADATA wsadata; int error = WSAStartup(0x0202,&wsadata); if (error) return false; //Hubo error if (wsadata.wVersion != 0x0202){ correcta? //Version de winsock WSACleanup();//Limpia winsock return false; } //Ahora adb para iniciar conexion system("D:\\DATOS\\Docume~1\\Fede\\Comple~1\\adtbu~1\\sdk\\platfo~1\\adb forward tcp:10000 tcp:10000"); //Obtener informacion para inicializar un socket SOCKADDR_IN target; target.sin_family = AF_INET; target.sin_port = htons(puerto); //Puerto a conectarse target.sin_addr.s_addr = inet_addr (ADDRESS); cliente = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); // Crea socket if (cliente == INVALID_SOCKET){ return false; //No se pudo crear socket } cout << "Socket creado con exito.."; cout.flush(); //a tratar de conectarse if(connect(cliente, (SOCKADDR *) &target, sizeof(target)) == SOCKET_ERROR){ return false; // No se pudo conectar } else { return true; } //Temporal, a ver que pasa return true; } void CloseConnection() { //Cerrar socket si este existe if (cliente) closesocket(cliente); } WSACleanup();