modifica sketch per controller bluetooth, da 2.0 a 4.0

ciao a tutti,
tempo fa ho visto questo LINK
in cui un tizio spiega come interfacciare un accelerometro (MPU6050) con un gimbal (per chi non lo sapesse, è un uno stabilizzatore per fotocamere), via bluetooth.
Ho seguito il tutorial suddetto ma poi, visto che non funzionava, ho scoperto che l’HC-05 usa il bluetooth 2.x mentre nel mio sistema dovrebbe esserci (non ne sono certissimo) un HM-1x (10 o forse 11) che usa il bluetooth 4.0. Nome del modulo a parte, ho confermato che il gimbal usa la 4.0 dato che non viene visto da un vecchio smartphone che usa il 3.0, mentre viene tranquillamente visto da uno smartphone con il 4.0.
E’ praticamente la prima volta che uso il bluetooth con Arduino quindi sono poco “formato” su questo tipo trasmissione.
Mi pare di aver capito però che che i due standard sono nettamente diversi e mentre il 2.x usa comandi AT come CMODE, PAIR e LINK, nel 4.0 non è previsto il pairing.
Vorrei modificare lo sketch di configurazione (linkato nella pagina ma che riporto di seguito):

/*
#include <SoftwareSerial.h>

/*********************************************************************/

#define TRUE                        (1)
#define FALSE                       (0)
#define BT_MAXLINE                  (40)

// Joypad:
// PC format -> 20:14:05:14:32:83
// AT format -> 2014:5:143283

// FunnyGo:
// PC format -> 20:14:03:24:11:76
// AT format -> 2014,3,241176

#define BT_ADDRESS                  "2014,3,241176"
#define BT_PASSWORD                 "1234"

#define HC05_POWER                  (8)
#define HC05_ATMODE                 (9)

/*********************************************************************/

SoftwareSerial BluetoothSerial(10, 11);

/*********************************************************************/

int Counter = 0;

char BTResponseBuffer[BT_MAXLINE];
int BTResponseFilled = 0;

int BT_SendCommand(int Timeout, char *Command)
{
    int i;
    int StartTime;
    int CurrentTime;
    char NewChar;

    BluetoothSerial.println(Command);

    BTResponseBuffer[0] = '\0';
    BTResponseFilled = 0;
    StartTime = millis();
    while(1)
        {
        CurrentTime = millis();
        if ((CurrentTime - StartTime) > Timeout)
            {
            return FALSE;
            }

        if (BluetoothSerial.available())
            {
            NewChar = BluetoothSerial.read();
            if ((NewChar == '\r') || (NewChar == '\n'))
                break;
            BTResponseBuffer[BTResponseFilled++] = NewChar;
            if (BTResponseFilled > (BT_MAXLINE - 2))
                return FALSE;
            }
        }

    BTResponseBuffer[BTResponseFilled] = '\0';
    if (BTResponseFilled == 0)
        return FALSE;

    Serial.print("Response ");
    Serial.print(BTResponseFilled, DEC);
    Serial.print(": ");
    for(i=0; i < BTResponseFilled; i++)
        {
        Serial.print(BTResponseBuffer[i], HEX);
        Serial.print(" ");
        }
    Serial.println("");
    return TRUE;
}

/*********************************************************************/


void setup(void)
{
    int i;

    pinMode(HC05_ATMODE, OUTPUT);
    digitalWrite(HC05_ATMODE, HIGH);

    Serial.begin(9600);
    BluetoothSerial.begin(38400);               /* The AT mode runs at 38400 */

    Serial.println("Ready.");
}


