BLE UART adapted for controlling ObCP ENSMM user board with nrF UART

Dependencies:   mbed X_NUCLEO_IDB0XA1 BLE_API LIS3DH_spi

main.cpp

Committer:
jimbaud
Date:
2020-11-09
Revision:
13:38d6b18040c7

File content as of revision 13:38d6b18040c7:

#include "mbed.h"
#include "ble/BLE.h"
#include "ble/services/UARTService.h"
#include "Serial.h"
#include "LIS3DH.h"
#include "stdlib.h"

#define UART_BUFFER (UARTService::BLE_UART_SERVICE_MAX_DATA_LEN)


const static char DEVICE_NAME[] = "ObCP";
UARTService *uartServicePtr;

//PWM output
PwmOut PWMoutput(PB_1);          //Main PWM output
PwmOut Green(PC_8);              //PWM Red LED
PwmOut Red(PC_6);                //PWM Green LED
PwmOut Blue(PC_9);               //PWM Blue LED

//Accelerometer

#define MOSI PC_12
#define MISO PC_11
#define CS PC_5
#define SCLK PC_10

// Def Peripheriques
DigitalIn myButton(PC_13);    // USER BUTTON
//Init accelerometer
LIS3DH      acc(MOSI, MISO, SCLK, CS, LIS3DH_DR_NR_LP_50HZ, LIS3DH_FS_2G);

Ticker Acceleration;

// Tableau et index de communication avec UART
static char uartBuff[UART_BUFFER];
// Variables contenant accelerations
double accX, accY, accZ;
// Routine de traitement des erreurs
void onBleError(ble_error_t error);

/****************************************************/
/* Ticker actif lorsque la connexion BLE est présente */
/****************************************************/
void ConnectedBLE(void)
{
    // Signal de vie: allumer et éteindre la LED
    Green.period(1.0f);  // période = 1 seconde
    Green.write(0.01f);  // élaire 1% de la période
}

void AccMeasurement(void)
{
    char outstrX[5];
    char outstrY[5];
    char outstrZ[5];

    // Mesure des accélérations sur les 3 axes
    accX = float(short((acc.read_reg(LIS3DH_OUT_X_H) << 8) | acc.read_reg(LIS3DH_OUT_X_L))) * 0.001F / 15;
    accY = float(short((acc.read_reg(LIS3DH_OUT_Y_H) << 8) | acc.read_reg(LIS3DH_OUT_Y_L))) * 0.001F / 15;
    accZ = float(short((acc.read_reg(LIS3DH_OUT_Z_H) << 8) | acc.read_reg(LIS3DH_OUT_Z_L))) * 0.001F / 15;

    //Transformation des valeurs numeriques en chaine de caracteres
    sprintf(outstrX,"%5.2f",accX);
    sprintf(outstrY,"%5.2f",accY);
    sprintf(outstrZ,"%5.2f",accZ);
    //Integre les trois chaines de caractere contenant les accelerations dans la chaine uartBuff
    sprintf(uartBuff, "X%s Y%s Z%s", outstrX, outstrY, outstrZ) ;
    //Envoie la chaine uartBuff sur le sevice TX UART BLE
    uartServicePtr->write(uartBuff, UARTService::BLE_UART_SERVICE_MAX_DATA_LEN);
    // Réinitialiser la chaîne uartBuff en entrant 0 dans les premiers caractères UART_BUFFER
    memset(uartBuff, 0, UART_BUFFER);

}

/*************************/
/* Connexion BLE réussie */
/*************************/
void BleConnectionCallback(const Gap::ConnectionCallbackParams_t *params)
{
    // Signal de connexion BLE: allume / éteint la LED avec une période de 1 seconde
    ConnectedBLE();
    Acceleration.attach(AccMeasurement, 1);
}

/*****************************/
/* Déconnexion du client BLE */
/*****************************/
void BleDisconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
{
    (void)params;
    // Redémarrer la publicité
    Acceleration.detach();
    BLE::Instance().gap().startAdvertising();
    
    PWMoutput.write(0.0f);
    Green.write(0.0f);
    Red.write(0.0f);
    Blue.write(0.0f);
}

/***************************/
/* Rx de BLE et Rx vers USB*/
/***************************/
void BleOnDataWrittenCallback(const GattWriteCallbackParams *params)
{
    char reception[UART_BUFFER];
    char commande[2];
    float valeur;

    // Reçoit une chaîne de BLE
    if (params->handle == uartServicePtr->getTXCharacteristicHandle()) {
        // Copie de la chaine reçue dans reception
        sprintf(reception,"%s", params->data);
        // Copie dans la chaine commande des deux premier caracteres de la chaine reception
        sprintf(commande,"%c%c", reception[0], reception[1]);
        // Transformation des 3 caracteres suivants en valeur numerique
        valeur = ((reception[2] - '0')* 100 + (reception[3] - '0')* 10 +(reception[4] - '0')) ;
        valeur = valeur/255;
                
        if( strcmp(commande, "LR")==0) {
            Red.period(0.01f);
            Red.write(valeur);
        }
        if( strcmp(commande, "LV")==0) {
            Green.period(0.01f);
            Green.write(valeur);
        }
        if( strcmp(commande, "LB")==0) {
            Blue.period(0.01f);
            Blue.write(valeur);
        }
        if( strcmp(commande, "PW")==0) {
            PWMoutput.period(0.001f);
            PWMoutput.write(valeur);
        }

    }
}

/***************************/
/* Erreur sur le canal BLE */
/***************************/

void onBleError(ble_error_t error)
{
    Red.period(0.8f);  // période = 0.8 seconde
    Red.write(0.10f);  // élaire 10% de la période
    /* Entrer le traitement des erreurs */
}

/**************************************/
/* Initialisation du service BLE UART */
/**************************************/

void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
{
    BLE&        ble   = params->ble;
    ble_error_t error = params->error;

    if (error != BLE_ERROR_NONE) {

        /* En cas d'erreur, transmettez le traitement d'erreur à onBleInitError*/
        onBleError(error);
        return;
    }

    /* Assurez-vous qu'il s'agit de l'instance par défaut de BLE */
    if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
        return;
    }

    ble.gap().onConnection(BleConnectionCallback);
    ble.gap().onDisconnection(BleDisconnectionCallback);
    ble.gattServer().onDataWritten(BleOnDataWrittenCallback);

    /* Configuration du service primaire. */
    UARTService uartService(ble);
    uartServicePtr = &uartService;

    /* Configurer la publicité */
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble.gap().setAdvertisingInterval(500); /* 500ms. */
    ble.gap().startAdvertising();

    // Attend les événements sur BLE
    while (true) {
        ble.waitForEvent();
    }
}

/********/
/* MAIN */
/********/
int main(void)
{
    //Définit le fonctionnement du bouton sur "PullDown": Open = '0'. L’autre mode de fonctionnement est PullUp
    myButton.mode(PullDown);

    // Initialiser LED
    Green.write(0.0f);
    Red.write(0.0f);
    Blue.write(0.0f);

    /****** START Initialiser BLE **********/
    BLE &ble = BLE::Instance();
    ble.init(bleInitComplete);
    /******* FIN initialise BLE ***********/

}