sexta-feira, abril 25, 2014

Comunicação Bluetooth entre Arduino e Android - Configuração do módulo BT.

Embora você possa usar o módulo Bluetooth com a configuração de fábrica, você provavelmente vai querer alterar os parâmetros de conexão. Neste post veremos como fazer isto.


Novamente esbarramos na escassez de documentação. O arquivo BT_HC06.pdf (que você encontra nos arquivos do blog) contem algumas informações úteis, apesar de não se referir especificamente ao módulo que estou usando.

A configuração é feita através de "comandos AT" enviados pela interface serial. Os comandos AT foram criados pela Hayes em 1981 e vem sendo sistematicamente abusados desde então. O módulo BT aceita apenas quatro comandos, e de forma totalmente rudimentar. Os comandos devem obrigatoriamente ser enviados em maiúscula e em caso de erro são silenciosamente ignorados. O módulo aceita os comandos AT somente quando não está conectado a um mestre através do rádio.

A determinação do início e do fim do comando é feito por tempo, seguindo as recomendações cifradas do documento adotei uma pausa de 1 segundo antes do primeiro caracter e uma pausa de 1 segundo após o último. O final da resposta (em caso de sucesso) também precisa ser determinado por tempo.

O primeiro comando consiste simplesmente de "AT" (sem as aspas); a resposta para este comando é "OK" (também sem aspas). Este comando é útil para confirmar que o módulo está entendendo os comandos que estamos enviando.

O segundo comando é "AT+BAUDn", onde n é um dígito de 1 a 9 ou uma das letras A, B e C. Este comando determina a velocidade da comunicação serial do módulo (no caso, o Arduino). Já deu para perceber a pegadinha? Para configurar uma nova velocidade você precisa saber qual a velocidade atual. O documento tem a tabela das velocidades (1=1200, 2=2400, 3=4800, 4=9600, etc). Eu tenho usado a velocidade de 9600, que é a padrão de fábrica. A resposta ao comando é "OKnnnnn", ainda na velocidade antiga (nnnn é 1200, 4800, 9600, etc).

O próximo comando é "AT+NAMExxxxx". Este comando altera o "Bluetooth name", que é uma das identificações que o Android vai receber quando procurar dispositivos BT para se conectar (para o caso de você estar curioso, a outra identificação é o endereço MAC do módulo). Este nome pode ter até 20 caracteres. A resposta a este comando é "OKsetname".

Por último temos "AT+PINnnnn", que define a senha (ou PIN) que deve ser fornecida para "parear" o módulo com um mestre (veremos mais sobre isto em um post futuro, quando falarmos no processo de conexão no lado do Android). A senha (nnnn) são sempre quatro dígitos (ou seja, de 0000 a 9999). A resposta ao comando é "OKsetPIN".

Com estas informações, podemos fazer um pequeno programa que programa o módulo para velocidade de 9600, nome DQSOFT e senha 4321..
// Configura o módulo Bluetooth

#include <SoftwareSerial.h>

// Módulo ligado aos pinos 10 (TXD) e 11 (RXD)
SoftwareSerial BTSerial(10, 11);

// Iniciação
void setup ()
{
  char resp[40];
  
  // Serial ligada ao PC
  Serial.begin(19200);
  
  // Espera digitar algo no PC
  while (Serial.available() == 0)
    ;
  Serial.read();
  
  // Procura a velocidade atual
  unsigned int baud[] = { 2400, 4800, 9600, 19200, 38400, 57600 };
  for (int i = 0; i < 6; i++)
  {
    Serial.print ("Tentando ");
    Serial.print (baud[i]);
    Serial.print ("bps\r\n");
    BTSerial.begin(baud[i]);
    enviaCmd ("AT");
    leResp (resp, sizeof(resp));
    if (strcmp ((const char *)resp, "OK") == 0)
    {
      Serial.print ("Achou\r\n");
      // Programa 9600
      enviaCmd ("AT+BAUD4");
      leResp (resp, sizeof(resp));
      Serial.print (resp);
      Serial.print ("\r\n");
      BTSerial.end();
      break;
    }
    BTSerial.end();    
    delay(500);
  }

  // Configurar os demais parametros  
  BTSerial.begin(9600);
  enviaCmd ("AT");
  leResp (resp, sizeof(resp));
  if (strcmp ((const char *)resp, "OK") == 0)
  {
    enviaCmd ("AT+NAMEDQSOFT");
    leResp (resp, sizeof(resp));
    Serial.print (resp);
    Serial.print ("\r\n");
    enviaCmd ("AT+PIN4321");
    leResp (resp, sizeof(resp));
    Serial.print (resp);
    Serial.print ("\r\n");
  }
}

// Programa principal, não faz nada
void loop ()
{
}

// Rotina para enviar um comando AT
void enviaCmd (char *cmd)
{
  unsigned long to;
  char c;
  
  delay(1000);
  while (*cmd != 0)
  {
    BTSerial.write (*cmd++);
  }
  delay(1000);
}

// Rotina para ler a resposta do módulo
int leResp (char *buf, int tam)
{
  int n = 0;
  int cont = 0;
  int c;
  unsigned long to = millis() + 500;  // timeout inicial
  while (n < (tam-1))
  {
    if (BTSerial.available() > 0)
    {
      c = BTSerial.read();
      cont++;
      if (cont > 100)
        break;  // provavelmente recebendo continuamente lixo
      if ((c > 0x1F) && (c < 0x7F))
        buf[n++] = (c > 0x5F) ? c - 0x20 : c;
      to = millis() + 200;  // rearma o timeout
    }
    if (millis() >= to)
    {
      break;  // timeout
    }
  }
  buf [n] = 0;
  return n;
}
No próximo post vamos começar a ver o lado do Android.

5 comentários:

Bruno Aguiar disse...

Amigo esse código funcionou para você? Não esta dando certo para mim

Daniel Quadros disse...

Funcionou sim. Confira se você ligou corretamente o módulo ao Arduino, conforme descrito no post anterior.

Bruno Aguiar disse...

Daniel, poderia comentar o que significa cada linha dessa parte do código:

void enviaCmd (char *cmd)
{
unsigned long to;
char c;

delay(1000);
while (*cmd != 0)
{
BTSerial.write (*cmd++);
}
delay(1000);
}

Desde já, agradeço

Daniel Quadros disse...

Bruno, não tem nada de especial nesta parte (fora a declaração desnecessária de to, que deve ter sobrado de alguma edição). A rotina recebe o ponteiro para um comando (cmd), que é uma sequência de caracteres encerrada por 0 (como é costume em C). Dá uma pausa de 1 segundo, que é a forma de indicar para o módulo o início do comando. Em seguida são enviados ao módulo os caracteres do comando. Por último, uma nova pausa de 1 segundo para indicar o fim do comando.

Bruno Aguiar disse...

Certo. Obrigado.