Bluetooth HC-05 comunicación half duplex, Pic C Compiler

En esta sección aprenderÔs a establecer una comunicación inalÔmbrica en modo half duplex utilizando dos módulos Bluetooth para enviar y recibir datos. El objetivo es establecer la comunicación inalÔmbrica entre un PIC Maestro y un PIC Esclavo para enviar comandos o instrucciones para recibir la lectura del valor de un potenciometro o un botón.

Bluetooth HC-05Ā 

El Bluetooth HC-05 es un módulo de comunicación inalÔmbrico que utiliza la tecnología Bluetooth para establecer un enlace de comunicación serie entre dos dispositivos. Es un dispositivo muy popular en proyectos de electrónica y robótica, ya que permite la comunicación inalÔmbrica entre un microcontrolador, como Arduino, y otros dispositivos como un ordenador, smartphone o tablet. El HC-05 puede funcionar como maestro o esclavo y utiliza el perfil serial port profile (SPP) de Bluetooth, lo que lo hace compatible con una amplia variedad de dispositivos que soportan este perfil.

CaracterĆ­sticas:

  • TecnologĆ­a: Bluetooth 2.0 + EDR (Enhanced Data Rate)
  • Alcance de comunicación: hasta 10 metros (en condiciones ideales)
  • Velocidad de transmisión: 2.1 Mbps mĆ”x. en modo EDR, 721 kbps mĆ”x. en modo estĆ”ndar
  • Frecuencia: 2.4 GHz a 2.4835 GHz banda ISM
  • Potencia de transmisión: Clase 2, hasta 4 dBm (2.5 mW)
  • Sensibilidad de recepción: -80 dBm tĆ­pico
  • Protocolos de soporte: Bluetooth serial port profile (SPP)
  • Modo de operación: Maestro o Esclavo
  • Compatibilidad: Compatible con dispositivos que soportan Bluetooth SPP
  • Interfaz: UART (Universal Asynchronous Receiver/Transmitter)
  • Voltaje de alimentación: 3.3V a 5V DC
  • Consumo de energĆ­a: 30 mA en modo de operación, 1 mA en modo de espera
  • Dimensiones: 28 mm x 15 mm x 2.35 mm

Circuito de conexión

Configuración

Inicialmente se deben configurar los módulos Bluetooth en modo maestro y esclavo para poder transmitir los datos mediante una comunicación inalÔmbrica.

Programación PIC Maestro

Inicialmente se establecen los parÔmetros de la comunicación RS232.

  • baud = Velocidad de transmisión y recepción configurada en el módulo Bluetooth.
  • stop = Bits de parada.
  • parity = Bit de paridad.Ā 
  • xmit = Pin de transmisión.
  • rcv = Pin de recepción.Ā 
  • bits = Datos de transmisión.
  • stream = identificación de transmisión.

#use rs232(baud=38400, stop=1, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8)

Inicialmente esperamos a que los módulos bluetooth se vinculen. El pin STATE del módulo genera una señal digital de «1» cuando el módulo bluetooth esta vinculado y «0» cuando no esta vinculado.


#define  state input(pin_d0)

