A finales de 2009 los creadores de Processing anunciaron que iban a dar soporte a la plataforma de Android. La verdad es que fue una noticia muy buena, ya que el famoso entorno de creación de gráficos animados iba a poder ejecutar sketchs dentro de móviles que tuviesen a Android como sistema operativo. Pero no se han quedado ahí y además admite la posibilidad de usar las características embebidas en los dispositivos móviles como el GPS, la brújula electrónica, enviar y recibir sms, etc y por supuesto bluetooth.
Lo que explicaré en este artículo son los pasos que he seguido para crear una conexión desde mi teléfono Android con un dispositivo bluetooth y poder enviarle información a la par que recibirla dibujando los resultados de una forma gráfica con Processing para Android.
Ya en su momento me dediqué a programar en symbian algo parecido:
Sin embargo finalmente lo deseché porque la plataforma de symbian tiene ya poco futuro y porque las APIS eran confusas, mal explicadas y no se puede acceder a todos los elementos de hardware con ellas.
Por otra parte no hay que compararlo con Amarino, ya que Amarino es una aplicación ya hecha para Android con una interfaz definida y está pensado para usarse con Arduino, sin embargo aquí vamos a programar nuestra propia aplicación con su propia interfaz para cualquier dispositivo que tenga un controlador bluetooth.
Dicho esto lo primero es necesario instalar todo el entorno de desarrollo, aquí viene bien explicado en castellano por lo que no considero necesario añadir más.
Antes de empezar, sería interesante que echarais un vistazo a dos páginas para entender mejor lo que viene a continuación. Por una parte la API de Android para bluetooth para comprender qué posibilidades nos ofrece. Por otra parte unos conceptos y un ejemplo de cómo usar Android y gestionar el hardware con Processing. A los que hayáis programado en Processing puede resultar extraño que además de poder usar las funciones básicas del entorno, se puedan incluir librerias y código de Java y la API Android. Esto es debido a que tanto Android como Processing tienen una fuerte vinculación con el lenguaje de programación Java y su unión ha creado una suerte de mescolanza que reúne lo mejor de ambos mundos.
El objetivo es que podamos crear una interfaz completa para que nos muestre los dispositivos bluetooth que hay alrededor, a continuación podamos elegir uno de ellos y finalmente conectarnos a este para enviar y recibir datos. En este caso en concreto voy a conectar mi móvil HTC Wildfire S con una placa Arduino a través de un módulo bluetooth. La placa Arduino enviará a mi móvil cada segundo un valor comprendido entre 0 y 39 y este lo mostrará en su pantalla. En el móvil habrá dibujado un botón que cuando se pulse enviará un 0 a la placa Arduino para encender o apagar el led del pin 13.
Este es el código fuente del sketch para la placa Arduino:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
boolean estado; void setup() { Serial.begin(9600); pinMode(13, OUTPUT); digitalWrite(13, LOW); randomSeed(analogRead(0)); estado = false; } void loop() { delay(1000); Serial.write(random(40)); while(Serial.available() > 0) { Serial.read(); estado = !estado; digitalWrite(13, estado); } } |
Ahora la parte de Android y Processing. A partir de aquí iré explicando los conceptos a medida que publico el código fuente para comentar los aspectos que considero que son más relevantes y finalmente pondré el código fuente integro.
Para poder programar el bluetooth de nuestro dispositivo basado en Android junto con Processing empezaremos por crear un sketch, daremos los permisos BLUETOOTH y BLUETOOTH_ADMIN en el menú Android/Sketch Permissions e importaremos las clases necesarias para que todo funcione:
1 2 3 4 5 6 7 8 9 10 11 12 |
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import java.util.ArrayList; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Method; |
Hay algunas librerías que, como veremos más adelante, podemos prescindir de ellas dependiendo de lo que queremos hacer y lo bien o mal que nos funcione.
A continuación vamos a añadir los métodos típicos de un sketch de Processing: setup y draw:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
void setup() { size(320,480); frameRate(25); f1 = createFont("Arial",20,true); f2 = createFont("Arial",15,true); stroke(255); } void draw() { switch(estado) { case 0: listaDispositivos("BUSCANDO DISPOSITIVOS", color(255, 0, 0)); break; case 1: listaDispositivos("ELIJA DISPOSITIVO", color(0, 255, 0)); break; case 2: conectaDispositivo(); break; case 3: muestraDatos(); break; case 4: muestraError(); break; } } |
En el método setup forzamos a que la resolución de la pantalla sea de 320 píxeles de ancho x 480 píxeles de alto (HVGA), ya que es una configuración muy extendida dentro del mundo de los móviles. Establecemos que la frecuencia de refresco sea de 25 fps. Creamos dos tipos de fuentes con las que dibujar después los textos que queramos.
En el método draw vamos a simular varias ventanas dependiendo del estado en el que se encuentre nuestra aplicación en cada momento. Así nada más empezar se muestra la ventana de búsqueda de dispositivos, a continuación se ofrece al usuario que seleccione uno de los dispositivos mostrados:
Después se intenta conectar con el dispositivo elegido y finalmente si tiene éxito se muestra la ventana con los datos enviados por Arduino y con el botón que mencionaba antes:
Si algo falla se muestra el error en una ventana:
Un sketch de Proccesing para Arduino se trata como una Activity, por eso se puede inicializar todo en el evento OnStart cuando es llamado al arrancar la aplicación (OnCreate no es llamado).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
void onStart() { super.onStart(); println("onStart"); adaptador = BluetoothAdapter.getDefaultAdapter(); if (adaptador != null) { if (!adaptador.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); } else { empieza(); } } } |
En el evento OnStart primero debemos llamar al método onStart de la clase padre para inicializar correctamente. Después recuperamos el adaptador bluetooth del móvil y comprobamos si está activo. Si está activo empezamos a mostrar la lista de dispositivos. Si no lo está, lanzamos una petición para activarlo. En esta petición Android nos mostrará un mensaje similar a este en el móvil para activar el bluetooth:
Pulsemos la opción que pulsemos, se llamará al evento onActivityResult:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
void onActivityResult (int requestCode, int resultCode, Intent data) { println("onActivityResult"); if(resultCode == RESULT_OK) { println("RESULT_OK"); empieza(); } else { println("RESULT_CANCELED"); estado = 4; error = "No se ha activado el bluetooth"; } } |
Si hemos pulsado Si entonces empezaremos a mostrar la lista de dispositivos, si hemos pulsado No iremos directamente a la pantalla de error.
Cuando se abandona la aplicación se llama al evento onStop (onDestroy no es llamado) y aquí se pueden liberar los recursos que hayamos utilizado antes de terminar definitivamente.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
void onStop() { println("onStop"); /* if(registrado) { unregisterReceiver(receptor); } */ if(socket != null) { try { socket.close(); } catch(IOException ex) { println(ex); } } super.onStop(); } |
En el evento OnStop vamos a hacer dos cosas, aunque una de ellas está comentada por una razón que explicaré más adelante. Lo que se ve es que se cierra un socket que no es otra cosa que la conexión que hayamos establecido con nuestro dispositivo para poder liberar los recursos asociados a este. Finalmente se llama al método onStop de la clase padre para cerrar correctamente la aplicación.
El método empieza sirve para rellenar la lista de dispositivos bluetooth que más tarde mostraremos al usuario.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
void empieza() { dispositivos = new ArrayList(); /* registerReceiver(receptor, new IntentFilter(BluetoothDevice.ACTION_FOUND)); registerReceiver(receptor, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED)); registerReceiver(receptor, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)); registrado = true; adaptador.startDiscovery(); */ for (BluetoothDevice dispositivo : adaptador.getBondedDevices()) { dispositivos.add(dispositivo); } estado = 1; } |
Inicializamos un array que rellenaremos de objetos BluetoothDevice. Aquí comento una problemática que me he encontrado: Puedes incluir los dispositivos que hay alrededor del móvil o bien incluir los que previamente se hayan emparejado. La parte que está comentada (y por tanto la del método onStop que desregistra el Receiver) se usa para lanzar un proceso de búsqueda de dispositivos bluetooth que estén cerca de nuestro móvil: se registra el empiece, cada dispositivo que se encuentre y el final de la búsqueda. Para manejar estos eventos se usa una clase del tipo BroadcastReceiver ya inicializada:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
BroadcastReceiver receptor = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { println("onReceive"); String accion = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(accion)) { BluetoothDevice dispositivo = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); println(dispositivo.getName() + " " + dispositivo.getAddress()); dispositivos.add(dispositivo); } else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(accion)) { estado = 0; println("Empieza búsqueda"); } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(accion)) { estado = 1; println("Termina búsqueda"); } } }; |
Cuando se empieza la búsqueda se encuentra en el estado 0 para mostrar la lista de dispositivos a medida que van apareciendo. Por cada dispositivo bluetooth que se encuentre se añade al array de dispositivos bluetooth, Cuando termina la búsqueda se pasa al estado 1 para que el usuario seleccione el dispositivo al que quiere conectarse.
El hacerlo de esta forma provoca que más adelante cuando se conecte al dispositivo bluetooth se tenga que mostrar una ventana preguntando por un código de emparejamiento para vincular el móvil con este.El problema es que esa ventana no se visualiza cuando están los gráficos mostrándose y el proceso de conexión dará finalmente un error. Por eso la otra alternativa que he encontrado es emparejar el dispositivo bluetooth a mano con el móvil y rellenar la lista de dispositivos con los que ya están vinculados en el móvil, así no pedirá el código de emparejamiento y se conectará con el dispositivo bluetooth directamente.
En varias ocasiones hay que capturar donde pulsa el dedo del usuario para saber qué acción quiere realizar. Esto se consigue con el evento mouseReleased:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
void mouseReleased() { switch(estado) { case 0: /* if(registrado) { adaptador.cancelDiscovery(); } */ break; case 1: compruebaEleccion(); break; case 3: compruebaBoton(); break; } } |
Depende del estado en el que encontremos hará una acción diferente. Cuando estamos en el estado 0 y si se usara la búsqueda de dispositivos bluetooth (pero no es así por los motivos que he comentado) al pulsar en la pantalla cancelaría la búsqueda y lanzaría un ACTION_DISCOVERY_FINISHED al BroadCastReceiver visto anteriormente. Si estamos en el estado 1 se buscaría qué dispositivo bluetooth de la lista ha pulsado el usuario para conectarse a el. Si estamos en el estado 3 se comprueba si se ha pulsado el botón que envía un byte al dispositivo bluetooth.
El método que comprueba que elección ha hecho el usuario en el estado 1 es compruebaEleccion:
1 2 3 4 5 6 7 8 9 10 |
void compruebaEleccion() { int elegido = (mouseY - 50) / 55; if(elegido < dispositivos.size()) { dispositivo = (BluetoothDevice) dispositivos.get(elegido); println(dispositivo.getName()); estado = 2; } } |
Con una sencilla fórmula matemática se puede sacar el dispositivo bluetooth que el usuario ha elegido en base a en qué parte de la pantalla ha pulsado. Después se pasa al estado 2 (Conexión al dispositivo bluetooth).
La lista de dispostivos bluetooth se hace con el método listaDispositivos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
void listaDispositivos(String texto, color c) { background(0); textFont(f1); fill(c); text(texto,0, 20); if(dispositivos != null) { for(int indice = 0; indice < dispositivos.size(); indice++) { BluetoothDevice dispositivo = (BluetoothDevice) dispositivos.get(indice); fill(255,255,0); int posicion = 50 + (indice * 55); if(dispositivo.getName() != null) { text(dispositivo.getName(),0, posicion); } fill(180,180,255); text(dispositivo.getAddress(),0, posicion + 20); fill(255); line(0, posicion + 30, 319, posicion + 30); } } } |
Se recorre el array de dispositivos bluetooth mostrando su nombre y su dirección MAC. Es usada tanto en el estado 0 (listado de dispositivos bluetooth a medida que van apareciendo en la búsqueda) como en el estado 1 (selección del dispositivo bluetooth al que conectarse).
La conexión con el dispositivo bluetooth se hace con el método conectaDispositivo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
void conectaDispositivo() { try { socket = dispositivo.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); /* Method m = dispositivo.getClass().getMethod("createRfcommSocket", new Class[] { int.class }); socket = (BluetoothSocket) m.invoke(dispositivo, 1); */ socket.connect(); ins = socket.getInputStream(); ons = socket.getOutputStream(); estado = 3; } catch(Exception ex) { estado = 4; error = ex.toString(); println(error); } } |
Aquí ocurre un caso especial. Para conectar con el dispositivo bluetooth se debe crear un socket con el dispositivo y después hacer la conexión propiamente dicha con el método connect. Sin embargo dependiendo de con qué dispositivo se conecte puede dar problemas el método que se use para obtener ese socket. La versión normal es la que está en el metodo y se supone que es la estándar, pero a mi me dio problemas al conectar al blueooth de un PC y tuve que usar las dos líneas que aparecen comentadas . Sin embargo con el módulo bluetooth de Sure la línea que aparece actualmente ha funcionado sin problemas. Como estamos creando una conexión SPP (como si fuese un puerto serie virtual) a través del protocolo RFCOMM, debemos obtener el socket que conecta con el servicio 00001101-0000-1000-8000-00805F9B34FB, que es el identificador único de servicio para SPP en el estandar Bluetooth. El método connect es bloqueante por lo que dejará la aplicación paralizada hasta que se conecte realmente o surja un error. Google dice que se debe usar un thread para separar el hilo de ejecución principal con el de la conexión, pero creo que está solución es más sencilla. Una vez se ha conectado se pueden recuperar el stream de entrada y el de salida para recibir y enviar datos respectivamente con el dispositivo bluetooth. A continuación se pasa al estado 3 (Visualización de datos e interacción con el botón). Si hubiese algún error se pasaría al estado 4 mostrando qué lo ha provocado.
El método que muestra los datos enviados desde el dispositivo bluetooth es muestraDatos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
void muestraDatos() { try { while(ins.available() > 0) { valor = (byte)ins.read(); } } catch(Exception ex) { estado = 4; error = ex.toString(); println(error); } background(0); fill(255); text(valor, width / 2, height / 2); stroke(255, 255, 0); fill(255, 0, 0); rect(120, 400, 80, 40); fill(255, 255, 0); text("Botón", 135, 425); } |
Simplemente comprueba si se ha recibido algún byte y lo muestra. También muestra el botón ficticio que puede pulsar el usuario.
El método que se ejecuta cuando el usuario pulsa el botón es compruebaBoton:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
void compruebaBoton() { if(mouseX > 120 && mouseX < 200 && mouseY > 400 && mouseY < 440) { try { ons.write(0); } catch(Exception ex) { estado = 4; error = ex.toString(); println(error); } } } |
Si se comprueba que el usuario ha pulsado en el área del botón se envía un byte con valor 0 al dispositivo bluetooth, que actualmente lo que hace es encender o apagar el led de la placa Arduino. Si hubiese algún error se pasaría al estado 4 mostrando qué lo ha provocado.
Finalmente el método que muestra los errores es muestraError:
1 2 3 4 5 6 7 8 9 10 |
void muestraError() { background(255, 0, 0); fill(255, 255, 0); textFont(f2); textAlign(CENTER); translate(width / 2, height / 2); rotate(3 * PI / 2); text(error, 0, 0); } |
Simplemente muestra el texto del error de forma apaisada para mostrar cadenas largas.
Dejo el código fuente entero:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import java.util.ArrayList; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Method; private static final int REQUEST_ENABLE_BT = 3; ArrayList dispositivos; BluetoothAdapter adaptador; BluetoothDevice dispositivo; BluetoothSocket socket; InputStream ins; OutputStream ons; boolean registrado = false; PFont f1; PFont f2; int estado; String error; byte valor; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// BroadcastReceiver receptor = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { println("onReceive"); String accion = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(accion)) { BluetoothDevice dispositivo = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); println(dispositivo.getName() + " " + dispositivo.getAddress()); dispositivos.add(dispositivo); } else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(accion)) { estado = 0; println("Empieza búsqueda"); } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(accion)) { estado = 1; println("Termina búsqueda"); } } }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void setup() { //size(320,480); frameRate(25); f1 = createFont("Arial",20,true); f2 = createFont("Arial",15,true); stroke(255); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void draw() { switch(estado) { case 0: listaDispositivos("BUSCANDO DISPOSITIVOS", color(255, 0, 0)); break; case 1: listaDispositivos("ELIJA DISPOSITIVO", color(0, 255, 0)); break; case 2: conectaDispositivo(); break; case 3: muestraDatos(); break; case 4: muestraError(); break; } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void onStart() { super.onStart(); println("onStart"); adaptador = BluetoothAdapter.getDefaultAdapter(); if (adaptador != null) { if (!adaptador.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); } else { empieza(); } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void onStop() { println("onStop"); /* if(registrado) { unregisterReceiver(receptor); } */ if(socket != null) { try { socket.close(); } catch(IOException ex) { println(ex); } } super.onStop(); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void onActivityResult (int requestCode, int resultCode, Intent data) { println("onActivityResult"); if(resultCode == RESULT_OK) { println("RESULT_OK"); empieza(); } else { println("RESULT_CANCELED"); estado = 4; error = "No se ha activado el bluetooth"; } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void mouseReleased() { switch(estado) { case 0: /* if(registrado) { adaptador.cancelDiscovery(); } */ break; case 1: compruebaEleccion(); break; case 3: compruebaBoton(); break; } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void empieza() { dispositivos = new ArrayList(); /* registerReceiver(receptor, new IntentFilter(BluetoothDevice.ACTION_FOUND)); registerReceiver(receptor, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED)); registerReceiver(receptor, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)); registrado = true; adaptador.startDiscovery(); */ for (BluetoothDevice dispositivo : adaptador.getBondedDevices()) { dispositivos.add(dispositivo); } estado = 1; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void listaDispositivos(String texto, color c) { background(0); textFont(f1); fill(c); text(texto,0, 20); if(dispositivos != null) { for(int indice = 0; indice < dispositivos.size(); indice++) { BluetoothDevice dispositivo = (BluetoothDevice) dispositivos.get(indice); fill(255,255,0); int posicion = 50 + (indice * 55); if(dispositivo.getName() != null) { text(dispositivo.getName(),0, posicion); } fill(180,180,255); text(dispositivo.getAddress(),0, posicion + 20); fill(255); line(0, posicion + 30, 319, posicion + 30); } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void compruebaEleccion() { int elegido = (mouseY - 50) / 55; if(elegido < dispositivos.size()) { dispositivo = (BluetoothDevice) dispositivos.get(elegido); println(dispositivo.getName()); estado = 2; } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void conectaDispositivo() { try { socket = dispositivo.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); /* Method m = dispositivo.getClass().getMethod("createRfcommSocket", new Class[] { int.class }); socket = (BluetoothSocket) m.invoke(dispositivo, 1); */ socket.connect(); ins = socket.getInputStream(); ons = socket.getOutputStream(); estado = 3; } catch(Exception ex) { estado = 4; error = ex.toString(); println(error); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void muestraDatos() { try { while(ins.available() > 0) { valor = (byte)ins.read(); } } catch(Exception ex) { estado = 4; error = ex.toString(); println(error); } background(0); fill(255); text(valor, width / 2, height / 2); stroke(255, 255, 0); fill(255, 0, 0); rect(120, 400, 80, 40); fill(255, 255, 0); text("Botón", 135, 425); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void compruebaBoton() { if(mouseX > 120 && mouseX < 200 && mouseY > 400 && mouseY < 440) { try { ons.write(0); } catch(Exception ex) { estado = 4; error = ex.toString(); println(error); } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void muestraError() { background(255, 0, 0); fill(255, 255, 0); textFont(f2); textAlign(CENTER); translate(width / 2, height / 2); rotate(3 * PI / 2); text(error, 0, 0); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
Hello Oscar!
I’m really excited about your project! I need to read data emitted bluetooth loop with an Android device (samsung galaxy tab 2) inspired me and I would like your project to the reception party bluetooth.
But as soon as I copy your code I get small defects:
No library found for android.bluetooth
No library found for android.bluetooth
No library found for android.bluetooth
No library found for android.content
No library found for android.content
No library found for android.content
No library found for android.content
Android SDK Tools Revision 21
Installed at C:UsersSimonAppDataLocalAndroidandroid-sdk
Project Type: Application
Project Target: Android 2.3.3
API level: 10
Library dependencies:
No Libraries
——————
API<=15: Adding annotations.jar to the classpath.
Merging AndroidManifest files into one.
Manifest merger disabled. Using project manifest only.
No AIDL files to compile.
No RenderScript files to compile.
Generating resource IDs…
Generating BuildConfig class.
BUILD FAILED
C:UsersSimonAppDataLocalAndroidandroid-sdktoolsantbuild.xml:705: The following error occurred while executing this line:
C:UsersSimonAppDataLocalAndroidandroid-sdktoolsantbuild.xml:718: Compile failed; see the compiler error output for details.
Total time: 3 seconds
I tried to find information on the missing libraries and it is said that they are supposed to be downloaded with the SDK. (I download all MAJs SDK) I work with a processing configuration 2.0.b3 vista
I need help, please!
Thank you in advance
Did you give BLUETOOTH and BLUETOOTH_ADMIN permissions in Android/Sketch Permissions menu?
Yes, android/sketch permissions is okay. Now in Sketch/add file… I search the android API and bluetooth’s library are ok. But now, after this when I compile it’s fail again :s
Thanks again
I followed bluetooth mode of your program, as well as other websites but when I want to just separate blutooth I have a compilation error.
The all libraries (the header).
BroadcastReceiver Receiver = new BroadcastReceiver ()
{
public void onReceive (Context context, Intent intent)
{
println («onReceive»);
String action = intent. GetAction ();
if (BluetoothDevice. ACTION_FOUND. equals (action))
{
BluetoothDevice device = intent. GetParcelableExtra (BluetoothDevice. EXTRA_DEVICE);
println (dispositivo. getName () + «» + device. getAddress ());
devices. add (device);
}
else if (BluetoothAdapter. ACTION_DISCOVERY_STARTED. equals (action))
{
status = 0;
println («Lancer la recherche»);
}
else if (BluetoothAdapter. ACTION_DISCOVERY_FINISHED. equals (action))
{
status = 1;
println («Fin de la recherche»);
}
}
};
Thanks again
Me señala esta línea
socket = dispositivo.createRfcommSocketToServiceRecord(UUID.fromString(«00001101-0000-1000-8000-00805F9B34FB»));
Me sata error en este línea tu ayuda por favor.
socket = dispositivo.createRfcommSocketToServiceRecord(UUID.fromString(«00001101-0000-1000-8000-00805F9B34FB»));
Ahora es necesario importar la librería import java.util.UUID;
De nuevo yo, incluyendo esta línea ya no saca el error. No estaba reconociendo el UUID.
import java.util.UUID;
Gracias de nuevo
Hola, alguien pordria decirme donde descargar todas las librerias??.
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import java.util.ArrayList; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Method;
Llevo toda la mañana buscando…
Te tienes que descargar el SDK de Android
Hola, instale SDK de Android y sigo sin poder hacer correr el programa, me salen los siguientes errores:
No library found for android.bluetooth
No library found for android.bluetooth
No library found for android.bluetooth
No library found for android.content
No library found for android.content
No library found for android.content
No library found for android.content
Libraries must be installed in a folder named ‘libraries’inside the ‘sketchbook’ folder.
Utilizo processing 2.0b7
Ya consegui que encontrara las librerias. No tenia el processing en modo Android. Que bobada ¿verdad?. Los principios son duros!!.
Hey!
I found your code really helpful in understanding the bluetooth library so thank you so much!
Would just like to add that the line:
socket=dispositivo.createRfcommSocketToServiceRecord(UUID.fromString(«00001101-0000-1000-8000-00805F9B34FB»));
gave me errors too and I used the commented lines instead like you said. But then I figured that the error was because we needed to import UUID package. I added this line:
import java.util.UUID;
and it worked just fine 🙂
Thanks again 🙂
Yes, in processing 2.0 that import is necessary.
Estoy probando el sketch en el simulador y arranca, pero lo quiero instalar en un samsung galaxy con la version 2.2.1 Froyo….
En el emulador si selecciono la version 2.2 NO funciona ….. si selecciono 2.3.3 Si ….
me sale el siguiente error…
Lost connection with device while installing. Try again
debug:
Failure [INSTALL_FAILED_OLDER_SDK]
Shutting down any existing adb server..
imagino que habra que cambiar el sdk usado para compilarlo,,,, pero donde se cambia….??
Hola. Apenas estoy empezando a programar en Java y no entiendo muy bien la parte del código. ¿Cada uno va en una clase por separado o todo eso va en el main? Saludos
Va tal cual aparece en el sketch de Processing.
Soy nueva en java. Leí en comentarios que puede sustituirse el Processing con botones, cómo se hace eso?
Hello !
Very nice job but I get an error during the processing compilation : «cannot find symbol» and the line : «socket = dispositivo.createRfcommSocketToServiceRecord(UUID.fromString(«00001101-0000-1000-8000-00805F9B34FB»));» is highlighted
Can you help me ?
Prof.buchi, Strasbourg (France)
Try to import java.util.UUID
Buenas otra vez….
Después de hacer varias pruebas y actualizar mi samsung galaxy a la versión 2.3.3, ya funciona correctamente… Muchisimas gracias por el trabajo…
Quiero enviar otro dato desde el arduino al teléfono, pero no lo consigo.
quiero enviar en primer lugar un long, de millis y mostrarlo en el teléfono,( para mostrarlo después en el formato 00:00:000 ) pero no llega bien… he probado a enviar cada 100 milis un numero y al llegar a 255 empieza de cero otra vez…
y luego me gustaría enviar algun texto también …
alguna idea?? gracias
Un long son 4 bytes, tendrás que descomponerlo en arduino y enviarlos uno por uno , luego en processing los recuperas uno por uno y lo vuelves a componer.
ok!
gracias,, pruebo y te cuento… a ver si soy capaz de enviarlos separados en tres y volver a mostrarlos después…
un saludo.
Buenas otra vez….
He descompuesto el tiempo, en todos los valore… Es decir ..
MM:SS,DDD en 9 valores, y hago un serial.write de cada uno de ellos para enviarlos al telefono,
Pero no se como unirlos para mostrarlos…
Podrias orientarme? Gracias
No, envía los 4 bytes del millis:
unsigned long valor = millis();
Serial.write((valor & 0xFF000000) >> 24);
Serial.write((valor & 0xFF0000) >> 16);
Serial.write((valor & 0xFF00) >> 8);
Serial.write(valor & 0xFF);
Y luego ya en el sketch de Processing los vas recuperando:
unsigned long valor = ins.read() << 24; valor |= ins.read() << 16; valor |= ins.read() << 8; valor |= ins.read(); Así tienes en tu móvil la variable valor con el número que arduino te ha enviado. Ya sólo te falta formatear ese número en processing para mostrar HH:MM:SS,DDD
Ok !
Muchisimas gracias!
una pregunta, podria conectar dos smartphones con este programa sin ninguna modificacion y mostrar en pantalla de cada uno el byte mandado en este caso para encender el led del arduino? o qué modificacion habria que hacer?
El programa esta hecho para conectarse como cliente, si quieres hacerlo como servidor tendrás que seguir los pasos que aparecen en la documentación de google http://developer.android.com/guide/topics/connectivity/bluetooth.html#ConnectingDevices y modificar el programa.
Gracias le estoy echando un vistazo pero tengo ciertos problemas, ando con un proyecto entremanos, si no te importa, te podrias poner en contacto directamente a mi correo para poder explicarte lo que quiero hacer y asi pudieras asesorarme un poco? gracias.
Mi correo eso juanpredroortegaruiz@gmail.com
Sin animo de molestar, este tipo de comentarios están fuera de lugar en este blog.
Si buscas asesoramiento gratuito, lo indicado es ir a un foro del tema, plantear la duda y allí encontrarás ayuda para que puedas hacer tu proyecto, tampoco esperes que nadie lo realice por tí (como más de un caso se suele ver). Esto es lo que hacemos todos cuando tenemos unda duda de estos temas, hay muchos sitios donde resolverlas, con buscar en google saldrán unos cuantos.
Si buscas a alguien que te asesore de manera particular, a tu correo, lo indicado es pagar por ello, hay varios sitios para esto, ejemplo: http://www.infolancer.net/
Una cosa es hacer un blog porque nos guste, y otra cosa muy distinta es estar recibiendo peticiones de gente para que hagamos sus proyectos o les ayudemos con ellos (cansados estamos de ello), como comprenderas el tiempo libre que tenemos preferimos aplicarlo a nuestros propios proyectos.
Para ayudar y consultar dudas de manera gratuita están los foros.
Un saludo.
quizá no lo he explicado del mejor modo, mi intención no es es que los demás me hagan mi trabajo es simplemente resolver una duda sobre como declarar ciertas cosas en processing ya que soy bastante novato, nadie quiere perder su tiempo en cosas que resulten ser eso, una perdida de tiempo, pero tampoco veo correcto que esto de lugar a colgarme un sanBenito tan a la ligera, tendre que tener mas cuidado a la hora de explicarme en otras ocasiones. No sabia yo que crear una pequeña aplicación para guardar los archivos de mi pulsómetro de deporte fuera una app para dar lugar a un comentario de este tipo, el pedir ese «asesoramiento» por llamarlo así es porque quizá un mensaje de esas dimensiones intercederia en la dinamica principal del tema, pero deacuerdo, disculpad si os ha ofendido mi comentario.
Mi intención no era colgarte nada ni decir que no quieras hacer tu trabajo, simplemente indicarte que para resolver dudas sobre proyectos personales, los comentarios de un blog no es el sitio adecuado, y dejar una dirección de correo para ello tampoco lo es.
El sitio adecuado para estas cosas son los foros de internet, allí es donde se resuelven las dudas sobre los proyectos personales.
Siento que te haya tocado este comentario, ya que mi intención ni mucho menos era molestar, pero para que te hagas una idea, podemos tener cientos de correos de gente preguntando dudas sobre sus proyectos personales, mandandonos cosas a nuestros correos personales, y esperando a que les respondamos o les hagamos algo, lamentablemente esa es la actitud general que tenemos por aquí.
Solo volverte a indicar el uso de los foros para este tipo de peticiones, que era el fin de mi mensaje, y siento si en algún momento te ha molestado mi comentario.
Saludos.
Juan
Ten en cuenta que lo que está escrito en el artículo es lo que hay. Te puedo ayudar en cosas puntuales si se trata de algo del propio artículo y siempre en los comentarios (así otra gente lo puede ver también), pero cualquier otra ayuda que se salga del ámbito del artículo ya es tiempo del que desgraciadamente no dispongo. Como dice Jorge si es algo que te urge de programación en Processing puedes preguntarlo en los foros especializados http://forum.processing.org/ o si es algo de programación en Android lo puedes hacer en el foro de htcmania http://www.htcmania.com/forumdisplay.php?f=153
Siento no poder darte más ayuda, pero al ser esto un hobby y no una profesión no puedo dedicarle más tiempo que el estrictamente necesario.
Un saludo
hola Juan seria de ayuda contactarme con voz es algo relacionado al proyecto que mensionaste que dejo mi correo jose_xp_799@hotmail.cm
No, si entiendo lo que decís, es logico, solo queria que supierais que mi intención no era robar vuestro tiempo, ni nada por el estilo, pido perdón si lo ha parecido y estoy muy agradecido por la ayuda prestada, voy a plantear mi duda ahora mismo en el foro Oscar a ver si alguien pudiera ayudarme con ella, repito, Muchas gracias de veras 🙂
Oye Una Pregunta de los modulos blue que venden aqui me servira lo puedes cheekear http://www.dynamoelectronics.com/images/stories/Bluetooth%20Shield.pdf
gracias necesito enviar un high al pin 12 de arduino
otra cosa copie el codigo que tienes y me aparece error que las librerias que estan en la cabecera no existen
¿has leido los comentarios donde otra gente ha tenido tus mismos problemas?
ya logre solucionar eso pero ahora le doy run al programa tuyo
y me sale un error en esta linea
socket = dispositivo.createRfcommSocketToServiceRecord(UUID.fromString(«00001101-0000-1000-8000-00805F9B34FB»));
a que se debe dice
[javac] Since compiler setting isn’t classic or modern, ignoring fork setting.
[javac] Since compiler setting isn’t classic or modern, ignoring fork setting.
[javac] Since compiler setting isn’t classic or modern, ignoring fork setting.
[javac] Compiling 3 source files to C:UsersusuarioAppDataLocalTempandroid3109560753686470828sketchbinclasses
[javac] Since compiler setting isn’t classic or modern, ignoring fork setting.
[javac] C:UsersusuarioAppDataLocalTempandroid3109560753686470828sketchsrcprocessingtestsketch_130202asketch_130202a.java:252: cannot find symbol
[javac] symbol : variable UUID
[javac] location: class processing.test.sketch_130202a.sketch_130202a
[javac] socket = dispositivo.createRfcommSocketToServiceRecord(UUID.fromString(«00001101-0000-1000-8000-00805F9B34FB»));
[javac] ^
[javac] Note: C:UsersusuarioAppDataLocalTempandroid3109560753686470828sketchsrcprocessingtestsketch_130202asketch_130202a.java uses unchecked or unsafe operations.
[javac] Note: Recompile with -Xlint:unchecked for details.
[javac] 1 error
BUILD FAILED
C:UsersusuarioDesktopadt-bundle-windows-x86_64sdktoolsantbuild.xml:710: The following error occurred while executing this line:
C:UsersusuarioDesktopadt-bundle-windows-x86_64sdktoolsantbuild.xml:723: Compile failed; see the compiler error output for details.
Esta relacion al conecta dispositivo El simbolo UUID no lo reconoce no se porque en ese caso que debo hacer?? gracias
En los comentarios está la respuesta.
Si ya solucione todo eso ahora conecto mi tablet samsumng galaxy note II y sale esto en el cuadro de run
debug:
Shutting down any existing adb server…
No se qué puede ser. ¿Y si lo lanzas sin debug?
Igual sin debug aparece eso y device no se conecta :s
Pero lo estás ejecutando en el samsumg o en el PC? Al tener librerías bluetooth sólo funciona en el samsumg directamente.
Hi
When running the whole program in processing i keep getting an error in line 227 (Incomptible types).
Does anyone recgionize this error and do you have any solutions for it.
When commenting this line out i can get the aplication to compile and run on my Nexus 7. It even sees the BT module i have on my embedded board.
Any help is greatly appreciated
Processing 2.0b7
With socket.connect(); ?
Sorry. I did not understand that.
The line contains socket.connect();?
void conectaDispositivo ( )
{
try
{
socket = // Method m = dispositivo.getClass().getMethod(«createRfcommSocket», new Class[] { int.class });
// socket = (BluetoothSocket) m.invoke(dispositivo, 1);
socket. connect ( ) ; // line 225
ins = socket. getInputStream ( ) ;
ons = socket. getOutputStream ( ) ;
the compiler reports «Incompatible Types» and halts in line 225
Pete
Hola buenos días me podrías compartir por favor este proyecto de ejemplo ya que con este código no e logrado compilarlo, ya que me saca error en varias clases que no esta en el código que publicaste, te lo agradecería enormemente, por que a partir de esto puedo seguir con mi proyecto.
gracias quedo atento
Muchas gracias por compartir esta informacion!
Hola buenas, antes de nada felicitarte por el pedazo de curro que has hecho.
Estoy intentando seguir tus pasos pero a la hora de compilar me da un error en la linea de codigo siguiente:
socket = dispositivo.createRfcommSocketToServiceRecord(UUID.fromString(«00001101-0000-1000-8000-00805F9B34FB»));
Y no me da mucha explicación, por lo que no puedo buscar por mi cuenta.
Tambien tengo que decir que estoy compilando el sketch en emulador y puede ser el motivo…pero no lo se.
Si me pudieses ayudar te lo estaría muy agradecido.
Saludos y otra vez felicidades.
Mil gracias
La respuesta está en los comentarios.
Ostras, lo siento me lo había saltado ese. Muchas gracias igualmente! 🙂
Brilliant job Oscar. But did you forget to import java.util.UUID?
Thank you
When I wrote the articles it was not necessary to import it, however now it is mandatory.
Buenas e nuevo….
Estoy intentando hacer algo similar pero con processing en el pc…. Y tengo una duda…
Cuando configuras el puerto serie en processing… Usando la siguiente linea.
myPort = new Serial(this, Serial.list()[0], 9600);
Donde [0] es el puerto que corresponde con la placa arduino ( ya sea usando el cable usb o un puerto serie bt….
Mi problema biene cuando cambio de puerto o uso otro adaptador serie, que el puerto cambia, por lo que hay que cambiar este numero con el que corresponda….
Para saber cual es basta con hacer un porlist…
println(Serial.list());
Pero …. Y aqui viene mi duda… Como se puede hacer, que el programa se detenga, nos muestre la lista de los puertos disponibles ,con un numero asignado a cada uno ( que ya es asi, el primero es el 0, luego el 1 y asi sucesivamente…). y espere a que seleccionemos uno de esos numeros para continuar la ejecucion del sketch usando ese numero de puerto ?
Perdon por la chapa….
Gracias por la ayuda!
Why does not work on android version 4.0.4?
Version 2.3.7 worked.
No idea. What kind of error do you have?
My bluetooth is not pairing with my device HC-05 module.
It says «paired but not connected»
When I run the program, the background is always the password when prompted in.
I in write, but does not connect to.
hola. por favor estoy intentando copilar pero el instante de cargar me sale cannot find symbol y mee subraya la linea de socket = dispositivo.createRfcommSocketToServiceRecord(UUID.fromString(«00001101-0000-1000-8000-00805F9B34FB»));
activo las otras dos pero por nuingun motivo funciona por favor si me podrias ayuda.gracias
La respuesta está en los comentarios.
Primero te agradesco Oscar. Quisiera saber en que linea puedo comenzar para crear una pantalla donde pueda ver una senal analogica ayudame por favor es para mi proyecto final de la universidad.gracias
hola Oscar buen dia amigo de verdad me interesa esto ya que estoy tratando de conectar una banda polar wearlink plus bluetooth, y de verdad soy algo nuevo por lo que seria de gran apoyo si me aconsejas ya que existe poco material acerca de esto por favor ayuda 🙁
porque me marca error en esa linea? xfa si puedes ayudame
socket = dispositivo.createRfcommSocketToServiceRecord(UUID.fromString(«00001101-0000-1000-8000-00805F9B34FB»));
La respuesta en los comentarios.
Buen dia Oscar sera que permitirias la aplicacion corriendo es que la necesito para entender mejor que hay cosas que no comprendo te dejo mi correo jose_xp_799@hotmail.com grax de ante mano 😀
tengo un problema con las bibliotecas , como las instalo para q processing las pueda utilizar,me pueden ayudar porfavor
En el artículo hay un enlace que explica cómo.
Hola Oscar.
Estamos desarrollando un dispositivo bluetooth y necesitamos programar una aplicación android para poder enlazar éste con el terminal y así poder interactuar con el teléfono. Si estás interesado en desarrollar la app como freelander o conoces a alguien que lo quiera hacer, por favor ponte en contacto con nosotros en iteeditorial@icloud.com o por teléfono 927 31 00 06. Gracias.
Juan Carlos Ramiro.
ITE editorial.
disculpa socio solo tengo una pregunta que hacerte el codigo final que a lo que entendi es la aplicacion para mi android como la instalo en mi dispositivo ?? saludos
Desde el propio Processing se sube la aplicación al dispositivo (este usa la SDK de Android).
gracias saludos
quisiera saber si tienes un ejemplo de una aplicacion en la cual se conecte con otro celular y puedes enviar datos como cadenas de caracteres o numeros…
llevo buscando mucho tiempo un ejemplo asi pero no lo encuentro.
o si me puedes decir como hacerlos.
Me temo que esto sólo es desde un módulo bluetooth serie a un móvil o tablet, no de móvil a móvil.
Logre reproducir esta aplicacion para mi arduino uno, gracias por publicarlo, solo un detalle curioso, cada vez que muevo de posicion mi telefono la aplicacion se cierra automaticamente, tuve que deshabilitar la funcion de rotacion de pantalla para lograr que la aplicacion no se cierre debido al movimiento del aparato.Que tendria que hacer para evitar que se cierre sin tener que deshabilitar la funcion mencionada?
Prueba a importar la librería android.content.pm.ActivityInfo y luego poner esto en la función setup:
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
Ahora estoy intentando leer una senal analoga (sensor temperatura) pero me encontre con dificultades.la senal enviada por el modulo bluetooth se recive como byte, asi que se necesitan hacer unas conversiones para convertir el inputstream a string.en void muestradatos() intente lo siguiente:
InputStream ins;
String valor;
ins = socket.getInputStream();
valor = str( ins.read() );
Puedo compilarlo sin ningun error pero al momento de abrir la aplicacion esta se cierra forzadamente. no tengo idea de que mas hacer
Pero ¿por qué pasarlo a cadena? La función text ya permite mostrar el número como una cadena a partir de un int o un byte.
Gracias por el consejo, mis conocimientos en Java son muy limitados, voy a investigar en la red como utilizar la funcion text para mostrar valores en cadena.
No solo pretendo recibir en Processing valores numericos, tambien pretendo enviar pequenos mensajes de texto, la funcion valor esta declarada como «byte» si quiero leer numeros mayores a 255 que es lo maximo que «cabe en un byte» o leer textos necesitaria leerla como un word o como un String es por eso que necesito saber como convertir el inpustream a string,
Puedes ir almacenando los bytes que recibes del inputstream en un arras y luego convertir este a string con Arrays.toString
Primero muchas gracias por tu aporte. He programado una aplicación de control de luces basado practicamente en tu proyecto, y ha funcionado varios meses bien, pero ahora, despues de cargar el programa de processing en el android y seleccionar el dispositivo bluetooth del arduino me sale siempre el mensaje «java.io.IOException: Unable to start Service Discovery», es decir ya no muestra el UI (los botones (rectangulos) de encendido y apagado de luces). Haciendo pruebas, la unica forma para que se muestre el UI es, en la funcion conectaDispositivo(), comentar la primera linea del try «socket = …» y descomentar las dos lineas siguientes (que estaban comentadas en tu proyecto) pero en este ultimo caso los botones no interactuan. Sabrias decirme primero porque ya no funciona con el socket que conecta con el servicio 00001101-0000-1000-8000-00805F9B34FB; y segundo, como puedo dar actividad a los botones utilizando el socket con el metodo estandar.
Muchas gracias de antemano.
Pues no sabría decirte. ¿Has cambiado el dispositivo bluetooth?. Si los botones no interactuan debe ser que no ha hecho una conexión correctamente, ¿has probado a enviar una cadena de caracteres (por ejemplo secuencia de apagados y encendidos de las luces) después de obtener el Outputstream para comprobar si al menos conecta bien y envía datos?
Prueba otra cosa, deja tu proyecto como estaba y antes del connect pon esta línea:
adaptador.cancelDiscovery();
Si cambie de bluetooth (utilizo JY-MCU Arduino Bluetooth) y tampoco funciona. Creo que todo esto empezo cuando instale en el portatil Toshiba (con el cual trabajo y conecto el arduino y el android) los nuevos drivers «Bluettoth Stack by Toshiba», y tal vez al compilar los programas (Processing y Arduino) tome otra información para el bluetooth?, aunque yo no utilizo el bluetooth del portatil, solo utilizo en la comunicacion los bluetooth del android y del arduino.
He creado otro programa y copie (exactamente) tu proyecto ejemplo de esta pagina (para el arduino y para el android) y he comprobado que solo recibo y envio caracteres utilizando el socket con el metodo estandar, por tanto el bluetooth del arduino esta bien (con el socket que conecta con el servicio 00001101-0000-1000-8000-00805F9B34FB me muestra el mensaje “java.io.IOException: Unable to start Service Discovery”). Ahora tengo que hacer funcionar mi proyecto (bastante mas largo tambien incluye comunicacion web) con el socket del metodo estándar y mi pregunta es si es necesario o no crear un thread como lo comentas (lo cual no sabria hacerlo) o si tendre problemas de funcionamiento.
Muchas gracias de antemano.
¿has probado lo que te comentaba del adaptador.cancelDiscovery()?
Si tambien coloque la linea adaptador.cancelDiscovery(); antes de la linea socket.connect(); y salia el mismo mensaje “java.io.IOException: Unable to start Service Discovery” despues de pulsar (elegir ) de la lista el dispositivo bluetooth del arduino.
Hola Ricardo, Óscar,
Lo primero, muchas gracias a Óscar por este post/tutorial tan útil y claro. Me acabo de descargar processing hace una hora y estoy alucinando con lo potente que es.
Hace unos días estuve escribiendo una aplicación similar directamente sobre Android y me llevó bastante más tiempo.
Respecto al socket, aparentemente en nuevas versiones de Android las cosas funcionan diferente y no es posible la conexión utilizando UUID. He leído bastantes posts sobre el tema en stackoverflow, y la conclusión es que hay que utlizar la opción propuesta más arriba:
Method m = dispositivo.getClass().getMethod(«createRfcommSocket», new Class[] {int.class});
socket = (BluetoothSocket) m.invoke(dispositivo, 1);
Con este cambio, y añadiendo los import necesarios, a mí me funciona perfecto. He subido el sketch con todos los cambios al proyecto de mi aplicación android por si alguien quiere descargárselo:
https://github.com/jmgjmg/SerialBluetooth/blob/master/BTSketchProcessing.pde
Gracias de nuevo por un artículo tan útil!
Gracias Javier por aportar luz al asunto. Hace tiempo que no uso processing para Android y por eso agradezco vuestros comentarios sobre los cambios que hay que hacer para que siga funcionando.
Hola Javier y Oscar, acabo de entrar de nuevo a este link (después de algunos meses) y me alegró la respuesta de Javier, porque haciendo pruebas había solucionado mi problema (hace unos meses) con la solución de Javier y me deja más tranquilo que es lo correcto.
Al hilo de esto, tengo otro problema y si alguno de ustedes sabe la solución les estaré muy agradecido. Mi proyecto Processing-Android funciona muy bien en un target API level 10 pero al instalarlo en un android 4.1.2 (API 16) o 4.2.2 (API 17), se conecta bien al Bluetooth del Arduino pero el teclado del android se bloquea (no permite introducir digitos, lo que en el API 10 funciona perfectamente), y tampoco funciona en un emulador en este caso sólo muestra el mensaje «BUSCANDO DISPOSITIVOS». He leido en la web que Processing sólo soporta el API level 10, y la solución que propone alguno es que se debería modificar los fuentes de Processing, y recompilarlo, etc. Mi pregunta es alguno de vosotros ha instalado un proyecto Processing-Android en un API level mayor a 10 y como lo ha hecho?
Muchas gracias de antemano.
Retomando lo del asunto de leer valores mayores de un byte: importe la libreria:
import processing.bluetooth.*;
Client c;
byte[] inbuffer = new byte[2]; // leyendo bytes y acomodarlos en un array
void muestraDatos() {
if (c.available() > 0) {
// Leer bytes
c.readBytes(inbuffer);
{
// Convertir el array de bytes a String
String myString = new String(inbuffer);
if (inbuffer !=null)
// Show it text area
println(myString);
}
}
}
El programa se compila sin ningun error, pero al momento de abrir la aplicacion esta es forzada a cerrarse… Si por favor alguien sabe como leer datos en forma de «String» o de guiarme con un ejemplo lo agradecere mucho se me acaba el ciclo escolar para fin de mes y mi proyecto final aun no tiene forma, gracias
Hola, primeramente excelente tu trabajo. Lo que queria preguntarte es como podria hacer para que en ves de ver numeros en la pantalla del celular pueda ver otra cosa una imagen con algun texto por darte un ejemplo vdd esque esto es justo lo que necesito para un proyecto, otra pregunta la señal que envias al celular podrias hacerlo ccon un pulsador?
Espero me puedas aclarar estas dudas gracias de antemano
Dado que se trata de Processing, puedes usar las funciones propias del entorno http://processing.org/reference/PImage.html. Con respecto a la señal mediante pulsador, ¿tiene experiencia en la electrónica? si es así sabrá que cuando se programa un microntrolador puede hacer tareas repetitivas o esperar a un evento (por ejemplo la pulsación de un botón) para hacer algo.
Hola de nuevo muchas gracias por responder, leere el articulo, y si se electronica un poco mas que basica jeje, en fin, lo que en realidad quiero hacer para ser mas espesifico jeje es una ratonera automatizada algo raro pero me anda valiendo un 10 en la uni y lo unico que quiero hacer o lo que se quiere lograr es que al momento de que se accione la ratonera esta me mande una señal (apachurre el pulsador) y eseta señal se mande al arduino, del arduino via bluetooth que me llege al celular android, en resumen es el monitoreo de la trampa. jeje espero no estresarte con esto, y una vez mas gracias por la info.
En principio no hay problema para hacer que arduino detecte el cierre de un pulsador, luego ese estado se envía al módulo bluetooth mediante el puerto serie y sería recibido por tu celular.
Talvez mi duda será tonta…
Pero no puedo importar la librería import java.util.UUID…
no se como hacerlo… soy super nuevo en esto..
en el menú me voy a Sketch, luego Add Library, Add Library… y luego en All busco java.util.UUID y no encuentro nada… no se si asi es la forma..
Esta instalado el Android SDK Manager y tengo agregado donde dice Android Support Library…
o en donde es…
Les agradecería que me explicaran..
La solución está en los comentarios.
Te agradezco…
Pero como te mencione soy totalmente nuevo en esto y estoy tirando a grandes ligas con lo que tu sabes…
Disculpa mi ignorancia…
pero no encuentro por donde ingresarle la librería y si es por donde digo no la encuentro a la hora de la búsqueda…
Entonces me gustaría saber si me podes asesorar que hacer… gracias…
Lo primero es que que sólo tienes que poner esa línea al principio del código, no hace falta añadir ninguna librería. Lo segundo es saber si estás en modo android en el entorno de processing.
Gracias… muchas gracias….
Definitivamente mi ignorancia era grande… gracias…
Otra consulta que tengo es que tengo es que no logro emular o compilar la aplicación en modo android ya que siempre me da el error
Lost Connection with device while launching. Try again.
Desde una aplicación sencilla hasta la que esta aquí.
Tendras idea de que sea… (solo en modo android me da, ahora en java si funciona)
Hola amigo muchas gracias por tu informacion funciona correctamente, quisiera realizar una pregunta sencilla soy novato en esto de processing, asi que veo que la instruccion TRY este ejecuta el proceso indefinidamente (loop) pero requiero que solamente me envie un dato una UNICA vez.
ejemplo
try
{
ons.write(‘A’) esta enviando AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
}
PERO REQUIERO
ons.write(‘A’) que envie A
Agradeceria que me pudieran dar alguna idea de como solucionar
Gracias 🙂
EL ons.write en el código del artículo sólo se envía cuando se pulsa una zona de la pantalla que hace de botón (función compruebaBoton), no continuamente.