jueves, 3 de octubre de 2019

Bluetooth con Arduino

El caso es que tengo esto medio abandonado...
Bueno, pues vamos a revivirlo un poco. El otro día me aburría y me acorde que en su día (hace ya años), me compre un modulo bluetooth para el arduino, y se me ocurrió ponerme a juguetear con el. Hasta ahí todo normal, supongo. El caso es que lo que voy a contar ahora aquí, sera fácil de encontrar por cualquier sitio de internet, pero bueno, por si acaso alguien acaba en esta pagina, pues espero que a alguien le sea útil.

Así que lo primero que hice fue ponerme a investigar a ver que es lo que tenia entre manos, y resulto que lo que yo tenia en mi poder era el modulo bluetooth HC-06. Hay 2 módulos bluetooth para arduino: el HC-05 y el HC-06. La diferencia entre ambos es que el HC-05 puede funcionar tanto en modo maestro como en modo esclavo, mientras que el HC-06 funciona solo en modo esclavo. El caso es que el precio es muy similar y entonces os preguntareis: "¿pero por que no has comprado entonces el HC-05, si es mejor?". Pues muy fácil, porque no tenia ni idea de lo que estaba haciendo!

Haz click por aqui para seguir leyendo:




Adjunto fotos de ambos módulos bluetooth:
HC-05:

HC-06:

Como podéis observar, son prácticamente iguales, salvo por un botón que tiene el HC-05 para cambiar de modo y otros 2 pines que también tiene el HC-05. Es mas, me atrevería a decir que lo que es la placa es exactamente la misma en ambos casos...

Bueno, sigamos. En este tutorial me dedicare exclusivamente al manejo del HC-06, ya que es el modulo bluetooth que tengo yo. También vale para el HC-05 configurado en modo esclavo. En el caso de que algún día me compre un HC-05, haré un tutorial para el.

NOTA IMPORTANTE: 2 módulos bluetooth configurados en modo esclavo (como por ejemplo 2 HC-06), NO PUEDEN COMUNICARSE ENTRE SI. Siempre hace falta un maestro. Puede haber varios esclavos, pero es necesario un maestro. En el caso de este tutorial (o lo que sea esto), el maestro sera el arduino, el ordenador, el móvil... pero no el modulo bluetooth.

Pues eso, lo primero que hice fue rebuscar un poco por internet a ver como funcionaba. si nos fijamos en los pines, vemos claramente que hay 4 pines en el modulo HC-06: VCC, GND, RXD, TXD. Esto va a ser importante:
-VCC: Pin de alimentación (Vcc), Funciona a 5V. Se puede conectar perfectamente al pin de 5V de nuestro arduino.
-GND: Pin de tierra. Se puede conectar perfectamente al pin de GND de nuestro arduino.
-RXD: Pin de comunicación por donde se reciben los datos. Se conectara al pin Rx del dispositivo con el que nos queramos comunicar (en nuestro caso, arduino).
-TXD: Pin de comunicación por donde se envían los datos. Se conectara al pin Tx del dispositivo con el que nos queramos comunicar (en nuestro caso, arduino).

*NOTA IMPORTANTE: Si alguno lo conecta a una fuente de alimentación externa y conecta los pines de comunicación a los pines del arduino (hay gente muy rarita por ahi y va a lo complicado), es posible que haya errores en la comunicacion. Para evitarlo, es IMPRESCINDIBLE que unáis la tierra de la fuente de alimentación con algún pin de tierra del arduino. Si no, va a dar errores en la comunicación (es posible que no los de, pero es muy muy probable que no se comunique, ya que las señales que se mandan por Rx y Tx son con respecto a GND, y como no haya una GND común, pues es posible que haya que este varios voltios por encima de la otra).

Pues sigo por donde iba, una vez averiguado lo evidente, lo siguiente que hice fue buscar un programa en internet y luego conectarme al modulo bluetooth. Así de fácil, no es broma, funciono a la primera y todo eso. Pero eso fue porque no fui capaz de seguir los pasos correctos, así que hoy voy a ir poco a poco y pondré primero lo que hice al día siguiente tranquilamente, que fue entrar en el modo de configuración del bluetooth, que al final fue muy sencillo.

