Como selecionar os dados recebidos como resposta de comandos AT do módulo BLE HM

Olá, atualmente estou desenvolvendo um detector de beacons e estou utilizando um arduino nano, um módulo ble HM-10 e um ESP-01 (modulo wifi). O HM-10 funciona através de comandos AT e por isso utilizo o arduino nano para fazer o envio do comando que procura por beacons de forma automática. Quando é enviado via serial o comando “AT+DISI?” para o modulo HM-10 ele retorna o seguinte resultado: OK+DISIS OK+DISC:4C000215:003E8C80EA014EBBB88878DA19DF9E5A:00000000C8:F248E589DDC3:-065 OK+DISCE

Eu gostaria de enviar para o módulo wifi ESP-01 somente os dois ultimos parametros: “F248E589DDC3:-065” que são o endereço MAC e o RSSI do beacon. Lembrando que para um beacon diferente o valor de MAC é diferente e o RSSI varia de acordo com a distancia da detecção do sinal. No codigo que utilizo ele ja faz o envio do comando AT+DISI? de forma automatica e retorna o resultado independente da quantidade de beacons ativo, porém gostaria de enviar para o modulo wifi somente o endereço mac e o rssi dos beacons.

Código utilizado:

#include <SoftwareSerial.h>

SoftwareSerial bluetooth(8, 9);

int cnt = 0;
int started = 0;
int index = 0;
const char endTag[] = "DISCE";

void setup() {
  bluetooth.begin(9600);
  Serial.begin(9600);

}

void loop() {
  if (started == 0)
  {
    bluetooth.print("AT+DISI?");
    started = 1;
  }

  if (started ==1 && bluetooth.available())
  {
    char charIn = bluetooth.read();

    Serial.print(charIn);


    // look for the endTag while we are processing
    if (charIn == endTag[index])
    {
      index++;
    }
    else
    {
      index = 0;
    }

    // have we found the endTag?
    if (index == 5)
    {
      Serial.println("*"); //line end
      started = 0;
      index = 0;
    }
  }
}

Olá!

Procure pela função "strtok_r", você poderá quebrar a mesagem nos dois pontos ( : ) e enviar somente a parte desejada.

Aqui tem exemplos:

https://github.com/FernandoGarcia/Ferduino_with_webcontrol_beta/blob/master/Ferduino_with_webcontrol_beta/Webserver.ino#L78

https://create.arduino.cc/editor/FernandoGarcia/35443889-d8fa-4194-bc59-2d7a2e70692a/preview

http://forum.arduino.cc/index.php?topic=186687.0

Como o " OK+DISCE" será constante você poderá ignorar na chegada ou separar no espaço.

Abraço.

FernandoGarcia: Olá!

Procure pela função "strtok_r", você poderá quebrar a mesagem nos dois pontos ( : ) e enviar somente a parte desejada.

Aqui tem exemplos:

https://github.com/FernandoGarcia/Ferduino_with_webcontrol_beta/blob/master/Ferduino_with_webcontrol_beta/Webserver.ino#L78

https://create.arduino.cc/editor/FernandoGarcia/35443889-d8fa-4194-bc59-2d7a2e70692a/preview

http://forum.arduino.cc/index.php?topic=186687.0

Como o " OK+DISCE" será constante você poderá ignorar na chegada ou separar no espaço.

Abraço.

Muito obrigado Fernando pela resposta, vou tentar implementar esta função. Outro problema que estou enfrentando com o Arduino Nano é que quando inicio outra serial simplesmente ele para de dar o print no monitor. Voce saberia me auxiliar nesse problema? A ideia é separar o resultado do comando em string e enviar via serial para o esp-01 porém quando tento iniciar outra serial além da conexao com o HM-10 ele simplesmente para de mostrar os valores no monitor serial...

Que eu saiba não dá para usar a serial 0 para duas funções ao mesmo tempo.

Tente usar a biblioteca softwareSerial para o dispositivo e deixar a serial 0 para o monitor.

Fernando eu estou conseguindo utilizar somente o esp-01 e o hm-10 porém tenho alguns problemas nas detecções. O que acontece é o seguinte: vou deixar para separar os valores no matlab e enviar toda a string recebida já é suficiente. No meu programa atual consigo enviar somente esta string: OK DISISOK DISC:4C000215:003E8C80EA014EBBB88878DA19DF9E55:00000000C1:6BF7E1EED3A6:-056OK DISC:4C000215:003E8C80EA014EBBB88878DA19DF9E55:00000000C1:431A8029738A:-058OK DISC:4C000215:003E8C80EA014EBBB88878DA19DF9E55:00000000C1:62C7EDB731FE:-054OK DISC:4C000