void main()
{  
 
   while (!state)//espera la conexion con el esclavo;
   {}
   .
   .
   .

Una vez que se vinculen los módulos Bluetooth, se envían los comandos por el puerto RS232 para solicitar un valor al PIC esclavo.


      printf("PAN0\r");
      recibe();
      PAN0 = (int16)atol(recibido);  //convierte la cadena en un numero de 16bits

La función «printf» envía un comando por el puerto RS232 para ser enviado por el módulo Bluetooth al PIC esclavo.


      printf("PAN0\r");

Para recibir el valor correspondiente al comando se utiliza la sub-rutina «recibe()» donde el valor recibido se guarda en la variable «recibido[]».

En la sub-rutina también se verifica la conexión de los módulos Bluetooth, si se llega a perder la conexión, el programa retorna a la función «main()».


void recibe()
{
   memset(recibido, 0, sizeof(recibido)); //limpia los registros de la varible
   int8 i=0;
   while(true)
   {
      if (kbhit())//espera el primer caracter
      {        
         while(true)
         {
            recibido[i]=getc();//RECIBE EL CARACTER

            if(recibido[i]=='\r')//busca el salto de linea \r
            {
               recibido[i]='\0';//fin de la cadena = caracter nulo \0
               return;
            }
            
            i++;
            
            if (!state)//verifica la conexion;
            {
               return;
            }
            
         }
      }
      
      if(!state)//verifica la conexion;
      {
         return;
      }
      
   }
}

Se convierte la cadena caracteres que contiene el valor recibido de la variable «recibido[]» en un valor «int16» y se guarda el valor en una variable «int16» asignada.


 PAN0 = (int16)atol(recibido);  //convierte la cadena en un numero de 16bits

Finalmente se muestra el valor correspondiente en el diplay OLED.


void mostrar()
{
   char texto[20];

   sprintf(texto,"PAN0=%04lu",PAN0);
   OLED_DrawText(1,1,texto,1);

   sprintf(texto,"PRD0=%u",PRD0);
   OLED_DrawText(1,10,texto,1);

   OLED_Display();//Muestra la información en pantalla;
}

Código completo PIC Maestro


#include "stdlib.h"

#FUSES NOMCLR

#use i2c(Master,Fast, sda=PIN_B0, scl=PIN_B1, force_sw, stream=OLED_stream)//parametros I2C
#use rs232(baud=38400, stop=1, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8)

#define SH1106_128_64 //DEFINE EL MODELO DE LA PANTALLA OLED
//#define SSD1306_128_64

#include "OLED_I2C.c" //libreria oled I2C

#define  state input(pin_d0)

char recibido[20];

int16 PAN0=0;
int1 PRD0=0;

void recibe()
{
   memset(recibido, 0, sizeof(recibido)); //limpia los registros de la varible
   int8 i=0;
   while(true)
   {
      if (kbhit())//espera el primer caracter
      {        
         while(true)
         {
            recibido[i]=getc();//RECIBE EL CARACTER

            if(recibido[i]=='\r')//busca el salto de linea \r
            {
               recibido[i]='\0';//fin de la cadena = caracter nulo \0
               return;
            }
            
            i++;
            
            if (!state)//verifica la conexion;
            {
               return;
            }
            
         }
      }
      
      if(!state)//verifica la conexion;
      {
         return;
      }
      
   }
}


void mostrar()
{
   char texto[20];

   sprintf(texto,"PAN0=%04lu",PAN0);
   OLED_DrawText(1,1,texto,1);

   sprintf(texto,"PRD0=%u",PRD0);
   OLED_DrawText(1,10,texto,1);

   OLED_Display();//Muestra la información en pantalla;
}


void main()
{

   OLED_Begin();
   OLED_ClearDisplay();

   mostrar();
   
   while (!state)//espera la conexion con el esclavo;
   {}
   
   while(TRUE)
   {

      printf("PAN0\r");
      recibe();
      PAN0 = (int16)atol(recibido);  //convierte la cadena en un numero de 16bits

      printf("PRD0\r");
      recibe();
      PRD0 = (int1)atoi(recibido);  //convierte la cadena en un numero de 8bits

      mostrar();
            
   }
   
}

Programación PIC Esclavo

Inicialmente se establecen los parÔmetros de la comunicación RS232.

  • baud = Velocidad de transmisión y recepción configurada en el módulo Bluetooth.
  • stop = Bits de parada.
  • parity = Bit de paridad.Ā 
  • xmit = Pin de transmisión.
  • rcv = Pin de recepción.Ā 
  • bits = Datos de transmisión.
  • stream = identificación de transmisión.

#use rs232(baud=38400, stop=1, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8)

Se habilita la conversión analógica a digital para los pines analógicos.


   setup_adc(ADC_CLOCK_INTERNAL);

Se hace la lectura del pin analógico «AN0» conectado el potenciometro y se guarda el valor en la variable correspondiente.


 set_adc_channel (0); //Habilita el canal AN0
 delay_us(10);
 val_PAN0 = read_adc(); //lectura del potenciometro

Se hace la lectura digital del pin conectado al botón y se guarda el valor en la variable correspondiente.


 val_PRD0 = input(pin_d0); // lectura del boton

Se habilitan las interrupciones para la recepción de datos por el puerto RS232.


   enable_interrupts(int_rda);
   enable_interrupts(global);

Cuando se habilita la interrupción, el programa se aloja en la sub-rutina «rda_isr()» para recibir el comando y guardarlo en la variable «recibido[]»


#int_rda
void rda_isr()
{
   memset(recibido, 0, sizeof(recibido)); //limpia los registros de la varible
   int8 i=0;
   while(true)
   {
      recibido[i]=getc();//RECIBE EL CARACTER

      if(recibido[i]=='\r')//busca el salto de linea \r
      {
         recibido[i]='\0';//fin de la cadena = caracter nulo \0
         enviar();
         return;
      }
      i++;
   }
}

En la sub-rutina «enviar()», se identifica el comando y se envía el valor correspondiente al comando.


void enviar()
{
   signed int8 result;
   
   int8 PAN0[10] = "PAN0";
   int8 PRD0[10] = "PRD0";

      result = strcmp(recibido, PAN0);
   
      if (result==0)
      {
         printf("%04lu\r",val_PAN0);//envia el valor del pin AN0
         return;
      }     
   
      result = strcmp(recibido, PRD0);
   
      if (result==0)
      {
         printf("%u\r",val_PRD0);//envia el valor del pin RD0
         return;
      }
      
}

La instrucción «strcmp()» compara dos cadenas de caracteres, se compara la variable «recibido» que contiene el comando recibido y la variable «PAN0» que contiene el comando «PAN0», si las dos cadenas de caracteres resultan iguales se envía el valor correspondiente en la sentencia «if » por el puerto RS232 al PIC maestro, si son diferentes, el programa pasara a la siguiente comparación para encontrar el comando correspondiente al valor que se enviara al PIC maestro.


   int8 PAN0[10] = "PAN0";

 result = strcmp(recibido, PAN0);
   
      if (result==0)
      {
         printf("%04lu\r",val_PAN0);//envia el valor del pin AN0
         return;
      }     

Después de enviar el valor correspondiente al comando recibido, se retorna a la función «main()» para hacer las lecturas de los pines y esperar una nueva interrupción para recibir un nuevo comando del PIC maestro.

Código completo PIC Esclavo


#include "stdlib.h"

#FUSES NOMCLR

#use rs232(baud=38400, stop=1, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8)

char recibido[20];

int16 val_PAN0=0;
int1 val_PRD0=0;

void enviar();

#int_rda
void rda_isr()
{
   memset(recibido, 0, sizeof(recibido)); //limpia los registros de la varible
   int8 i=0;
   while(true)
   {
      recibido[i]=getc();//RECIBE EL CARACTER

      if(recibido[i]=='\r')//busca el salto de linea \r
      {
         recibido[i]='\0';//fin de la cadena = caracter nulo \0
         enviar();
         return;
      }
      i++;
   }
}


void enviar()
{
   signed int8 result;
   
   int8 PAN0[10] = "PAN0";
   int8 PRD0[10] = "PRD0";

      result = strcmp(recibido, PAN0);//compara, si son iguales (0), no (+-1)
   
      if (result==0)
      {
         printf("%04lu\r",val_PAN0);//envia el valor del pin AN0
         return;
      }     
   
      result = strcmp(recibido, PRD0);
   
      if (result==0)
      {
         printf("%u\r",val_PRD0);//envia el valor del pin RD0
         return;
      }
      
}

void main()
{

   enable_interrupts(int_rda);
   enable_interrupts(global);

   setup_adc(ADC_CLOCK_INTERNAL);
   
   while(TRUE)
   {   
       set_adc_channel (0); //Habilita el canal AN0
       delay_us(10);
       val_PAN0 = read_adc(); //lectura del potenciometro

       val_PRD0 = input(pin_d0); // lectura del boton
   }
}
PCBWay2
Scroll al inicio