void loop(void)
{
    char *Command;
    char TempChar;


    Serial.println(Counter);
    delay(1000);
    Counter += 1;

    switch(Counter)
        {
        case 10:    Command = "AT+RESET";                   break;
        case 11:    Command = "AT+ORGL";                    break;
        case 12:    Command = "AT+VERSION?";                break;
        case 13:    Command = "AT+ADDR?";                   break;
        case 14:    Command = "AT+UART=9600,0,0";           break;
        case 15:    Command = "AT+ROLE=1";                  break;
        case 16:    Command = "AT+STATE?";                  break;
        case 17:    Command = "AT+PSWD="BT_PASSWORD;        break;
        case 18:    Command = "AT+INQM=0,5,5";              break;
        case 19:    Command = "AT+INIT";                    break;
        case 20:    Command = "AT+STATE?";                  break;
        case 21:    Command = "AT+INQ";                     break;

        case 25:    Command = "AT+RNAME?"BT_ADDRESS;        break;

        case 31:    Command = "AT+PAIR="BT_ADDRESS",20";    break;
        case 40:    Command = "AT+STATE?";                  break;

        case 41:    Command = "AT+BIND="BT_ADDRESS;         break;
        case 50:    Command = "AT+STATE?";                  break;

        case 51:    Command = "AT+CMODE=0";                 break;
        case 52:    Command = "AT+LINK="BT_ADDRESS;         break;
        case 60:    Command = "AT+STATE?";                  break;
        default:    Command = NULL;                         break;
        }

    if (Command != NULL)
        {
        Serial.print("Command:  ");
        Serial.println(Command);
        BT_SendCommand(10 * 1000, Command);
        Serial.print("Response: ");
        Serial.println(BTResponseBuffer);
        }

    while(BluetoothSerial.available())
        Serial.write(BluetoothSerial.read());
    while(Serial.available())
        {
        TempChar = Serial.read();
        Serial.write(TempChar);
        BluetoothSerial.write(TempChar);
        }
}

/*********************************************************************/

Mi ritrovo un modulo chiamato “BT05”, che usa il CC2541 (lo stesso dell’HM-10), quindi bluetooth 4.0. E’ un modulo cinese… e con il simpatico comando AT:
AT+HELP mi fornisce questa lista di comandi disponibili:


  • Command Description *
  • ---------------------------------------------------------------- *
  • AT Check if the command terminal work normally *
  • AT+RESET Software reboot *
  • AT+VERSION Get firmware, bluetooth, HCI and LMP version *
  • AT+HELP List all the commands *
  • AT+NAME Get/Set local device name *
  • AT+PIN Get/Set pin code for pairing *
  • AT+BAUD Get/Set baud rate *
  • AT+LADDR Get local bluetooth address *
  • AT+ADDR Get local bluetooth address *
  • AT+DEFAULT Restore factory default *
  • AT+RENEW Restore factory default *
  • AT+STATE Get current state *
  • AT+PWRM Get/Set power on mode(low power) *
  • AT+POWE Get/Set RF transmit power *
  • AT+SLEEP Sleep mode *
  • AT+ROLE Get/Set current role. *
  • AT+PARI Get/Set UART parity bit. *
  • AT+STOP Get/Set UART stop bit. *
  • AT+INQ Search slave model *
  • AT+SHOW Show the searched slave model. *
  • AT+CONN Connect the index slave model. *
  • AT+IMME System wait for command when power on. *
  • AT+START System start working. *
  • AT+UUID Get/Set system SERVER_UUID . *
  • AT+CHAR Get/Set system CHAR_UUID . *
  • -----------------------------------------------------------------*
  • Note: (M) = The command support master mode only. *

NOTA: Il BT05 vede il gimbal.

Dopo aver settato il baud rate, la parità e il PIN ho configurato il controllo remoto con l’accelerometro come MASTER, quindi:
AT+ROLE=1

Ho fatto
AT+INQ
e ricevuto i due indirizzi bluetooth disponibili in vicinanza:

Scanning…+INQ:1 0x6618AC3E61B8
+INQ92 0x5XXXXXXXXXXX
+INQE

Stando al manuale (in cinese) del BT05
LINK al PDF
per associare un dispositivo (slave) è necessario il comando:
AT+CONN seguito dal numero finale della risposta “+INQ:”, che nella scansione sopra riportata sarebbe “2” (le x le ho messe io, ovviamente). Intanto, quel numero cambia (può trovare altri dispositivi) ogni volta che viene rifatta la scansione dei dispositivi disponibili, quindi se perdo il collegamento non è detto che riesco ad agganciare lo slave (il gimbal). Ma anche facendo un test a computer acceso (facendo scansione e associazione) non risolvo il problema.
Cosa mi consigliate di fare?
Secondo voi è fattibile quel controller?
Dovrei “semplicemente” modificare lo sketch di setup (dei due riportati al link sopra) o dite che vanno fatte modifiche complicate anche a quello del controller che legge l’MPU e invia i comandi di posizione al gimbal?

dite che è meglio rinunciare?

