前回 BLE Nanoとスマホでモーターの回転スピード制御するところまで出来ましたので今回は
ステップ2:BLE Nano (Peripheral) – Redbear Duo (Central) のBLE通信でDuoで
モーター供給電圧を指定してBLE Nanoから回転スピードを受信
を実施しました。BLE Nano – Redbear Duoの通信が意外と手こずりましたが。。。
全体概要
部品
BLE Nano
設定方法記事
ワウペダルと加速度センサでBLE制御ラジコン!
続きを見る
Pin配置
Redbear Duo
設定方法記事
ワウペダルと加速度センサでBLE制御ラジコン!
続きを見る
Pin配置
動作
BLE介してRedbear Duoに接続した10kohmボリュームでDCモーター(BLE Nano)への供給電圧を0.5~3.0Vまで変化させ回転スピードを制御してます。
モータの羽(割り箸)付近にフォトリフレクタを配置し回転スピードを計測しBLE NanoからRedbear Duoへスピード値を送信しています。回転スピード[usec]はRedbear Duoを接続したPCに表示されています。
Arduino IDE用コード
Redbear Duo (Central)
以下をベースに生成
#if defined(ARDUINO)
SYSTEM_MODE(SEMI_AUTOMATIC);
#endif
/*
* BLE scan parameters:
* - BLE_SCAN_TYPE
* 0x00: Passive scanning, no scan request packets shall be sent.(default)
* 0x01: Active scanning, scan request packets may be sent.
* 0x02 - 0xFF: Reserved for future use.
* - BLE_SCAN_INTERVAL: This is defined as the time interval from when the Controller started its last LE scan until it begins the subsequent LE scan.
* Range: 0x0004 to 0x4000
* Default: 0x0010 (10 ms)
* Time = N * 0.625 msec
* Time Range: 2.5 msec to 10.24 seconds
* - BLE_SCAN_WINDOW: The duration of the LE scan. The scan window shall be less than or equal to the scan interval.
* Range: 0x0004 to 0x4000
* Default: 0x0010 (10 ms)
* Time = N * 0.625 msec
* Time Range: 2.5 msec to 10240 msec
*/
#define BLE_SCAN_TYPE 0x00 // Passive scanning
#define BLE_SCAN_INTERVAL 0x0060 // 60 ms
#define BLE_SCAN_WINDOW 0x0030 // 30 ms
uint8_t mdVol = 0;
uint16_t mSpeed; //受信モータスピード
/******************************************************
* Type Define
******************************************************/
typedef struct {
uint16_t connected_handle;
uint8_t addr_type;
bd_addr_t addr;
struct {
gatt_client_service_t service;
struct {
gatt_client_characteristic_t chars;
gatt_client_characteristic_descriptor_t descriptor[2]; // User_descriptor and client charactersitc configuration descriptor.
} chars[2];
} service; // Service contains two characteristics and each characteristic contains two descriptors.
} Device_t;
/******************************************************
* Variable Definitions
******************************************************/
// Connect handle.
static uint16_t connected_id = 0xFFFF;
Device_t device;
uint8_t chars_index = 0;
uint8_t desc_index = 0;
// The service uuid to be discovered.
static uint8_t service1_uuid[16] = { 0x71,0x3d,0x00,0x00,0x50,0x3e,0x4c,0x75,0xba,0x94,0x31,0x48,0xf1,0x8d,0x94,0x1e };
static uint8_t gatt_notify_flag = 0;
/******************************************************
* Function Definitions
******************************************************/
/**
* @brief Find the data given the type in advertising data.
*
* @param[in] type The type of field data.
* @param[in] advdata_len Length of advertising data.
* @param[in] *p_advdata The pointer of advertising data.
* @param[out] *len The length of found data.
* @param[out] *p_field_data The pointer of buffer to store field data.
*
* @retval 0 Find the data
* 1 Not find.
*/
uint32_t ble_advdata_decode(uint8_t type, uint8_t advdata_len, uint8_t *p_advdata, uint8_t *len, uint8_t *p_field_data) {
uint8_t index = 0;
uint8_t field_length, field_type;
while (index < advdata_len) {
field_length = p_advdata[index];
field_type = p_advdata[index + 1];
if (field_type == type) {
memcpy(p_field_data, &p_advdata[index + 2], (field_length - 1));
*len = field_length - 1;
return 0;
}
index += field_length + 1;
}
return 1;
}
/**
* @brief Callback for scanning device.
*
* @param[in] *report
*
* @retval None
*/
void reportCallback(advertisementReport_t *report) {
uint8_t index;
Serial.println("reportCallback: ");
Serial.print("The advEventType: ");
Serial.println(report->advEventType, HEX);
Serial.print("The peerAddrType: ");
Serial.println(report->peerAddrType, HEX);
Serial.print("The peerAddr: ");
for (index = 0; index < 6; index++) {
Serial.print(report->peerAddr[index], HEX);
Serial.print(" ");
}
Serial.println(" ");
Serial.print("The rssi: ");
Serial.println(report->rssi, DEC);
Serial.print("The ADV data: ");
for (index = 0; index < report->advDataLen; index++) {
Serial.print(report->advData[index], HEX);
Serial.print(" ");
}
Serial.println(" ");
Serial.println(" ");
uint8_t len;
uint8_t adv_name[31];
// Find short local name.
if (0x00 == ble_advdata_decode(0x08, report->advDataLen, report->advData, &len, adv_name)) {
Serial.print(" The length of Short Local Name : ");
Serial.println(len, HEX);
Serial.print(" The Short Local Name is : ");
Serial.println((const char *)adv_name);
if (0x00 == memcmp(adv_name, "Biscuit", min(7, len))) {
ble.stopScanning();
device.addr_type = report->peerAddrType;
memcpy(device.addr, report->peerAddr, 6);
//ble.connect(report->peerAddr, report->peerAddrType);
//ble.connect(report->peerAddr, BD_ADDR_TYPE_LE_PUBLIC);
ble.connect(report->peerAddr, BD_ADDR_TYPE_LE_RANDOM);
}
}
else if (0x00 == ble_advdata_decode(0x09, report->advDataLen, report->advData, &len, adv_name)) {
Serial.print(" The length of Complete Local Name : ");
Serial.println(len, HEX);
Serial.print(" The Complete Local Name is : ");
Serial.println((const char *)adv_name);
if (0x00 == memcmp(adv_name, "Heart Rate", min(7, len))) {
}
}
}
/**
* @brief Connect handle.
*
* @param[in] status BLE_STATUS_CONNECTION_ERROR or BLE_STATUS_OK.
* @param[in] handle Connect handle.
*
* @retval None
*/
void deviceConnectedCallback(BLEStatus_t status, uint16_t handle) {
RGB.color(0, 60, 25);
switch (status) {
case BLE_STATUS_OK:
Serial.println("Device connected!");
// Connect to remote device, start to discover service.
connected_id = handle;
device.connected_handle = handle;
// Start to discover service, will report result on discoveredServiceCallback.
ble.discoverPrimaryServices(handle);
break;
default: break;
}
}
/**
* @brief Disconnect handle.
*
* @param[in] handle Connect handle.
*
* @retval None
*/
void deviceDisconnectedCallback(uint16_t handle){
RGB.color(100, 0, 0);
Serial.print("Disconnected handle:");
Serial.println(handle,HEX);
if (connected_id == handle) {
Serial.println("Restart scanning.");
// Disconnect from remote device, restart to scanning.
connected_id = 0xFFFF;
ble.startScanning();
}
}
/**
* @brief Callback for handling result of discovering service.
*
* @param[in] status BLE_STATUS_OK/BLE_STATUS_DONE
* @param[in] con_handle
* @param[in] *service Discoverable service.
*
* @retval None
*/
static void discoveredServiceCallback(BLEStatus_t status, uint16_t con_handle, gatt_client_service_t *service) {
uint8_t index;
if (status == BLE_STATUS_OK) { // Found a service.
Serial.println(" ");
Serial.print("Service start handle: ");
Serial.println(service->start_group_handle, HEX);
Serial.print("Service end handle: ");
Serial.println(service->end_group_handle, HEX);
Serial.print("Service uuid16: ");
Serial.println(service->uuid16, HEX);
Serial.print("The uuid128 : ");
for (index = 0; index < 16; index++) {
Serial.print(service->uuid128[index], HEX);
Serial.print(" ");
}
Serial.println(" ");
if (0x00 == memcmp(service->uuid128, service1_uuid, 16)) {
Serial.println("Target uuid128");
device.service.service = *service;
}
}
else if (status == BLE_STATUS_DONE) {
Serial.println("Discovered service done");
// All sevice have been found, start to discover characteristics.
// Result will be reported on discoveredCharsCallback.
ble.discoverCharacteristics(device.connected_handle, &device.service.service);
}
}
/**
* @brief Callback for handling result of discovering characteristic.
*
* @param[in] status BLE_STATUS_OK/BLE_STATUS_DONE
* @param[in] con_handle
* @param[in] *characteristic Discoverable characteristic.
*
* @retval None
*/
static void discoveredCharsCallback(BLEStatus_t status, uint16_t con_handle, gatt_client_characteristic_t *characteristic) {
uint8_t index;
if (status == BLE_STATUS_OK) { // Found a characteristic.
Serial.println(" ");
Serial.print("characteristic start handle: ");
Serial.println(characteristic->start_handle, HEX);
Serial.print("characteristic value handle: ");
Serial.println(characteristic->value_handle, HEX);
Serial.print("characteristic end_handle: ");
Serial.println(characteristic->end_handle, HEX);
Serial.print("characteristic properties: ");
Serial.println(characteristic->properties, HEX);
Serial.print("characteristic uuid16: ");
Serial.println(characteristic->uuid16, HEX);
Serial.print("characteristic uuid128 : ");
for (index = 0; index < 16; index++) {
Serial.print(characteristic->uuid128[index], HEX);
Serial.print(" ");
}
Serial.println(" ");
if (chars_index < 2) {
device.service.chars[chars_index].chars= *characteristic;
chars_index++;
}
}
else if (status == BLE_STATUS_DONE) {
Serial.println("Discovered characteristic done");
chars_index = 0;
// All characteristics have been found, start to discover descriptors.
// Result will be reported on discoveredCharsDescriptorsCallback.
ble.discoverCharacteristicDescriptors(device.connected_handle, &device.service.chars[chars_index].chars);
}
}
/**
* @brief Callback for handling result of discovering descriptor.
*
* @param[in] status BLE_STATUS_OK/BLE_STATUS_DONE
* @param[in] con_handle
* @param[in] *descriptor Discoverable descriptor.
*
* @retval None
*/
static void discoveredCharsDescriptorsCallback(BLEStatus_t status, uint16_t con_handle, gatt_client_characteristic_descriptor_t *descriptor) {
uint8_t index;
if (status == BLE_STATUS_OK) { // Found a descriptor.
Serial.println(" ");
Serial.print("descriptor handle: ");
Serial.println(descriptor->handle, HEX);
Serial.print("descriptor uuid16: ");
Serial.println(descriptor->uuid16, HEX);
Serial.print("descriptor uuid128 : ");
for (index = 0; index < 16; index++) {
Serial.print(descriptor->uuid128[index], HEX);
Serial.print(" ");
}
Serial.println(" ");
if (desc_index < 2) {
device.service.chars[chars_index].descriptor[desc_index++] = *descriptor;
}
}
else if (status == BLE_STATUS_DONE) {
// finish.
Serial.println("Discovered descriptor done");
chars_index++;
if (chars_index < 2) {
desc_index=0;
ble.discoverCharacteristicDescriptors(device.connected_handle, &device.service.chars[chars_index].chars);
}
else { // Read value of characteristic,
// Result will be reported on gattReadCallback.
ble.readValue(device.connected_handle,&device.service.chars[1].chars);
}
}
}
/**
* @brief Callback for handling result of reading.
*
* @param[in] status BLE_STATUS_OK/BLE_STATUS_DONE/BLE_STATUS_OTHER_ERROR
* @param[in] con_handle
* @param[in] value_handle
* @param[in] *value
* @param[in] length
*
* @retval None
*/
void gattReadCallback(BLEStatus_t status, uint16_t con_handle, uint16_t value_handle, uint8_t *value, uint16_t length) {
uint8_t index;
if (status == BLE_STATUS_OK) {
//受信処理
Serial.print("Moter Speed : ");
mSpeed = value[1] << 8 | value[0];
Serial.println(mSpeed);
}
else if (status == BLE_STATUS_DONE) {
//送信
uint8_t data[]= {mdVol};
// Result will be reported on gattWrittenCallback.
// If use ble.writeValueWithoutResponse, will no response.
ble.writeValue(device.connected_handle, device.service.chars[0].chars.value_handle, sizeof(data), data);
}
}
/**
* @brief Callback for handling result of writting.
*
* @param[in] status BLE_STATUS_DONE/BLE_STATUS_OTHER_ERROR
* @param[in] con_handle
*
* @retval None
*/
void gattWrittenCallback(BLEStatus_t status, uint16_t con_handle) {
if (status == BLE_STATUS_DONE) {
//受信
ble.readValue(device.connected_handle,&device.service.chars[1].chars);
}
}
/**
* @brief Callback for handling result of reading descriptor.
*
* @param[in] status BLE_STATUS_DONE/BLE_STATUS_OTHER_ERROR
* @param[in] con_handle
* @param[in] value_handle
* @param[in] *value
* @param[in] length
*
* @retval None
*/
void gattReadDescriptorCallback(BLEStatus_t status, uint16_t con_handle, uint16_t value_handle, uint8_t *value, uint16_t length) {
uint8_t index;
if(status == BLE_STATUS_OK) {
Serial.println(" ");
Serial.println("Read descriptor ok");
Serial.print("conn handle: ");
Serial.println(con_handle, HEX);
Serial.print("value handle: ");
Serial.println(value_handle, HEX);
Serial.print("The value : ");
for (index = 0; index < length; index++) {
Serial.print(value[index], HEX);
Serial.print(" ");
}
Serial.println(" ");
}
else if (status == BLE_STATUS_DONE) {
// Enable notify.
ble.writeClientCharsConfigDescritpor(device.connected_handle, &device.service.chars[0].chars, GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION);
}
}
/**
* @brief Callback for handling result of writting client characteristic configuration.
*
* @param[in] status BLE_STATUS_DONE/BLE_STATUS_OTHER_ERROR
* @param[in] con_handle
*
* @retval None
*/
void gattWriteCCCDCallback(BLEStatus_t status, uint16_t con_handle) {
if (status == BLE_STATUS_DONE) {
Serial.println("gattWriteCCCDCallback done");
if (gatt_notify_flag == 0) {
gatt_notify_flag = 1;
ble.writeClientCharsConfigDescritpor(device.connected_handle, &device.service.chars[1].chars, GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION);
}
else if (gatt_notify_flag == 1) {
gatt_notify_flag = 2;
}
}
}
/**
* @brief Callback for handling notify event from remote device.
*
* @param[in] status BLE_STATUS_OK
* @param[in] con_handle
* @param[in] value_handle
* @param[in] *value
* @param[in] length
*
* @retval None
*/
void gattNotifyUpdateCallback(BLEStatus_t status, uint16_t con_handle, uint16_t value_handle, uint8_t *value, uint16_t length) {
uint8_t index;
Serial.println(" ");
Serial.println("Notify Update value ");
Serial.print("conn handle: ");
Serial.println(con_handle, HEX);
Serial.print("value handle: ");
Serial.println(value_handle, HEX);
Serial.print("The value : ");
for (index = 0; index < length; index++) {
Serial.print(value[index], HEX);
Serial.print(" ");
}
Serial.println(" ");
}
/**
* @brief Setup.
*/
void setup() {
Serial.begin(115200);
delay(5000);
RGB.control(true);
RGB.color(100, 0, 0);
// Open debugger, must befor init().
//ble.debugLogger(true);
//ble.debugError(true);
//ble.enablePacketLogger();
Serial.println("BLE central demo!");
// Initialize ble_stack.
ble.init();
// Register callback functions.
ble.onConnectedCallback(deviceConnectedCallback);
ble.onDisconnectedCallback(deviceDisconnectedCallback);
ble.onScanReportCallback(reportCallback);
ble.onServiceDiscoveredCallback(discoveredServiceCallback);
ble.onCharacteristicDiscoveredCallback(discoveredCharsCallback);
ble.onDescriptorDiscoveredCallback(discoveredCharsDescriptorsCallback);
ble.onGattCharacteristicReadCallback(gattReadCallback);
ble.onGattCharacteristicWrittenCallback(gattWrittenCallback);
ble.onGattDescriptorReadCallback(gattReadDescriptorCallback);
ble.onGattWriteClientCharacteristicConfigCallback(gattWriteCCCDCallback);
ble.onGattNotifyUpdateCallback(gattNotifyUpdateCallback);
// Set scan parameters.
ble.setScanParams(BLE_SCAN_TYPE, BLE_SCAN_INTERVAL, BLE_SCAN_WINDOW);
// Start scanning.
ble.startScanning();
Serial.println("Start scanning ");
}
/**
* @brief Loop.
*/
void loop() {
//10kohm VR アナログ値読み取り
mdVol = map(analogRead(A7), 0, 4096, 0, 27);
//Serial.println(analogRead(A0));
delay(15);
}
BLE Nano (Peripheral)
以下をベースに生成
#include <BLE_API.h>
#include <Wire.h>
#include <QTRSensors.h>
//フォトリフレクタライブラリ https://github.com/pololu/qtr-sensors-arduino
const int DRV8830 = 0x64;
#define NUM_SENSORS 1 // number of sensors used
#define NUM_SAMPLES_PER_SENSOR 1 // average 4 analog samples per sensor reading
#define EMITTER_PIN QTR_NO_EMITTER_PIN // emitter is controlled by digital pin 2
// sensors 0 through 5 are connected to analog inputs 0 through 5, respectively
QTRSensorsAnalog qtra((unsigned char[]) {A4},
NUM_SENSORS, NUM_SAMPLES_PER_SENSOR, EMITTER_PIN);
unsigned int sensorValues[NUM_SENSORS];
unsigned long Time;
int QTRstate = 0;
uint8_t mdVol = 0;
uint16_t mSpeed = 0;
#define DEVICE_NAME "BLE_Peripheral"
#define TXRX_BUF_LEN 20
// Create ble instance
BLE ble;
// The uuid of service and characteristics
static const uint8_t service1_uuid[] = {0x71, 0x3D, 0, 0, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
static const uint8_t service1_chars1_uuid[] = {0x71, 0x3D, 0, 2, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
static const uint8_t service1_chars2_uuid[] = {0x71, 0x3D, 0, 3, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
static const uint8_t service1_chars3_uuid[] = {0x71, 0x3D, 0, 4, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
// Used in advertisement
static const uint8_t uart_base_uuid_rev[] = {0x1E, 0x94, 0x8D, 0xF1, 0x48, 0x31, 0x94, 0xBA, 0x75, 0x4C, 0x3E, 0x50, 0, 0, 0x3D, 0x71};
// Initialize value of chars
uint8_t chars1_value[TXRX_BUF_LEN] = {0};
uint8_t chars2_value[TXRX_BUF_LEN] = {0,};
uint8_t chars3_value[TXRX_BUF_LEN] = {0};
uint8_t tx_value[TXRX_BUF_LEN] = {0,};
// Create characteristic
GattCharacteristic characteristic1(service1_chars1_uuid, chars1_value, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE );
GattCharacteristic characteristic2(service1_chars2_uuid, chars2_value, 2, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
GattCharacteristic characteristic3(service1_chars3_uuid, chars3_value, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
GattCharacteristic *uartChars[] = {&characteristic1, &characteristic2, &characteristic3};
//Create service
GattService uartService(service1_uuid, uartChars, sizeof(uartChars) / sizeof(GattCharacteristic *));
//モータドライバ I2C制御 motor driver I2C
//参考 http://makers-with-myson.blog.so-net.ne.jp/2014-05-15
void writeMotorResister(byte vset, byte data1){
int vdata = vset << 2 | data1;
Wire.beginTransmission(DRV8830);
Wire.write(0x00);
Wire.write(vdata);
Wire.endTransmission(true);
}
HeartRateService *hrService;
DeviceInformationService *deviceInfo;
// Init HRM to 100bps
static uint16_t hrmCounter = 100;
/** @brief Disconnect callback handle
*
* @param[in] *params params->handle : connect handle
* params->reason : CONNECTION_TIMEOUT = 0x08,
* REMOTE_USER_TERMINATED_CONNECTION = 0x13,
* REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES = 0x14, // Remote device terminated connection due to low resources.
* REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF = 0x15, // Remote device terminated connection due to power off.
* LOCAL_HOST_TERMINATED_CONNECTION = 0x16,
* CONN_INTERVAL_UNACCEPTABLE = 0x3B,
*/
void disconnectionCallBack(const Gap::DisconnectionCallbackParams_t *params) {
Serial.print("Disconnected hande : ");
Serial.println(params->handle, HEX);
Serial.print("Disconnected reason : ");
Serial.println(params->reason, HEX);
Serial.println("Restart advertising ");
writeMotorResister(0x00, 0x00);
ble.startAdvertising();
}
/** @brief Connection callback handle
*
* @param[in] *params params->handle : The ID for this connection
* params->role : PERIPHERAL = 0x1, // Peripheral Role
* CENTRAL = 0x2, // Central Role.
* params->peerAddrType : The peer's BLE address type
* params->peerAddr : The peer's BLE address
* params->ownAddrType : This device's BLE address type
* params->ownAddr : This devices's BLE address
* params->connectionParams->minConnectionInterval
* params->connectionParams->maxConnectionInterval
* params->connectionParams->slaveLatency
* params->connectionParams->connectionSupervisionTimeout
*/
void connectionCallBack( const Gap::ConnectionCallbackParams_t *params ) {
uint8_t index;
if(params->role == Gap::PERIPHERAL) {
Serial.println("Peripheral ");
}
Serial.print("The conn handle : ");
Serial.println(params->handle, HEX);
Serial.print("The conn role : ");
Serial.println(params->role, HEX);
Serial.print("The peerAddr type : ");
Serial.println(params->peerAddrType, HEX);
Serial.print(" The peerAddr : ");
for(index=0; index<6; index++) {
Serial.print(params->peerAddr[index], HEX);
Serial.print(" ");
}
Serial.println(" ");
Serial.print("The ownAddr type : ");
Serial.println(params->ownAddrType, HEX);
Serial.print(" The ownAddr : ");
for(index=0; index<6; index++) {
Serial.print(params->ownAddr[index], HEX);
Serial.print(" ");
}
Serial.println(" ");
Serial.print("The min connection interval : ");
Serial.println(params->connectionParams->minConnectionInterval, HEX);
Serial.print("The max connection interval : ");
Serial.println(params->connectionParams->maxConnectionInterval, HEX);
Serial.print("The slaveLatency : ");
Serial.println(params->connectionParams->slaveLatency, HEX);
Serial.print("The connectionSupervisionTimeout : ");
Serial.println(params->connectionParams->connectionSupervisionTimeout, HEX);
}
/** @brief write callback handle of Gatt server
*
* @param[in] *Handler Handler->connHandle : The handle of the connection that triggered the event
* Handler->handle : Attribute Handle to which the write operation applies
* Handler->writeOp : OP_INVALID = 0x00, // Invalid operation.
* OP_WRITE_REQ = 0x01, // Write request.
* OP_WRITE_CMD = 0x02, // Write command.
* OP_SIGN_WRITE_CMD = 0x03, // Signed write command.
* OP_PREP_WRITE_REQ = 0x04, // Prepare write request.
* OP_EXEC_WRITE_REQ_CANCEL = 0x05, // Execute write request: cancel all prepared writes.
* OP_EXEC_WRITE_REQ_NOW = 0x06, // Execute write request: immediately execute all prepared writes.
* Handler->offset : Offset for the write operation
* Handler->len : Length (in bytes) of the data to write
* Handler->data : Pointer to the data to write
*/
//モータドライバ用データ送受信
void gattServerWriteCallBack(const GattWriteCallbackParams *Handler) {
uint8_t index;
uint8_t buf[TXRX_BUF_LEN];
uint16_t bytesRead;
//受信
Serial.print("Write Handle : ");
// Check the attribute belong to which characteristic
if (Handler->handle == characteristic1.getValueAttribute().getHandle()) {
// Read the value of characteristic
ble.readCharacteristicValue(characteristic1.getValueAttribute().getHandle(), buf, &bytesRead);
mdVol = buf[0];
Serial.println(mdVol, DEC);
}
//送信
ble.updateCharacteristicValue(characteristic2.getValueAttribute().getHandle(), (uint8_t *)&mSpeed, 2);
}
/**
* @brief Set advertisement
*/
void setAdvertisement(void) {
// A list of Advertising Data types commonly used by peripherals.
// FLAGS = 0x01, // Flags, refer to GapAdvertisingData::Flags_t.
// INCOMPLETE_LIST_16BIT_SERVICE_IDS = 0x02, // Incomplete list of 16-bit Service IDs.
// COMPLETE_LIST_16BIT_SERVICE_IDS = 0x03, // Complete list of 16-bit Service IDs.
// INCOMPLETE_LIST_32BIT_SERVICE_IDS = 0x04, // Incomplete list of 32-bit Service IDs (not relevant for Bluetooth 4.0).
// COMPLETE_LIST_32BIT_SERVICE_IDS = 0x05, // Complete list of 32-bit Service IDs (not relevant for Bluetooth 4.0).
// INCOMPLETE_LIST_128BIT_SERVICE_IDS = 0x06, // Incomplete list of 128-bit Service IDs.
// COMPLETE_LIST_128BIT_SERVICE_IDS = 0x07, // Complete list of 128-bit Service IDs.
// SHORTENED_LOCAL_NAME = 0x08, // Shortened Local Name.
// COMPLETE_LOCAL_NAME = 0x09, // Complete Local Name.
// TX_POWER_LEVEL = 0x0A, // TX Power Level (in dBm).
// DEVICE_ID = 0x10, // Device ID.
// SLAVE_CONNECTION_INTERVAL_RANGE = 0x12, // Slave Connection Interval Range.
// LIST_128BIT_SOLICITATION_IDS = 0x15, // List of 128 bit service UUIDs the device is looking for.
// SERVICE_DATA = 0x16, // Service Data.
// APPEARANCE = 0x19, // Appearance, refer to GapAdvertisingData::Appearance_t.
// ADVERTISING_INTERVAL = 0x1A, // Advertising Interval.
// MANUFACTURER_SPECIFIC_DATA = 0xFF // Manufacturer Specific Data.
// AD_Type_Flag : LE_LIMITED_DISCOVERABLE = 0x01, Peripheral device is discoverable for a limited period of time
// LE_GENERAL_DISCOVERABLE = 0x02, Peripheral device is discoverable at any moment
// BREDR_NOT_SUPPORTED = 0x03, Peripheral device is LE only
// SIMULTANEOUS_LE_BREDR_C = 0x04, Not relevant - central mode only
// SIMULTANEOUS_LE_BREDR_H = 0x05, Not relevant - central mode only
ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
// Add short name to advertisement
ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,(const uint8_t *)"Biscuit", 7);
// Add complete 128bit_uuid to advertisement
ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,(const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid_rev));
// Add complete device name to scan response data
ble.accumulateScanResponse(GapAdvertisingData::COMPLETE_LOCAL_NAME,(const uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME) - 1);
}
void setup() {
// put your setup code here, to run once
Serial.begin(9600);
Wire.begin(D3, D2, 400000L);
writeMotorResister(0x00, 0x00);
Serial.println("Start ");
pinMode(D13, OUTPUT);
ble.init();
ble.onConnection(connectionCallBack);
ble.onDisconnection(disconnectionCallBack);
ble.onDataWritten(gattServerWriteCallBack);
// set advertisement
setAdvertisement();
// set adv_type(enum from 0)
// ADV_CONNECTABLE_UNDIRECTED
// ADV_CONNECTABLE_DIRECTED
// ADV_SCANNABLE_UNDIRECTED
// ADV_NON_CONNECTABLE_UNDIRECTED
ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
// add service
hrService = new HeartRateService(ble, hrmCounter, HeartRateService::LOCATION_FINGER);
deviceInfo = new DeviceInformationService(ble, "ARM", "Model1", "SN1", "hw-rev1", "fw-rev1", "soft-rev1");
ble.addService(uartService);
// set device name
ble.setDeviceName((const uint8_t *)DEVICE_NAME);
// set tx power,valid values are -40, -20, -16, -12, -8, -4, 0, 4
ble.setTxPower(4);
// set adv_interval, 100ms in multiples of 0.625ms.
ble.setAdvertisingInterval(160);
// set adv_timeout, in seconds
ble.setAdvertisingTimeout(0);
// ger BLE stack version
Serial.print("BLE stack verison is : ");
Serial.println(ble.getVersion());
// start advertising
ble.startAdvertising();
Serial.println("start advertising ");
}
void loop() {
//モータードライバ電圧指定
if(mdVol < 6){
writeMotorResister(0x00, 0x00);
}else {
writeMotorResister((byte)mdVol, 0x01);
}
//フォトリフレクタ処理
// read raw sensor values
qtra.read(sensorValues);
if(sensorValues[0] < 900 && QTRstate == 0){
QTRstate = 1;
mSpeed = micros()-Time;
Time = micros();
}
if(sensorValues[0] > 920 && QTRstate == 1){
QTRstate = 0;
}
}
まとめ
デバイス同士の通信が確認できて一安心。
以下直近の実施予定項目です。
ステップ3:Redbear DuoでLED(Dotstar)制御確認
ステップ4:スマホ – Redbear Duo でLED色・回転速度WiFi制御
ステップ5:POV基本動作確認
まだまだコレ↓を実現するには時間かかりそう。。。
次の記事
Redbear DuoでDotstarを制御 -球体POV製作への道 その5-
続きを見る