Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BLE_API X_NUCLEO_IDB0XA1 X_NUCLEO_IKS01A1 mbed
Fork of SunTracker_BLE_Remote by
This application is the BLE Remote Control for the SunTracker demo application that you can find
here.
Please refer to that page for further information.
main.cpp
- Committer:
- fabiombed
- Date:
- 2016-03-21
- Revision:
- 5:5e62f661a7ab
- Parent:
- 4:17f96ffc073a
- Child:
- 6:ce0e5024e3fa
File content as of revision 5:5e62f661a7ab:
/**
******************************************************************************
* @file main.cpp
* @author Fabio Brembilla
* @version V2.0.0
* @date March, 2016
* @brief SunTracker + BLE (Client) Vertical Application
* This application use IKS01A1, IDB0XA1 expansion boards
******************************************************************************
* @attention
*
* <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Define --------------------------------------------------------------------*/
#define Sensors //IKS01A1 Option
/* Includes ------------------------------------------------------------------*/
#include "mbed.h"
#include "ble/BLE.h"
#include "ble/DiscoveredCharacteristic.h"
#include "ble/DiscoveredService.h"
#ifdef Sensors
#include "DevI2C.h"
#include "x_nucleo_iks01a1.h"
#endif
/* BlueTooth -----------------------------------------------------------------*/
#include "Utils.h" // Need for STORE_LE_16 and STORE_LE_32
#define SCAN_INT 0x30 // 30 ms = 48 * 0.625 ms
#define SCAN_WIND 0x30 // 30 ms = 48 * 0.625 ms
const Gap::Address_t BLE_address_BE = {0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA}; // CLIENT address
const Gap::Address_t BLE_peer_address_BE = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; // SERVER address (must be the same of SERVER)
//const Gap::Address_t BLE_address_BE = {0xCC, 0x00, 0x00, 0xE1, 0x80, 0x02}; // CLIENT address
//const Gap::Address_t BLE_peer_address_BE = {0xFD, 0x66, 0x05, 0x13, 0xBE, 0xBA}; // SERVER address (must be the same of SERVER)
DiscoveredCharacteristic userbutton_bleCharacteristic;
DiscoveredCharacteristic difference_bleCharacteristic;
DiscoveredCharacteristic position_bleCharacteristic;
DiscoveredCharacteristic sunpanel_bleCharacteristic;
#define SIZEOF_CONTROL_DATA_LEN 2
#define DIFFERENCE_DATA_LEN 2
// 1 byte 0xFF 8 bit int8
// 2 byte 0xFFFF 16 bit int16
uint8_t value_write[SIZEOF_CONTROL_DATA_LEN];
int16_t value_read = 0;
uint8_t value_write_diff[DIFFERENCE_DATA_LEN];
/* Variables ------------------------------------------------------------------*/
enum {
IDLE = 0,
READ_BUT = 1,
READ_DIF = 2,
READ_POS = 3,
READ_SUN = 4,
WRITE_BUT = 5,
WRITE_DIF = 6
};
int trigger_Op = IDLE;
bool trigger_button = false;
int8_t display=0; // Shown on Display: 0 = Motor Speed, 1 = Solar Panel Value, 2 = Manual Control [--> Receive BLE]
int16_t diff=0; // Babybear or Accelerometer difference [--> Receive BLE]
int16_t pos=0; // Motor Position [--> Receive BLE]
int16_t measure=0; // ADC Value from SunPanel [--> Receive BLE]
/* Initializations ------------------------------------------------------------*/
#ifdef Sensors
// Initializing I2C bus
DevI2C dev_i2c(D14, D15);
// Initializing Sensors Component IKS01A1
static X_NUCLEO_IKS01A1 *mems;
MotionSensor *accelerometer;
int32_t acc_data[3]; // Accelerometer difference
int16_t acc_diff=0; // Accelerometer difference
#endif
InterruptIn mybutton(USER_BUTTON);
/* User_Button_Pressed -------------------------------------------------------*/
void User_Button_Pressed(void)
{
trigger_button = true;
}
/* Bluetooth CallBack ---------------------------------------------------------*/
void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params)
{
if (params->peerAddr[0] != BLE_peer_address_BE[0]) // return if miss the server MAC address
{
printf("Missing Expected MAC Address");
return; // exit from advertisementCallback
}
// printf("adv peerAddr[%02x %02x %02x %02x %02x %02x] rssi %d, isScanResponse %u, AdvertisementType %u\r\n",
// params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2], params->peerAddr[1], params->peerAddr[0],
// params->rssi, params->isScanResponse, params->type);
printf("Found Expected MAC Address: isScanResponse %u, AdvertisementType %u\r\n",params->isScanResponse, params->type);
if(!params->isScanResponse)
{
BLE::Instance().gap().connect(params->peerAddr, Gap::ADDR_TYPE_PUBLIC, NULL, NULL);
}
}
void serviceDiscoveryCallback(const DiscoveredService *service)
{
printf("Start Service Discovery\r\n");
/*
if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT)
{
printf("S UUID-%x attrs[%u %u]\r\n", service->getUUID().getShortUUID(), service->getStartHandle(), service->getEndHandle());
}
else
{
printf("S UUID-");
const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++)
{
printf("%02X", longUUIDBytes[i]);
}
printf(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle());
}
*/
}
void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP)
{
if (characteristicP->getUUID().getShortUUID() == 0xA001)
{
userbutton_bleCharacteristic = *characteristicP;
printf("Found 0xA001 Characteristic\r\n");
}
if (characteristicP->getUUID().getShortUUID() == 0xB001)
{
difference_bleCharacteristic = *characteristicP;
printf("Found 0xB001 Characteristic\r\n");
}
if (characteristicP->getUUID().getShortUUID() == 0xB002)
{
position_bleCharacteristic = *characteristicP;
printf("Found 0xB002 Characteristic\r\n");
}
if (characteristicP->getUUID().getShortUUID() == 0xB003)
{
sunpanel_bleCharacteristic = *characteristicP;
printf("Found 0xB003 Characteristic\r\n");
}
}
void discoveryTerminationCallback(Gap::Handle_t connectionHandle)
{
//printf("discoveryTerminationCallback for handle %u\r\n", connectionHandle);
printf("Stop Service Discovery\r\n\r\n");
trigger_Op = READ_BUT;
}
void onDataReadCallback(const GattReadCallbackParams *response)
{
// Read SERVER --> CLIENT
/*
printf("response Handle %d\r\n", response->handle);
printf("userbutton Handle %d\r\n", userbutton_bleCharacteristic.getValueHandle());
printf("difference Handle %d\r\n", difference_bleCharacteristic.getValueHandle());
printf("position Handle %d\r\n", position_bleCharacteristic.getValueHandle());
printf("sunpanel Handle %d\r\n", sunpanel_bleCharacteristic.getValueHandle());
printf("onDataRead (data[0] %x)\r\n", response->data[0]);
printf("onDataRead (data[1] %x)\r\n\r\n", response->data[1]);
*/
// Return original value after inverted with STORE_LE_16 to send by BLE
value_read = response->data[0] + (response->data[1]<<8);
if (response->handle == userbutton_bleCharacteristic.getValueHandle())
{
display = value_read;
printf("\n\rReceive BLE Display %d\n\r", display);
trigger_Op = READ_DIF;
}
if (response->handle == difference_bleCharacteristic.getValueHandle())
{
diff = value_read;
printf("Receive BLE Difference %d lux/mems\n\r", diff);
trigger_Op = READ_POS;
}
if (response->handle == position_bleCharacteristic.getValueHandle())
{
pos = value_read;
printf("Receive BLE Position %d\n\r", pos);
trigger_Op = READ_SUN;
}
if (response->handle == sunpanel_bleCharacteristic.getValueHandle())
{
measure = value_read;
printf("Receive BLE Sunpanel %d mV\n\r", measure);
trigger_Op = WRITE_BUT;
}
}
void myonDataWriteCallback(const GattWriteCallbackParams *response)
{
// Write CLIENT --> SERVER
//printf("myonDataWrite (data[0] %x)\n\r", response->data[0]);
//printf("myonDataWrite (data[1] %x)\n\r\n\r", response->data[1]);
// Return original value after inverted with STORE_LE_16 to send by BLE
value_read = response->data[0] + (response->data[1]<<8);
if (response->handle == userbutton_bleCharacteristic.getValueHandle())
{
printf("\r\n\r\nonDataWrite BUTTON (data %d)\r\n", value_read);
trigger_Op = READ_BUT;
}
if (response->handle == difference_bleCharacteristic.getValueHandle())
{
//printf("onDataWrite DIFF (data %d)\r\n", value_read);
trigger_Op = READ_BUT;
}
}
/**
* This function is called when the ble initialization process has failled
*/
void onBleInitError(BLE &ble, ble_error_t error)
{
/* Initialization error handling should go here */
printf("Inizialization Error\n\r");
}
void connectionCallback(const Gap::ConnectionCallbackParams_t *params)
{
//uint16_t CONTROL_SERVICE_UUID = 0xA000;
//uint16_t USERBUTTON_CHARACTERISTIC_UUID = 0xA001;
//uint16_t SENSORS_SERVICE_UUID = 0xB000;
//uint16_t DIFFERENCE_CHARACTERISTIC_UUID = 0xB001;
//uint16_t POSITION_CHARACTERISTIC_UUID = 0xB002;
//uint16_t SUNPANEL_CHARACTERISTIC_UUID = 0xB003;
if (params->role == Gap::CENTRAL)
{
BLE &ble = BLE::Instance();
ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
// Discover all SERVICES and CHARACTERISTICS
ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback);
// Works only for one characteristic, if you need to discover all characteristic, use the above command
//ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback, CONTROL_SERVICE_UUID, USERBUTTON_CHARACTERISTIC_UUID);
//ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback, SENSORS_SERVICE_UUID, DIFFERENCE_CHARACTERISTIC_UUID);
//ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback, SENSORS_SERVICE_UUID, POSITION_CHARACTERISTIC_UUID);
//ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback, SENSORS_SERVICE_UUID, SUNPANEL_CHARACTERISTIC_UUID);
}
printf("Remote Connected\n\r");
}
void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
{
(void)params;
printf("Remote Disconnected\n\r");
}
/**
* Callback triggered when the ble initialization process has finished
*/
void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
{
BLE& ble = params->ble;
ble_error_t error = params->error;
if (error != BLE_ERROR_NONE)
{
/* In case of error, forward the error handling to onBleInitError */
onBleInitError(ble, error);
return;
}
/* Ensure that it is the default instance of BLE */
if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) { return; }
// Set BT Address
ble.gap().setAddress(BLEProtocol::AddressType::PUBLIC, BLE_address_BE);
ble.gap().onConnection(connectionCallback);
ble.onDisconnection(disconnectionCallback);
ble.gattClient().onDataRead(onDataReadCallback);
ble.gattClient().onDataWrite(myonDataWriteCallback);
ble.gap().setScanParams(SCAN_INT, SCAN_WIND);
ble.gap().startScan(advertisementCallback);
// Main Loop
while (true) {
//if (!ble.gattClient().isServiceDiscoveryActive())
if (trigger_Op!=IDLE) // Wait until discoveryTerminationCallback
{
// At present ARM BLE_API don't support Enable/Disable Notify from Client
//userbutton_bleCharacteristic.notify();
//difference_bleCharacteristic.notify();
//position_bleCharacteristic.notify();
//sunpanel_bleCharacteristic.notify();
// Don't run more ble .read or .write in the same loop
// because the callback is an interrupt and it doesn't work correctly if overloaded
if (display == 0 || display == 1)
{ if (trigger_Op == WRITE_DIF) trigger_Op = READ_BUT; } // if Display 0 or 1, skip WRITE_DIF
if (display == 2)
{ if (trigger_Op == READ_DIF) trigger_Op = WRITE_BUT; } // if Display 2, skip READ_DIF, READ_POS, READ_SUN
switch(trigger_Op)
{
case READ_BUT:
userbutton_bleCharacteristic.read();
trigger_Op = IDLE;
break;
case READ_DIF:
difference_bleCharacteristic.read();
trigger_Op = IDLE;
break;
case READ_POS:
position_bleCharacteristic.read();
trigger_Op = IDLE;
break;
case READ_SUN:
sunpanel_bleCharacteristic.read();
trigger_Op = IDLE;
break;
case WRITE_BUT:
if (trigger_button == true)
{
memset (value_write, 0, SIZEOF_CONTROL_DATA_LEN);
STORE_LE_16(value_write, 1234);
userbutton_bleCharacteristic.write(SIZEOF_CONTROL_DATA_LEN, value_write);
trigger_Op = IDLE;
trigger_button = false;
} else {
#ifdef Sensors
trigger_Op = WRITE_DIF;
#else
trigger_Op = READ_BUT;
#endif
}
break;
case WRITE_DIF:
#ifdef Sensors
accelerometer->Get_X_Axes(acc_data);
acc_diff = acc_data[0];
//printf("Send BLE Difference %d lux/mems\n\r", acc_diff);
memset (value_write_diff, 0, DIFFERENCE_DATA_LEN);
STORE_LE_16(value_write_diff, acc_diff);
difference_bleCharacteristic.write(DIFFERENCE_DATA_LEN, value_write_diff);
trigger_Op = IDLE;
#else
trigger_Op = READ_BUT;
#endif
break;
default:
break;
}
}
ble.waitForEvent();
}
}
/* Ticker --------------------------------------------------------------------*/
/*
void ticker_Callback(void)
{
}
*/
/* Main ----------------------------------------------------------------------*/
int main(void)
{
printf("\r\n\r\nSunTracker Remote Control\r\n\r\n");
#ifdef Sensors
// Initializing Sensors Component
mems=X_NUCLEO_IKS01A1::Instance(&dev_i2c);
accelerometer = mems->GetAccelerometer();
printf("Init Sensors OK\r\n");
#endif
//Ticker ticker;
//ticker.attach(ticker_Callback, 1); // every 1 second
mybutton.fall(&User_Button_Pressed);
BLE::Instance().init(bleInitComplete);
}