Sto trafficando su una cosa simile,
ti consiglio di usare una scheda ESP32, ha già il bluetooth 4.0 integrato.
Il bluetooth 4.0 è completamente diverso dai precedenti è utilizza un protocollo chiamato GATT basato su identificativi universali UUID.
Trovi molto materiale sul sito della Nordic e (ovviamente) su quello ufficiale del protocollo bluetooth.
Io ho iniziato da zero e sono ancora in alto mare.
Che io sappia i moduli hm-10 usano una versione semplificata del BLE che rende impossibile una vera e propria comunicazione con altri dispositivi BLE.
Se non ho capito male utilizzano una sola caratteristica (quindi un solo UUID) e non mi pare che abbia servizi,
si nota dagli ultimi comandi AT.
In parole povere, sono una rogna.

Spero di esserti stato utile.

P.S.
C'è la remota possibilità che si possa fare, ma dipende dal tuo gimbal, quante caratteristiche ha, quanti servizi.
Puoi usare l'app della Nordic: nRF Connect per controllare quello che ti ho scritto sopra.
Questo video youtube mi è stato molto utile.

Introduzione al BLE (bluetooth 4.0) che permette di capire che il BLE, nonostante il nome, con il classico Bluetooth 2.x ha ben poco a che vedere ... Prima parte, Seconda parte, Terza parte e Quarta parte.

Un mio breve thread sull'argomento QUI.

Guglielmo

intanto grazie delle risposte.

Il problema che ho riscontrato è che con il comando “AT+CONN” riesco a far connettere (il led di stato resta acceso fisso) il BT05 col gimbal (e spegnendo quest’ultimo, il led riprende a lampeggiare, a prova della perdita della connessione).
Ma non succede nulla, i dati dell’MPU non vengono inviati (o forse sì ma il gimbal non reagisce).

Lo sketch di controllo è lungo (e supero i 9000 caratteri permessi dal forum), quindi non posso riportarlo per intero.
La prima parte è:

#include <SoftwareSerial.h>
#include "MPU6050_6Axis_MotionApps20.h"
#include "Wire.h"

/*********************************************************************/

#define TRUE                                    (1)
#define FALSE                                   (0)

#define GIMBAL_DEGREES2ANGLE(Degree)            ((int16_t)((float)(Degree) * (1.0f / 0.02197265625f)))
#define GIMBAL_CALCULATESPEED(Speed)            ((int16_t)((float)(Speed) * (1.0f / 0.1220740379f)))

#define GIMBAL_MAXRESPONSE                      (40)
#define GIMBAL_COMMANDTIMEOUT                   (1 * 1000)
#define GIMBAL_PINGTIMEOUT                      (1 * 1000)
#define GIMBAL_PINGFAILURES                     (3)
#define GIMBAL_MODE1                            (1)
#define GIMBAL_MODE2                            (2)
#define GIMBAL_MODE3                            (3)
#define GIMBAL_MODEMANUAL                       (4)
#include "I2Cdev.h"

#define MPU_DISPLAYRATE                         (100)
#define MPU_SAMPLESMOOTHING                     (3)

#define GIMBAL_RANGEROLL                        (90)
#define GIMBAL_RANGEPITCH                       (180)
#define GIMBAL_RANGEYAW                         (90)

#define HC05_POWER                              (8)
#define HC05_ATMODE                             (9)

#define LED_PIN                                 (13)

#define ZERO_PIN                                (6)

/*********************************************************************/

MPU6050 mpu;

uint16_t MPUPacketSize                          = 0;
int MPUCounter                                  = 0;
bool MPUReady                                   = FALSE;
float MPUPitch                                  = 0.0;
float MPURoll                                   = 0.0;
float MPUYaw                                    = 0.0;
float MPUStartPitch                             = 0.0;
float MPUStartRoll                              = 0.0;
float MPUStartYaw                               = 0.0;


SoftwareSerial BluetoothSerial(10, 11);                     /* RX, TX */

byte GimbalDetected                             = FALSE;
byte GimbalJustConnected                        = FALSE;
byte GimbalPingAttempts                         = 0;
int GimbalSpeed                                 = 80;
int GimbalLastMessage                           = 0;
char GimbalResponseBuffer[GIMBAL_MAXRESPONSE]   = {0};
int GimbalResponseFilled                        = 0;

/*********************************************************************/

void System_FlashLED(int Count)
{
    byte i;

    for(i=0; i < Count; i++)
        {
        digitalWrite(LED_PIN, HIGH);
        delay(250);
        digitalWrite(LED_PIN, LOW);
        delay(250);
        }

    delay(500);
}