Aquí os dejo el código que utilice yo. Al final de todo os pondré el código para que lo descarguéis. Es muy fácil de usar este programa. Lo único que hay que tener en cuenta es que hay que enchufar el arduino al ordenador (evidentemente), hay que tener en cuenta que la configuración predeterminada del modulo bluetooth es de 9600 baudios (unidades de información por segundo) y sin ajuste de linea, y en este caso, hay que enchufar el pin Rx del modulo bluetooth al pin 11 del arduino, y el pin Tx del modulo bluetooth al pin Tx del arduino. O sea, Rx de un lado con Tx del otro. Y ya esta, a partir de ahí es escribir los comandos en la consola del arduino. Os dejo los comandos dentro del propio código del programa:

/*
Bluetooth HC-06, El mio con versión 1.8

Para configurar. Monitor serie a 9600 baudios y sin ajuste de linea


LISTA COMANDOS - versión linvorV1.8 :

AT                                <-- Prueba comunicación comandos AT
AT+NAMEMarcos      <-- Cambia el nombre, en este caso Marcos
AT+PIN1234               <-- Modifica pin de emparejamiento en este caso 1234
AT+BAUD4                <-- Selecciona los baudios, en este caso el 4 que es 9600

Las velocidades para el baudRate (baudios) son:

1 configura        1200bps
2 configura        2400bps
3 configura        4800bps
4 configura        9600bps (Default)
5 configura        19200bps
6 configura        38400bps
7 configura        57600bps
8 configura        115200bps


LISTA COMANDOS - versión VERSION:3.0-20170609

AT                                 <-- Prueba comunicación comandos AT
AT+NAME:Marcos      <-- Cambia el nombre, en este caso Marcos,responde
AT+PSWD:"1234"       <-- Modifica pin de emparejamiento en este caso 1234
AT+UART:9600,0,0     <-- Selecciona los baudios, en este caso el 4 que es 9600


*/


#include <SoftwareSerial.h>   // Incluimos la librería  SoftwareSerial
SoftwareSerial BT(10,11);    // Definimos los pines RX y TX del Arduino conectados al Bluetooth

void setup()
{
  BT.begin(9600);       // Inicializamos el puerto serie BT que hemos creado
  Serial.begin(9600);   // Inicializamos  el puerto serie
}

void loop()
{
  if(BT.available())    // Si llega un dato por el puerto BT se envía al monitor serial
  {
    Serial.write(BT.read());
  }

  if(Serial.available())  // Si llega un dato por el monitor serial se envía al puerto BT
  {
     BT.write(Serial.read());
  }
}

Si os fijáis, el código es muy muy simple. En resumen, lo que hace este programa es, recibir por un lado lo que se envía desde el ordenador, y luego se envía por el puerto que va al bluetooth, y lo que le llega del bluetooth, se envía al ordenador. Literalmente, no hace nada mas.

A partir de aquí, la cosa se complica ligeramente. El siguiente programa es bastante mas complejo, y a mi me llevo HORAS entenderlo. No es broma, hay una linea con la que estuve horas.

Este programa, lo que hace es hacer parpadear el LED interno que tiene el arduino, la cantidad de veces que le mandes. Dicho así es bastante simple. En mi caso, lo vincule con el móvil y utilice la app llamada "BTduino2". Es sencilla de usar, vas al terminal, escribes lo que quieras enviar, y envías.

En este caso, al contrario que el anterior, los pines de comunicación que se conectan al bluetooth son los pines 0 y 1 (Rx y Tx).

*NOTA IMPORTANTE: como los pines que se conectan al bluetooth son los pines Tx y Rx por defecto del propio arduino, a la hora de cargar el programa, es imprescindible desconectar estos 2 pines. De lo contrario os dará error (podéis probar si queréis).

Os voy explicando el código comentándolo en la misma linea:

const int led = 13;  //entiendo que a estas alturas todos sabéis que el led interno del arduino esta                                           vinculado al pin 13

int option; //creamos una variable, luego veréis en donde se usa

void setup(){
  Serial.begin(9600); //pues eso, usamos el puerto serie del arduino, a 9600 baudios
  pinMode(led, OUTPUT);  //el pin del led se pone de salida
}