Sendo que a string original é a seguinte: OK+DISISOK+DISC:4C000215:003E8C80EA014EBBB88878DA19DF9E55:00000000C1:7A7C6355A01C:-048OK+DISC:4C000215:003E8C80EA014EBBB88878DA19DF9E55:00000000C1:669A1BFFA0E8:-048OK+DISC:4C000215:003E8C80EA014EBBB88878DA19DF9E55:00000000C1:55E055D6B813:-048OK+DISC:4C000215:003E8C80EA014EBBB88878DA19DF9E55:00000000C1:7369CB99C575:-048OK+DISC:4C000215:003E8C80EA014EBBB88878DA19DF9E55:00000000C1:6B1B44660A19:-048OK+DISCE

Perceba que no meu programa atual ele nao consegue receber ou enviar toda a string, talvez seja pelo tempo leitura ou algo do tipo. Enfim, será que você poderia dar uma olhada no meu código para ver como consigo receber todo o valor? Obrigado.

#include <ESP8266WiFi.h>


// replace with your channel's thingspeak API key, 
String apiKey = "apikey";
const char* ssid = "ssid";
const char* password = "password";
const char* server = "api.thingspeak.com";

//detector beacon
int started = 0;
int ind = 0;
const char endTag[] = "DISCE";

const int timeout = 5000;

WiFiClient client;
   
 
void setup() 
{                
  Serial.begin(9600);
  Serial.setTimeout(timeout);
  WiFi.begin(ssid, password); 
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(500);
  } 
}
 

void loop() 
{
  if (started == 0)
  {
    Serial.print("AT+DISI?");
    started = 1;
  }
  
  if (started ==1 && Serial.available())
  {
      String d = "";

      while(Serial.available())
      {
        d = Serial.readString();

      }      
      
      if (client.connect(server,80))      //   "184.106.153.149" or api.thingspeak.com
      {
        String postStr = apiKey;
               postStr +="&field1=";
               postStr += String(d);
               postStr += "\r\n";
 
        client.print("POST /update HTTP/1.1\n"); 
        client.print("Host: api.thingspeak.com\n"); 
        client.print("Connection: close\n"); 
        client.print("X-THINGSPEAKAPIKEY: "+apiKey+"\n"); 
        client.print("Content-Type: application/x-www-form-urlencoded\n"); 
        client.print("Content-Length: "); 
        client.print(postStr.length()); 
        client.print("\n\n");
        client.print(postStr);
      }
      
      client.stop();
      delay(17000); // thingspeak needs minimum 15 sec delay between updates
      started = 0;      
  } 
}

Se o tempo não é suficiente altere esta linha:

const int timeout = 5000;

Tenha certeza que há memória suficiente para armazenar esta string.

Evite usar isto:

delay(17000);

Use a função millis().

FernandoGarcia: Se o tempo não é suficiente altere esta linha:

const int timeout = 5000;

Tenha certeza que há memória suficiente para armazenar esta string.

Evite usar isto:

delay(17000);

Use a função millis().

Tentei aumentar o valor do timeout mas não adiantou. Como verifico se há memória suficiente para armazenar esta string de 406 caracteres? Como eu poderia fazer para a variavel ficar recebendo valores do Serial.read até encontrar o marcador "DISCE"?

[EDIT] Acho que é problema de memória do ESP-01 mesmo ou entao uma limitação do servidor ThingSpeak, apesar que já vi pessoas comentando que conseguiram enviar mais de 1000 caracteres...

Use esta função:

Serial.print("FreeHeap : ");
Serial.println(ESP.getFreeHeap());

Após:

client.print(postStr);

Adicione:

Serial.println(postStr);

E veja se é possível receber a string completa no HM-10 já que não é possível usar o monitor serial simultaneamente.

Recomendo-te usar um NodeMCU que tem muitos pinos disponíveis e interface USB, o ESP-01 é muito limitado.

Boa tarde. Tudo certo? Estou trabalhando em um projeto parecido com o seu, porém quando comprei os HM-10 vieram o CC41a e o MLT-BT05 (clones do HM10), os quais não encontram outros dispositivos a não ser eles e também não possuem comandos tais como AT+DISI? que retorna os dispositivos próximos, junto com o MAC e o RSSI, que era exatamente o que eu precisava. Sabe me informar onde comprou estes HM-10 genuínos que atendem a tal comando? Preciso urgentemente de comprá-los, mas não estou encontrando.

Desde já agradeço!

Oi, eu comprei os HM-10 diretamente do mercadolivre porém o anuncio se encontra pausado, segue o link: http://produto.mercadolivre.com.br/MLB-713082252-modulo-bluetooth-v40-hm-10-master-slave-serial-arduino-_JM

Existem outros vendedores no ML que vendem este módulo, procure entrar em contato questionando a versão do Firmware que vem instalada. Se eles te responderem algo como: v540 ou v390 é original

Obrigado, Kether! Consegui encontrar outro fornecedor que possui o HM-10 original.

Agora estou com o mesmo problema que você... Ele não está retornando todo o texto que deveria. Sempre falta partes.

Você conseguiu resolver?

Pessoal gostaria de ajuda no desenvolvendo de um detector de beacons, estou utilizando um arduino uno, um módulo ble HM-10 e um ESP-01 (modulo wifi). Preciso que o arduino detecte os beacons automaticamente e grave os dados via wifi no banco de dados mysql.