int System_MemoryAvailable(void)
{
    extern int __heap_start, *__brkval;
    int v;
    return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

/*********************************************************************/

void Gimbal_SendCommand(byte Command, byte *Data, int Size)
{
    byte i, Checksum = 0;


    BluetoothSerial.write('>');
    BluetoothSerial.write(Command);
    BluetoothSerial.write(Size);
    BluetoothSerial.write(Command + Size);
    for(i=0; i < Size; i++)
        {
        Checksum += Data[i];
        BluetoothSerial.write(Data[i]);
        }
    BluetoothSerial.write(Checksum);

//    Serial.print(Command);
//    Serial.println(" Message sent.");

    delay(20);                                                  /* 20ms delay as suggested in SimpleBGC firmware */
}


int Gimbal_ProcessCommand(int Timeout, byte WaitForResponse, byte Command, byte *Data, int DataSize)
{
    int i;
    int StartTime;
    int CurrentTime;
    int ResponseSize = 4;
    int InMessage = FALSE;
    char NewChar;


    if (WaitForResponse == TRUE)                                /* Make sure anything that might be waiting is cleared */
        {
        delay(20);
        while(BluetoothSerial.available())
            BluetoothSerial.read();
        }

    if (Command != 0)
        Gimbal_SendCommand(Command, Data, DataSize);

    BluetoothSerial.println(Command);

    GimbalResponseFilled = 0;
    if (WaitForResponse == FALSE)
        return TRUE;

    StartTime = millis();
    while(GimbalResponseFilled < ResponseSize)
        {
        CurrentTime = millis();
        if ((CurrentTime - StartTime) > Timeout)
            {
            Serial.println("Timeout");
            return FALSE;
            }

        if (BluetoothSerial.available())
            {
            GimbalLastMessage = millis();
            GimbalPingAttempts = 0;
            NewChar = BluetoothSerial.read();
            if ((NewChar == '>') && (InMessage == FALSE))
                {
                GimbalResponseFilled = 0;
                InMessage = TRUE;
                }
            if (InMessage == TRUE)
                {
                GimbalResponseBuffer[GimbalResponseFilled++] = NewChar;
                if (GimbalResponseFilled > (GIMBAL_MAXRESPONSE - 2))
                    {
                    Serial.print("Overrun: ");
                    Serial.println(ResponseSize);
                    return FALSE;
                    }
                if (GimbalResponseFilled == 3)
                    {
                    ResponseSize = (GimbalResponseBuffer[2] + 4 + 1);
                    }
                }
            }
        }

    GimbalResponseBuffer[GimbalResponseFilled] = '\0';
    if ((GimbalResponseFilled == 0) && (ResponseSize > 0))
        {
        Serial.print("No response: ");
        Serial.println(ResponseSize);
        return FALSE;
        }

    Serial.print("Response ");
    Serial.print(GimbalResponseFilled, DEC);
    Serial.print(": ");
    for(i=0; i < GimbalResponseFilled; i++)
        {
        Serial.print(GimbalResponseBuffer[i], HEX);
        Serial.print(" ");
        }
    Serial.println("");

    if ((Command != 0) &&
        (GimbalResponseBuffer[1] != Command))
        {
        Serial.print("Mismatched: ");
        Serial.println(Command, HEX);
        return FALSE;
        }
    return TRUE;
}

Ovviamente, il baud rate del gimbal è settato a 115200. Ho anche provato a cambiarlo (fino a 9600) ma non succede niente.

Non capisco se vi è qualcosa nello sketch riportato sopra che va cambiato.

Fermati, stai facendo un errore, prima di tutto devi essere sicuro che il tuo gimball sia BLE perché, come ha sottolineato gpb01 con maggiore sintesi rispetto a me, 4.0 e i precedenti BT non hanno nulla a che vedere in termini di comunicazione.
La struttura della comunicazione è diversa, non si possono capire.
In più, un programma pensato per BT deve essere pesantemente modificato per funzionare con un protocollo GATT BLE (nel tuo caso se dovessi avere una fortuna sfacciata e la comunicazione con il gimball dovesse necessitare di una sola caratteristica, forse no).
Usa l'applicazione che ti ho consigliato per verificare se il gimball usa BLE e puoi già guardare quante caratteristiche (e servizi) mette a disposizione.

Se il tuo gimball è BLE, per portare a termine questo progetto devi studiare un poco come funziona il protocollo gatt.
Ma se il gimball prevede anche un protocollo di accoppiamento il HM-10 non penso che basti, lui va a cercare una sola caratteristica, mentre può darsi che nel tuo caso ne serva una per l'accoppiamento e almeno una per la comunicazione dati.