void loop(){               //comenzamos el programa
  //si existe información pendiente
  if (Serial.available()>0){
    //leemos la opción
    //recibimos el dato como un caracter. IMPORTANTISIMO que lo recibimos como un CARACTER
    char option = Serial.read(); //Leemos el numero enviado como si fuese TEXTO
    //si la opcion esta entre '1' y '9'
    if (option >= '1' && option <= '9') //Aparece entre comillas porque lo reconoce como TEXTO
    {
      //restamos el valor '0' para obtener el numero enviado
      //explicación: en la tabla ASCII, el 0 tiene la posición 48
      //option -= '0'; //ESTA ES LA MALDITA LINEA CON LA QUE ESTUVE HORAS.
      //En resumen, aquí lo que se hace es tomar la tabla ASCII, donde el 0 tiene la posición 48, y                //restarle el valor en texto 0, o lo que es lo mismo, 48 en ASCII.
   
      //Aqui he modificado el código para entenderlo yo mejor. Antes ponía option -= '0';
      option -= 48; //en C es lo mismo que option=option-48
      for(int i=0;i<option;i++){ //Y aquí encendemos y apagamos el led las veces que hemos querido
         digitalWrite(led, HIGH);
         delay(100);
         digitalWrite(led, LOW);
         delay(200);
      }
      Serial.write("Prueba"); //Esto es un punto de control mio, para saber que hemos llegado a este punto, y se envía al móvil. Debería aparecer por el terminal.
    }
  }
}


Y básicamente hasta ahí. No tiene mas. Ahora os dejo un enlace de descarga para que os descarguéis estos dos programillas. Si tenéis cualquier tipo de duda, decidmelo en los comentarios y os lo resolveré (o lo intentare). Un saludo!!

Enlace de descarga:
https://drive.google.com/drive/folders/11aQaSIDUxJrMu1DZHVxEZLbatlBuFHhA?usp=sharing

9 comentarios:

  1. Hola viejo amigo,

    Muy buen post. Está realmente interesante. Además tenía curiosidad en saber un poco del módulo BT. Así que me tendré que hacer con uno y probarlo en casa.
    Lo de la tabla ASCII: Un horror mental.

    Salu2,
    David.

    ResponderEliminar
    Respuestas
    1. "viejo amigo"? nos conocemos o es una forma de saludar sin mas? XD

      Eliminar
    2. Hola de nuevo. Claro que nos conocemos. Soy david el que se paso de industriales a electronica. Recuerdas? jajaja

      Eliminar
    3. Pues si que recuerdo... aun te debo una hamburguesa jaja

      Eliminar
  2. char option = Serial.read(); //Leemos el numero enviado como si fuese TEXTO
    //si la opcion esta entre '1' y '9'
    if (option >= '1' && option <= '9') //Aparece entre comillas porque lo reconoce como TEXTO
    {

    cómo puede detectar que un char con contenido '2' es menor que '3'. Es por la tabla ASCII, no?
    '0'=48
    '1'=49
    por ejemplo... 'Hola' solo lo interpreta como 'H' en la tabla ascii, que por ejemplo correponde con 'H'=17 (POR EJEMPLO).

    Funciona así, nooooooo?????????????

    ResponderEliminar
    Respuestas
    1. Entonces 'Hola' es < que '9';

      y el if podria ponerse, sabiendo que:
      '1'=49
      '9'=57
      como...
      if (option >= 49 && option <= 57){}

      NOOOOOOOOOOOOOOOO?

      Eliminar
    2. No tengo muy controlado el tema de la tabla ASCII, la verdad. Seguro que hay opciones de convertir determinados caracteres a numeros, y luego, a partir de ahi, trabajar con numeros seria lo ideal y lo mas facil.

      En el caso de este programa, respondiendo a tu pregunta, el 2 es menor que el 3, y en el programa se sabria porque siguiendo el orden de la tabla ascii, el 2 corresponde al numero 50 (00110010) de la tabla, y el 3 al 51 (00110011). Todos los numeros del 0 al 9 estan en orden en la tabla. Tambien es importante encontrar la tabla adecuada, que en cada una que ves por internet el 0 corresponde a una posicion distinta.

      Eliminar
    3. En cuanto al tema que me preguntas del 'Hola', no te se responder. No se que ocurriria exactamente en ese caso, seguramente, como dices, coja solo el primer caracter, pero tambien podria ser que te ponga todos los 0 y 1 correspondientes del ascii seguidos, o te coja solo el ultimo caracter, o a saber. Si tengo luego un rato, te lo miro, que me has dejado con curiosidad jaja
      Pero en caso de que tengas razon, si la H correspondiese con el numero 17 de la tabla (POR EJEMPLO), y 'Hola' fuese igual a 17, se cumpliria la condicion de que 'Hola' es menor que '9'.

      Eliminar
    4. Y en cuanto a lo ultimo que me preguntas, lo del if, como bien dices, se podria poner tanto el valor en caracter como el valor en numero. O sea, que hay dos formas de escribir exactamente lo mismo:
      if (option >= 49 && option <= 57)
      if (option >= '1' && option <= '9')
      ambas lineas son exactamente lo mismo.

      Un saludo y gracias por tus preguntas! :)

      Eliminar