From 8455f044db290f90670afce34e0c7781d6e649a5 Mon Sep 17 00:00:00 2001 From: EmbeddedMan Date: Sun, 19 Nov 2017 09:39:41 -0600 Subject: [PATCH 1/9] * enterCommandMode() now properly handles situation where module has prompt turned on or off * Library now keeps track of if it is in command mode or not * Added function setOperationMode() * Added startCustomAdvertising() function * Added support for PIC32 (chipKIT) * Moved reset and wake pin definitions into hwInit() so that different boards can be supported without editing library --- Readme.md | 37 +- library.properties | 8 +- src/RN487x_BLE.cpp | 1139 +++++++++++++++++++++++++------------------- src/RN487x_BLE.h | 190 ++++---- src/RN487x_CONST.h | 3 +- 5 files changed, 783 insertions(+), 594 deletions(-) diff --git a/Readme.md b/Readme.md index 79bd508..75e66e4 100644 --- a/Readme.md +++ b/Readme.md @@ -2,6 +2,8 @@ Arduino library for using the Microchip RN487x BLE module. +Updated to work with chipKIT boards. + ## Usage Quick example: @@ -10,21 +12,23 @@ Quick example: #include "RN487x_BLE.h" #define bleSerial Serial1 +#define BT_RESET 7 +#define BLUETOOTH_WAKE 12 void setup() { - rn487xBle.hwInit() ; - bleSerial.begin(rn487xBle.getDefaultBaudRate()) ; - rn487xBle.initBleStream(&bleSerial) ; - if (rn487xBle.swInit()) - { - rn487xBle.enterCommandMode() ; - rn487xBle.stopAdvertising() ; - rn487xBle.setAdvPower(3) ; - rn487xBle.setSerializedName("Microchip") ; - rn487xBle.clearAllServices() ; - rn487xBle.reboot() ; - } + rn487xBle.hwInit(BT_RESET, BLUETOOTH_WAKE); + bleSerial.begin(rn487xBle.getDefaultBaudRate()); + rn487xBle.initBleStream(&bleSerial); + if (rn487xBle.swInit()) + { + rn487xBle.enterCommandMode(); + rn487xBle.stopAdvertising(); + rn487xBle.setAdvPower(3); + rn487xBle.setSerializedName("Microchip"); + rn487xBle.clearAllServices(); + rn487xBle.reboot(); + } } void loop() @@ -41,6 +45,15 @@ void loop() v1.0.0 Initial Release +v1.1.0 Release +* enterCommandMode() now properly handles situation where module has prompt turned on or off +* Library now keeps track of if it is in command mode or not +* Added function setOperationMode() +* Added startCustomAdvertising() function +* Added support for PIC32 (chipKIT) +* Moved reset and wake pin definitions into hwInit() so that different boards can be supported without editing library + + ## License (c) 2016 Microchip Technology Inc. and its subsidiaries. You may use this diff --git a/library.properties b/library.properties index 8fa2766..fbdcbac 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=Microchip_RN487x -version=1.0.0 +version=1.1.0 author=M16946,Microchip Technology (c) -maintainer=M16946 +maintainer=Brian Schmalz sentence=An Arduino library for the Microchip RN487x -paragraph=It supports to enable BLE communication. +paragraph=Command mode support for NR487x BLE modules from Microchip. Updated to work with chipKIT boards. category=Communication -url=https://github.com/SodaqMoja/Microchip_RN487x +url=https://github.com/chipKIT32-libraries/Microchip_RN487x architectures=* diff --git a/src/RN487x_BLE.cpp b/src/RN487x_BLE.cpp index 943fd98..7ae42a9 100644 --- a/src/RN487x_BLE.cpp +++ b/src/RN487x_BLE.cpp @@ -28,22 +28,11 @@ #include #include -#if defined(ARDUINO_SODAQ_ONE) - #define BLUETOOTH_WAKE (26u) // A6/D6 - #define BT_RESET (24u) //A2/D2 -#endif - -// Bluetooth Reset signal is supported from the BSP version SODAQ_SAMD_BOARD_1.6.10 -// Redefine the pin in case of using prior version than v1.6.9 -#ifndef BT_RESET - #define BT_RESET (46u) -#endif - //#define DEBUG #ifdef DEBUG -#define debugPrintLn(...) { if (this->diagStream) this->diagStream->println(__VA_ARGS__) ; } -#define debugPrint(...) { if (this->diagStream) this->diagStream->print(__VA_ARGS__) ; } +#define debugPrintLn(...) { if (this->diagStream) this->diagStream->println(__VA_ARGS__); } +#define debugPrint(...) { if (this->diagStream) this->diagStream->print(__VA_ARGS__); } #warning "Debug mode is ON" #else #define debugPrintLn(...) @@ -52,7 +41,7 @@ // ---------------------------------------- Private section ---------------------------------------- -Rn487xBle rn487xBle ; +Rn487xBle rn487xBle; // ********************************************************************************* // Constructor @@ -62,9 +51,9 @@ Rn487xBle rn487xBle ; // ********************************************************************************* Rn487xBle::Rn487xBle(void) { - uartBufferLen = DEFAULT_INPUT_BUFFER_SIZE ; - uartBuffer = new char[uartBufferLen] ; - memset(uartBuffer, 0, uartBufferLen) ; + uartBufferLen = DEFAULT_INPUT_BUFFER_SIZE; + uartBuffer = new char[uartBufferLen]; + memset(uartBuffer, 0, uartBufferLen); } // ********************************************************************************* @@ -77,8 +66,8 @@ Rn487xBle::~Rn487xBle() { if (uartBuffer != NULL) { - delete []uartBuffer ; - uartBuffer = NULL ; + delete []uartBuffer; + uartBuffer = NULL; } } @@ -90,13 +79,41 @@ Rn487xBle::~Rn487xBle() // ********************************************************************************* void Rn487xBle::hwInit(void) { - debugPrintLn("[hwInit]") ; + debugPrintLn("[hwInit]"); + + wakePin = -1; + resetPin = -1; + + // Hardware reset + hwReset(); + + // Place the 'wakePin' pin in Low level + hwWakeUp(); +} + +// ********************************************************************************* +// Hardware Init. procedure +// ********************************************************************************* +// Input : uint8_t resetBLEPin - the digital I/O pin number connected to the BLE +// module's reset pin. Use -1 to disable +// library's reset of BLE module +// Input : uint8_t wakeBLEPin - the digital I/O pin number connected to the BLE +// module's wake pin. Use -1 to disable library's +// use of wake pin +// Output: void +// ********************************************************************************* +void Rn487xBle::hwInit(uint8_t resetBLEPin, uint8_t wakeBLEPin) +{ + debugPrintLn("[hwInit]"); + wakePin = wakeBLEPin; + resetPin = resetBLEPin; + // Hardware reset - hwReset() ; + hwReset(); - // Place the BLUETOOTH_WAKE pin in Low level - hwWakeUp() ; + // Place the 'wakePin' pin in Low level + hwWakeUp(); } // ********************************************************************************* @@ -107,15 +124,15 @@ void Rn487xBle::hwInit(void) // ********************************************************************************* bool Rn487xBle::swInit(void) { - debugPrintLn("[swInit]") ; + debugPrintLn("[swInit]"); - bool initOk = false ; + bool initOk = false; if (reboot()) { // Set a known mode - setOperationMode(dataMode) ; - initOk = true ; + setOperationMode(dataMode); + initOk = true; } else { @@ -124,12 +141,12 @@ bool Rn487xBle::swInit(void) if (reboot()) { // Set a known mode - setOperationMode(dataMode) ; - initOk = true ; + setOperationMode(dataMode); + initOk = true; } } } - return initOk ; + return initOk; } // ********************************************************************************* @@ -142,13 +159,20 @@ bool Rn487xBle::swInit(void) // ********************************************************************************* void Rn487xBle::hwReset(void) { - debugPrintLn("[hwReset]") ; + if (resetPin != -1) + { + debugPrintLn("[hwReset]"); - pinMode(BT_RESET, OUTPUT) ; - digitalWrite(BT_RESET, LOW) ; - delay(1) ; - digitalWrite(BT_RESET, HIGH) ; - delay(500) ; + pinMode(resetPin, OUTPUT); + digitalWrite(resetPin, LOW); + delay(1); + digitalWrite(resetPin, HIGH); + delay(500); + } + else + { + debugPrintLn("[hwReset skipped]"); + } } // ********************************************************************************* @@ -161,11 +185,17 @@ void Rn487xBle::hwReset(void) // ********************************************************************************* void Rn487xBle::hwWakeUp(void) { - debugPrintLn("[wakeUp]") ; - - pinMode(BLUETOOTH_WAKE, OUTPUT) ; - digitalWrite(BLUETOOTH_WAKE, LOW) ; - delay(5) ; + if (wakePin != -1) + { + debugPrintLn("[wakeUp]"); + pinMode(wakePin, OUTPUT); + digitalWrite(wakePin, LOW); + delay(5); + } + else + { + debugPrintLn("[wakeUp - skipped]"); + } } // ********************************************************************************* @@ -178,11 +208,18 @@ void Rn487xBle::hwWakeUp(void) // ********************************************************************************* void Rn487xBle::hwSleep(void) { - debugPrintLn("[sleep]") ; + if (wakePin != -1) + { + debugPrintLn("[sleep]"); - pinMode(BLUETOOTH_WAKE, OUTPUT) ; - digitalWrite(BLUETOOTH_WAKE, HIGH) ; - delay(1) ; + pinMode(wakePin, OUTPUT); + digitalWrite(wakePin, HIGH); + delay(1); + } + else + { + debugPrintLn("[sleep - skipped]"); + } } @@ -195,18 +232,49 @@ void Rn487xBle::hwSleep(void) // ********************************************************************************* bool Rn487xBle::enterCommandMode(void) { - debugPrintLn("[enterCommandMode]") ; + debugPrintLn("[enterCommandMode]"); // To enter Command mode from Data mode, type $$$ character sequence after 100 ms delay before the first $ - delay(DELAY_BEFORE_CMD) ; + delay(DELAY_BEFORE_CMD); + + memset(uartBuffer, 0, uartBufferLen); // clear the buffer + cleanInputBuffer(); + + this->bleSerial->print(ENTER_CMD); + + // This command will reply with either "CMD> " or "CMD" depending on if + // the command prompt is turned on or off. This routine needs to detect which + // reply comes back, and set the commandPromptEnabled variable appropriately. This + // reply takes less than 15ms to arrive. Each string is 5 bytes long. + + debugPrintLn("[expectResponse] expecting CMD> or CMD"); - this->bleSerial->print(ENTER_CMD) ; - if (expectResponse(PROMPT, DEFAULT_CMD_TIMEOUT)) + unsigned long previous = millis(); + + while ((millis() - previous < 15) && (this->bleSerial->available() < 5)) { - setOperationMode(cmdMode) ; - return true ; + debugPrint("."); } - return false ; + + this->bleSerial->readBytes(this->uartBuffer, this->bleSerial->available()); + + debugPrint("("); + debugPrint(this->uartBuffer); + debugPrint(")"); + + if (strstr(this->uartBuffer, PROMPT) != NULL) + { + debugPrintLn(" found a match ! - Command prompts are enabled."); + setOperationMode(cmdMode); + return true; + } + else if (strstr(this->uartBuffer, PROMPT_CR) != NULL) + { + debugPrintLn(" found a match ! - Command prompts are disabled."); + setOperationMode(cmdMode); + return true; + } + return false; } // ********************************************************************************* @@ -222,15 +290,15 @@ bool Rn487xBle::enterCommandMode(void) // ********************************************************************************* bool Rn487xBle::enterDataMode(void) { - debugPrintLn("[enterDataMode]") ; + debugPrintLn("[enterDataMode]"); - sendCommand(EXIT_CMD) ; + sendCommand(EXIT_CMD); if (expectResponse(PROMPT_END, DEFAULT_CMD_TIMEOUT)) { - setOperationMode(dataMode) ; - return true ; + setOperationMode(dataMode); + return true; } - return false ; + return false; } // ********************************************************************************* @@ -247,18 +315,18 @@ bool Rn487xBle::enterDataMode(void) // ********************************************************************************* void Rn487xBle::sendCommand(String stream) { - debugPrint("[sendCommand] " ) ; - debugPrintLn(stream) ; + debugPrint("[sendCommand] " ); + debugPrintLn(stream); - this->flush() ; - cleanInputBuffer() ; - stream.concat(CR) ; - bleSerial->print(stream) ; + this->flush(); + cleanInputBuffer(); + stream.concat(CR); + bleSerial->print(stream); } void Rn487xBle::sendData(char *data, uint16_t dataLen) { - bleSerial->write(data, dataLen) ; + bleSerial->write(data, dataLen); } @@ -272,21 +340,21 @@ bool Rn487xBle::retrieveBtAddress(void) { if (getSettings(0, 6)) { - btAddress[0] = uartBuffer[10] ; - btAddress[1] = uartBuffer[11] ; - btAddress[2] = uartBuffer[8] ; - btAddress[3] = uartBuffer[9] ; - btAddress[4] = uartBuffer[6] ; - btAddress[5] = uartBuffer[7] ; - btAddress[6] = uartBuffer[4] ; - btAddress[7] = uartBuffer[5] ; - btAddress[8] = uartBuffer[2] ; - btAddress[9] = uartBuffer[3] ; - btAddress[10]= uartBuffer[0] ; - btAddress[11]= uartBuffer[1] ; - return true ; + btAddress[0] = uartBuffer[10]; + btAddress[1] = uartBuffer[11]; + btAddress[2] = uartBuffer[8]; + btAddress[3] = uartBuffer[9]; + btAddress[4] = uartBuffer[6]; + btAddress[5] = uartBuffer[7]; + btAddress[6] = uartBuffer[4]; + btAddress[7] = uartBuffer[5]; + btAddress[8] = uartBuffer[2]; + btAddress[9] = uartBuffer[3]; + btAddress[10]= uartBuffer[0]; + btAddress[11]= uartBuffer[1]; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -297,25 +365,25 @@ bool Rn487xBle::retrieveBtAddress(void) // ********************************************************************************* bool Rn487xBle::getFirmwareVersion(void) { - debugPrint("[getFirmwareVersion]") ; + debugPrint("[getFirmwareVersion]"); - uint16_t timeout = DEFAULT_CMD_TIMEOUT ; - unsigned long previous ; + uint16_t timeout = DEFAULT_CMD_TIMEOUT; + unsigned long previous; - sendCommand(DISPLAY_FW_VERSION) ; - previous = millis() ; + sendCommand(DISPLAY_FW_VERSION); + previous = millis(); while (millis() - previous < timeout) { - debugPrint(".") ; + debugPrint("."); if (this->bleSerial->available() > 0) { if (readUntilCR() > 0) { - return true ; + return true; } } } - return false ; + return false; } // ********************************************************************************* @@ -326,8 +394,8 @@ bool Rn487xBle::getFirmwareVersion(void) // ********************************************************************************* bool Rn487xBle::disableBeacon(void) { - debugPrintLn("[disableBeacon]") ; - return(setBeaconFeatures(BEACON_OFF)) ; + debugPrintLn("[disableBeacon]"); + return(setBeaconFeatures(BEACON_OFF)); } // ********************************************************************************* @@ -338,8 +406,8 @@ bool Rn487xBle::disableBeacon(void) // ********************************************************************************* bool Rn487xBle::enableBeacon(void) { - debugPrintLn("[enableBeacon]") ; - return(setBeaconFeatures(BEACON_ON)) ; + debugPrintLn("[enableBeacon]"); + return(setBeaconFeatures(BEACON_ON)); } // ********************************************************************************* @@ -350,8 +418,8 @@ bool Rn487xBle::enableBeacon(void) // ********************************************************************************* bool Rn487xBle::enableBeaconAndAdv(void) { - debugPrintLn("[enableBeaconAndAdv]") ; - return(setBeaconFeatures(BEACON_ADV_ON)) ; + debugPrintLn("[enableBeaconAndAdv]"); + return(setBeaconFeatures(BEACON_ADV_ON)); } // ********************************************************************************* @@ -364,14 +432,14 @@ bool Rn487xBle::enableBeaconAndAdv(void) // ********************************************************************************* bool Rn487xBle::factoryReset(void) { - debugPrintLn("[factoryReset]") ; + debugPrintLn("[factoryReset]"); - sendCommand(FACTORY_RESET) ; + sendCommand(FACTORY_RESET); if (expectResponse(FACTORY_RESET_RESP, RESET_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -384,23 +452,32 @@ bool Rn487xBle::factoryReset(void) // ********************************************************************************* bool Rn487xBle::setAdvPower(uint8_t value) { - debugPrint("[setAdvPower] ") ; debugPrintLn(value) ; - - if (value < MIN_POWER_OUTPUT) value = MIN_POWER_OUTPUT ; - if (value > MAX_POWER_OUTPUT) value = MAX_POWER_OUTPUT ; - - uint8_t len = strlen(SET_ADV_POWER) ; - char c[1] ; - sprintf(c, "%d", value) ; - this->flush() ; - memcpy(uartBuffer, SET_ADV_POWER, len) ; - memcpy(&uartBuffer[len], c, 1) ; - sendCommand(uartBuffer) ; + debugPrint("[setAdvPower] "); + debugPrintLn(value); + +#if (MIN_POWER_OUTPUT != 0) + if (value < MIN_POWER_OUTPUT) + { + value = MIN_POWER_OUTPUT; + } +#endif + if (value > MAX_POWER_OUTPUT) + { + value = MAX_POWER_OUTPUT; + } + + uint8_t len = strlen(SET_ADV_POWER); + char c[1]; + sprintf(c, "%d", value); + this->flush(); + memcpy(uartBuffer, SET_ADV_POWER, len); + memcpy(&uartBuffer[len], c, 1); + sendCommand(uartBuffer); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -413,23 +490,32 @@ bool Rn487xBle::setAdvPower(uint8_t value) // ********************************************************************************* bool Rn487xBle::setConPower(uint8_t value) { - debugPrint("[setConnPower] ") ; debugPrintLn(value) ; + debugPrint("[setConnPower] "); + debugPrintLn(value); - if (value < MIN_POWER_OUTPUT) value = MIN_POWER_OUTPUT ; - if (value > MAX_POWER_OUTPUT) value = MAX_POWER_OUTPUT ; +#if (MIN_POWER_OUTPUT != 0) + if (value < MIN_POWER_OUTPUT) + { + value = MIN_POWER_OUTPUT; + } +#endif + if (value > MAX_POWER_OUTPUT) + { + value = MAX_POWER_OUTPUT; + } - uint8_t len = strlen(SET_CONN_POWER) ; - char c[1] ; - sprintf(c, "%d", value) ; - this->flush() ; - memcpy(uartBuffer, SET_CONN_POWER, len) ; - memcpy(&uartBuffer[len], c, 1) ; - sendCommand(uartBuffer) ; + uint8_t len = strlen(SET_CONN_POWER); + char c[1]; + sprintf(c, "%d", value); + this->flush(); + memcpy(uartBuffer, SET_CONN_POWER, len); + memcpy(&uartBuffer[len], c, 1); + sendCommand(uartBuffer); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -444,30 +530,30 @@ bool Rn487xBle::setConPower(uint8_t value) // ********************************************************************************* bool Rn487xBle::setSerializedName(const char *newName) { - debugPrint("[setSerializedName] ") ; - debugPrintLn(newName) ; + debugPrint("[setSerializedName] "); + debugPrintLn(newName); - uint8_t len = strlen(SET_SERIALIZED_NAME) ; - uint8_t newLen = strlen(newName) ; + uint8_t len = strlen(SET_SERIALIZED_NAME); + uint8_t newLen = strlen(newName); if (newLen > MAX_SERIALIZED_NAME_LEN) { - newLen = MAX_SERIALIZED_NAME_LEN ; - debugPrintLn(" Too many characters") ; + newLen = MAX_SERIALIZED_NAME_LEN; + debugPrintLn(" Too many characters"); } // Fill the device name without the last two bytes of the Bluetooth MAC address - memset(deviceName, 0, newLen) ; - memcpy(deviceName, newName, newLen) ; + memset(deviceName, 0, newLen); + memcpy(deviceName, newName, newLen); // Fill the buffer - this->flush() ; - memcpy(uartBuffer, SET_SERIALIZED_NAME, len) ; - memcpy(&uartBuffer[len], newName, newLen) ; - sendCommand(uartBuffer) ; + this->flush(); + memcpy(uartBuffer, SET_SERIALIZED_NAME, len); + memcpy(&uartBuffer[len], newName, newLen); + sendCommand(uartBuffer); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -479,30 +565,30 @@ bool Rn487xBle::setSerializedName(const char *newName) // ********************************************************************************* bool Rn487xBle::setDevName(const char *newName) { - debugPrint("[setDeviceName] ") ; - debugPrintLn(newName) ; + debugPrint("[setDeviceName] "); + debugPrintLn(newName); - uint8_t len = strlen(SET_DEVICE_NAME) ; - uint8_t newLen = strlen(newName) ; + uint8_t len = strlen(SET_DEVICE_NAME); + uint8_t newLen = strlen(newName); if (newLen > MAX_DEVICE_NAME_LEN) { - newLen = MAX_DEVICE_NAME_LEN ; - debugPrintLn(" Too many characters") ; + newLen = MAX_DEVICE_NAME_LEN; + debugPrintLn(" Too many characters"); } // Fill the device name - memset(deviceName, 0, newLen) ; - memcpy(deviceName, newName, newLen) ; + memset(deviceName, 0, newLen); + memcpy(deviceName, newName, newLen); // Fill the buffer - this->flush() ; - memcpy(uartBuffer, SET_DEVICE_NAME, len) ; - memcpy(&uartBuffer[len], newName, newLen) ; - sendCommand(uartBuffer) ; + this->flush(); + memcpy(uartBuffer, SET_DEVICE_NAME, len); + memcpy(&uartBuffer[len], newName, newLen); + sendCommand(uartBuffer); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -518,14 +604,14 @@ bool Rn487xBle::setDevName(const char *newName) // ********************************************************************************* bool Rn487xBle::enableLowPower(void) { - debugPrintLn("[enableLowPower]") ; + debugPrintLn("[enableLowPower]"); - sendCommand(SET_LOW_POWER_ON) ; + sendCommand(SET_LOW_POWER_ON); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -537,14 +623,14 @@ bool Rn487xBle::enableLowPower(void) // ********************************************************************************* bool Rn487xBle::disableLowPower(void) { - debugPrintLn("[disableLowPower]") ; + debugPrintLn("[disableLowPower]"); - sendCommand(SET_LOW_POWER_OFF) ; + sendCommand(SET_LOW_POWER_OFF); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -556,22 +642,22 @@ bool Rn487xBle::disableLowPower(void) // ********************************************************************************* bool Rn487xBle::setSupportedFeatures(uint16_t bitmap) { - debugPrint("[setSupportedFeatures]") ; + debugPrint("[setSupportedFeatures]"); - uint8_t len = strlen(SET_SUPPORTED_FEATURES) ; - char c[4] ; - sprintf(c, "%04X", bitmap) ; - uint8_t newLen = strlen(c) ; + uint8_t len = strlen(SET_SUPPORTED_FEATURES); + char c[4]; + sprintf(c, "%04X", bitmap); + uint8_t newLen = strlen(c); - this->flush() ; - memcpy(uartBuffer, SET_SUPPORTED_FEATURES, len) ; - memcpy(&uartBuffer[len], c, newLen) ; - sendCommand(uartBuffer) ; + this->flush(); + memcpy(uartBuffer, SET_SUPPORTED_FEATURES, len); + memcpy(&uartBuffer[len], c, newLen); + sendCommand(uartBuffer); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -586,23 +672,23 @@ bool Rn487xBle::setSupportedFeatures(uint16_t bitmap) // ********************************************************************************* bool Rn487xBle::setDefaultServices(uint8_t bitmap) { - debugPrint("[setDefaultServices]") ; + debugPrint("[setDefaultServices]"); - uint8_t len = strlen(SET_DEFAULT_SERVICES) ; - char c[2] ; - sprintf(c, "%02X", bitmap) ; - uint8_t newLen = strlen(c) ; + uint8_t len = strlen(SET_DEFAULT_SERVICES); + char c[2]; + sprintf(c, "%02X", bitmap); + uint8_t newLen = strlen(c); - this->flush() ; - memcpy(uartBuffer, SET_DEFAULT_SERVICES, len) ; - memcpy(&uartBuffer[len], c, newLen) ; + this->flush(); + memcpy(uartBuffer, SET_DEFAULT_SERVICES, len); + memcpy(&uartBuffer[len], c, newLen); - sendCommand(uartBuffer) ; + sendCommand(uartBuffer); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -615,14 +701,14 @@ bool Rn487xBle::setDefaultServices(uint8_t bitmap) // ********************************************************************************* bool Rn487xBle::clearAllServices(void) { - debugPrintLn("[cleanAllServices]") ; + debugPrintLn("[cleanAllServices]"); - sendCommand(CLEAR_ALL_SERVICES) ; + sendCommand(CLEAR_ALL_SERVICES); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -634,14 +720,75 @@ bool Rn487xBle::clearAllServices(void) // ********************************************************************************* bool Rn487xBle::startAdvertising(void) { - debugPrintLn("[startAdvertising]") ; + debugPrintLn("[startAdvertising]"); - sendCommand(START_DEFAULT_ADV) ; + sendCommand(START_DEFAULT_ADV); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; +} + +// ********************************************************************************* +// Start Custom Advertisement +// ********************************************************************************* +// The advertisement is undirect connectable. (note, with no second parameter, this +// function will use the form of the START_CUSTOM_ADV command where no second +// parameter is sent, thus making advertisements last forever) +// Input : interval - the number of milliseconds between advertisements +// Output: bool true if successfully executed +// ********************************************************************************* +bool Rn487xBle::startCustomAdvertising(uint16_t interval) +{ + debugPrintLn("[startCustomAdvertising]"); + + uint8_t len = strlen(START_CUSTOM_ADV); + char parameters[5]; + sprintf(parameters, "%04X", interval); + uint8_t newLen = strlen(parameters); + + this->flush(); + memcpy(uartBuffer, START_CUSTOM_ADV, len); + memcpy(&uartBuffer[len], parameters, newLen); + + sendCommand(uartBuffer); + + if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) + { + return true; + } + return false; +} + +// ********************************************************************************* +// Start Custom Advertisement +// ********************************************************************************* +// The advertisement is undirect connectable. +// Input : interval - the number of milliseconds between advertisements +// Input : totalAdTime - the number of 640ms ticks until advertisements stop +// Output: bool true if successfully executed +// ********************************************************************************* +bool Rn487xBle::startCustomAdvertising(uint16_t interval, uint16_t totalAdTime) +{ + debugPrintLn("[startCustomAdvertising]"); + + uint8_t len = strlen(START_CUSTOM_ADV); + char parameters[10]; + sprintf(parameters, "%04X,%04X", interval, totalAdTime); + uint8_t newLen = strlen(parameters); + + this->flush(); + memcpy(uartBuffer, START_CUSTOM_ADV, len); + memcpy(&uartBuffer[len], parameters, newLen); + + sendCommand(uartBuffer); + + if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) + { + return true; + } + return false; } // ********************************************************************************* @@ -653,14 +800,14 @@ bool Rn487xBle::startAdvertising(void) // ********************************************************************************* bool Rn487xBle::stopAdvertising(void) { - debugPrintLn("[stopAdvertising]") ; + debugPrintLn("[stopAdvertising]"); - sendCommand(STOP_ADV) ; + sendCommand(STOP_ADV); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -672,14 +819,14 @@ bool Rn487xBle::stopAdvertising(void) // ********************************************************************************* bool Rn487xBle::clearImmediateAdvertising(void) { - debugPrintLn("[clearImmediateAdvertising]") ; + debugPrintLn("[clearImmediateAdvertising]"); - sendCommand(CLEAR_IMMEDIATE_ADV) ; + sendCommand(CLEAR_IMMEDIATE_ADV); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -692,14 +839,14 @@ bool Rn487xBle::clearImmediateAdvertising(void) // ********************************************************************************* bool Rn487xBle::clearPermanentAdvertising(void) { - debugPrintLn("[clearPermanentAdvertising]") ; + debugPrintLn("[clearPermanentAdvertising]"); - sendCommand(CLEAR_PERMANENT_ADV) ; + sendCommand(CLEAR_PERMANENT_ADV); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -711,14 +858,14 @@ bool Rn487xBle::clearPermanentAdvertising(void) // ********************************************************************************* bool Rn487xBle::clearImmediateBeacon(void) { - debugPrintLn("[clearImmediateBeacon]") ; + debugPrintLn("[clearImmediateBeacon]"); - sendCommand(CLEAR_IMMEDIATE_BEACON) ; + sendCommand(CLEAR_IMMEDIATE_BEACON); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } @@ -732,14 +879,14 @@ bool Rn487xBle::clearImmediateBeacon(void) // ********************************************************************************* bool Rn487xBle::clearPermanentBeacon(void) { - debugPrintLn("[clearPermanentBeacon]") ; + debugPrintLn("[clearPermanentBeacon]"); - sendCommand(CLEAR_PERMANENT_BEACON) ; + sendCommand(CLEAR_PERMANENT_BEACON); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -753,24 +900,24 @@ bool Rn487xBle::clearPermanentBeacon(void) // ********************************************************************************* bool Rn487xBle::startImmediateAdvertising(uint8_t adType, const char adData[]) { - debugPrintLn("[startImmediateAdvertising]") ; - - uint8_t len = strlen(START_IMMEDIATE_ADV) ; - char c[2] ; - sprintf(c, "%02X", adType) ; - uint8_t newLen = strlen(c) ; - - this->flush() ; - memcpy(uartBuffer, START_IMMEDIATE_ADV, len) ; - memcpy(&uartBuffer[len], c, newLen) ; - memcpy(&uartBuffer[len+newLen], ",", 1) ; - memcpy(&uartBuffer[len+newLen+1], adData, strlen(adData)) ; - sendCommand(uartBuffer) ; + debugPrintLn("[startImmediateAdvertising]"); + + uint8_t len = strlen(START_IMMEDIATE_ADV); + char c[2]; + sprintf(c, "%02X", adType); + uint8_t newLen = strlen(c); + + this->flush(); + memcpy(uartBuffer, START_IMMEDIATE_ADV, len); + memcpy(&uartBuffer[len], c, newLen); + memcpy(&uartBuffer[len+newLen], ",", 1); + memcpy(&uartBuffer[len+newLen+1], adData, strlen(adData)); + sendCommand(uartBuffer); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -785,24 +932,24 @@ bool Rn487xBle::startImmediateAdvertising(uint8_t adType, const char adData[]) // ********************************************************************************* bool Rn487xBle::startPermanentAdvertising(uint8_t adType, const char adData[]) { - debugPrintLn("[startPermanentAdvertising]") ; - - uint8_t len = strlen(START_PERMANENT_ADV) ; - char c[2] ; - sprintf(c, "%02X", adType) ; - uint8_t newLen = strlen(c) ; - - this->flush() ; - memcpy(uartBuffer, START_PERMANENT_ADV, len) ; - memcpy(&uartBuffer[len], c, newLen) ; - memcpy(&uartBuffer[len+newLen], ",", 1) ; - memcpy(&uartBuffer[len+newLen+1], adData, strlen(adData)) ; - sendCommand(uartBuffer) ; + debugPrintLn("[startPermanentAdvertising]"); + + uint8_t len = strlen(START_PERMANENT_ADV); + char c[2]; + sprintf(c, "%02X", adType); + uint8_t newLen = strlen(c); + + this->flush(); + memcpy(uartBuffer, START_PERMANENT_ADV, len); + memcpy(&uartBuffer[len], c, newLen); + memcpy(&uartBuffer[len+newLen], ",", 1); + memcpy(&uartBuffer[len+newLen+1], adData, strlen(adData)); + sendCommand(uartBuffer); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -816,24 +963,24 @@ bool Rn487xBle::startPermanentAdvertising(uint8_t adType, const char adData[]) // ********************************************************************************* bool Rn487xBle::startImmediateBeacon(uint8_t adType, const char adData[]) { - debugPrintLn("[startImmediateBeacon]") ; - - uint8_t len = strlen(START_IMMEDIATE_BEACON) ; - char c[2] ; - sprintf(c, "%02X", adType) ; - uint8_t newLen = strlen(c) ; - - this->flush() ; - memcpy(uartBuffer, START_IMMEDIATE_BEACON, len) ; - memcpy(&uartBuffer[len], c, newLen) ; - memcpy(&uartBuffer[len+newLen], ",", 1) ; - memcpy(&uartBuffer[len+newLen+1], adData, strlen(adData)) ; - sendCommand(uartBuffer) ; + debugPrintLn("[startImmediateBeacon]"); + + uint8_t len = strlen(START_IMMEDIATE_BEACON); + char c[2]; + sprintf(c, "%02X", adType); + uint8_t newLen = strlen(c); + + this->flush(); + memcpy(uartBuffer, START_IMMEDIATE_BEACON, len); + memcpy(&uartBuffer[len], c, newLen); + memcpy(&uartBuffer[len+newLen], ",", 1); + memcpy(&uartBuffer[len+newLen+1], adData, strlen(adData)); + sendCommand(uartBuffer); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -848,24 +995,24 @@ bool Rn487xBle::startImmediateBeacon(uint8_t adType, const char adData[]) // ********************************************************************************* bool Rn487xBle::startPermanentBeacon(uint8_t adType, const char adData[]) { - debugPrintLn("[startPermanentBeacon]") ; - - uint8_t len = strlen(START_PERMANENT_BEACON) ; - char c[2] ; - sprintf(c, "%02X", adType) ; - uint8_t newLen = strlen(c) ; - - this->flush() ; - memcpy(uartBuffer, START_PERMANENT_BEACON, len) ; - memcpy(&uartBuffer[len], c, newLen) ; - memcpy(&uartBuffer[len+newLen], ",", 1) ; - memcpy(&uartBuffer[len+newLen+1], adData, strlen(adData)) ; - sendCommand(uartBuffer) ; + debugPrintLn("[startPermanentBeacon]"); + + uint8_t len = strlen(START_PERMANENT_BEACON); + char c[2]; + sprintf(c, "%02X", adType); + uint8_t newLen = strlen(c); + + this->flush(); + memcpy(uartBuffer, START_PERMANENT_BEACON, len); + memcpy(&uartBuffer[len], c, newLen); + memcpy(&uartBuffer[len+newLen], ",", 1); + memcpy(&uartBuffer[len+newLen+1], adData, strlen(adData)); + sendCommand(uartBuffer); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -880,14 +1027,14 @@ bool Rn487xBle::startPermanentBeacon(uint8_t adType, const char adData[]) // ********************************************************************************* bool Rn487xBle::startScanning(void) { - debugPrintLn("[startScanning]") ; + debugPrintLn("[startScanning]"); - sendCommand(START_DEFAULT_SCAN) ; + sendCommand(START_DEFAULT_SCAN); if (expectResponse(SCANNING_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -906,26 +1053,26 @@ bool Rn487xBle::startScanning(void) // ********************************************************************************* bool Rn487xBle::startScanning(uint16_t scanInterval, uint16_t scanWindow) { - debugPrint("[startScanning2]") ; //debugPrint(" Interval = " + scanInterval) ; debugPrint(" Window = " + scanWindow) ; - - uint8_t len = strlen(START_CUSTOM_SCAN) ; - char c1[4] ; - sprintf(c1, "%04X", scanInterval) ; - uint8_t newLen = strlen(c1) ; - char c2[4] ; - sprintf(c2, "%04X", scanWindow) ; + debugPrint("[startScanning2]"); //debugPrint(" Interval = " + scanInterval) ; debugPrint(" Window = " + scanWindow) ; + + uint8_t len = strlen(START_CUSTOM_SCAN); + char c1[4]; + sprintf(c1, "%04X", scanInterval); + uint8_t newLen = strlen(c1); + char c2[4]; + sprintf(c2, "%04X", scanWindow); - this->flush() ; - memcpy(uartBuffer, START_CUSTOM_SCAN, len) ; - memcpy(&uartBuffer[len], c1, newLen) ; - memcpy(&uartBuffer[len+newLen], ",", 1) ; - memcpy(&uartBuffer[len+newLen+1], c2, strlen(c2)) ; - sendCommand(uartBuffer) ; + this->flush(); + memcpy(uartBuffer, START_CUSTOM_SCAN, len); + memcpy(&uartBuffer[len], c1, newLen); + memcpy(&uartBuffer[len+newLen], ",", 1); + memcpy(&uartBuffer[len+newLen+1], c2, strlen(c2)); + sendCommand(uartBuffer); if (expectResponse(SCANNING_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -937,14 +1084,14 @@ bool Rn487xBle::startScanning(uint16_t scanInterval, uint16_t scanWindow) // ********************************************************************************* bool Rn487xBle::stopScanning(void) { - debugPrintLn("[stopScanning]") ; + debugPrintLn("[stopScanning]"); - sendCommand(STOP_SCAN) ; + sendCommand(STOP_SCAN); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -965,47 +1112,47 @@ bool Rn487xBle::stopScanning(void) // ********************************************************************************* bool Rn487xBle::addMacAddrWhiteList(bool addrType, const char *addr) { - debugPrint("[addMacAddrWhiteList] ") ; + debugPrint("[addMacAddrWhiteList] "); - uint8_t len = strlen(ADD_WHITE_LIST) ; - uint8_t addrLen = strlen(addr) ; + uint8_t len = strlen(ADD_WHITE_LIST); + uint8_t addrLen = strlen(addr); if (addrLen != MAC_ADDRESS_LEN) { - debugPrintLn("MAC Address is not valid !") ; - return false ; + debugPrintLn("MAC Address is not valid !"); + return false; } - debugPrintLn(addrType) ; + debugPrintLn(addrType); - whiteListCnt ++ ; + whiteListCnt++; if (whiteListCnt >= MAX_WHITE_LIST_SIZE) { - whiteListCnt = MAX_WHITE_LIST_SIZE ; - debugPrintLn("White list is full, not possible to add new MAC address.") ; - return false ; + whiteListCnt = MAX_WHITE_LIST_SIZE; + debugPrintLn("White list is full, not possible to add new MAC address."); + return false; } // Fill the buffer - this->flush() ; - memcpy(uartBuffer, ADD_WHITE_LIST, len) ; + this->flush(); + memcpy(uartBuffer, ADD_WHITE_LIST, len); if (addrType) { - memcpy(&uartBuffer[len], PRIVATE_ADDRESS_TYPE, 1) ; + memcpy(&uartBuffer[len], PRIVATE_ADDRESS_TYPE, 1); } else { - memcpy(&uartBuffer[len], PUBLIC_ADDRESS_TYPE, 1) ; + memcpy(&uartBuffer[len], PUBLIC_ADDRESS_TYPE, 1); } - len += 1 ; - memcpy(&uartBuffer[len], ",", 1) ; - len += 1 ; - memcpy(&uartBuffer[len], addr, addrLen) ; - sendCommand(uartBuffer) ; + len += 1; + memcpy(&uartBuffer[len], ",", 1); + len += 1; + memcpy(&uartBuffer[len], addr, addrLen); + sendCommand(uartBuffer); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -1022,14 +1169,14 @@ bool Rn487xBle::addMacAddrWhiteList(bool addrType, const char *addr) // ********************************************************************************* bool Rn487xBle::addBondedWhiteList(void) { - debugPrintLn("[addBondedWhiteList]") ; + debugPrintLn("[addBondedWhiteList]"); - sendCommand(ADD_BONDED_WHITE_LIST) ; + sendCommand(ADD_BONDED_WHITE_LIST); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -1041,16 +1188,16 @@ bool Rn487xBle::addBondedWhiteList(void) // ********************************************************************************* bool Rn487xBle::clearWhiteList(void) { - debugPrintLn("[clearWhiteList]") ; + debugPrintLn("[clearWhiteList]"); - whiteListCnt = 0 ; + whiteListCnt = 0; - sendCommand(CLEAR_WHITE_LIST) ; + sendCommand(CLEAR_WHITE_LIST); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -1062,14 +1209,14 @@ bool Rn487xBle::clearWhiteList(void) // ********************************************************************************* bool Rn487xBle::killConnection(void) { - debugPrintLn("[killConnection]") ; + debugPrintLn("[killConnection]"); - sendCommand(KILL_CONNECTION) ; + sendCommand(KILL_CONNECTION); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -1083,20 +1230,20 @@ bool Rn487xBle::killConnection(void) // ********************************************************************************* bool Rn487xBle::getRSSI(void) { - debugPrint("[getRSSI]") ; + debugPrint("[getRSSI]"); - uint16_t timeout = DEFAULT_CMD_TIMEOUT ; - unsigned long previous ; - sendCommand(GET_RSSI_LEVEL) ; - previous = millis() ; + uint16_t timeout = DEFAULT_CMD_TIMEOUT; + unsigned long previous; + sendCommand(GET_RSSI_LEVEL); + previous = millis(); while (millis() - previous < timeout) { - debugPrint(".") ; + debugPrint("."); if (this->bleSerial->available() > 0) { if (readUntilCR() > 0) { - return true ; + return true; } } } @@ -1113,15 +1260,15 @@ bool Rn487xBle::getRSSI(void) // ********************************************************************************* bool Rn487xBle::reboot(void) { - debugPrintLn("[reboot]") ; + debugPrintLn("[reboot]"); - sendCommand(REBOOT) ; + sendCommand(REBOOT); if (expectResponse(REBOOTING_RESP, RESET_CMD_TIMEOUT)) { - delay(RESET_CMD_TIMEOUT) ; // delay needed - return true ; + delay(RESET_CMD_TIMEOUT); // delay needed + return true; } - return false ; + return false; } // ********************************************************************************* @@ -1137,37 +1284,37 @@ bool Rn487xBle::reboot(void) // ********************************************************************************* bool Rn487xBle::setServiceUUID(const char *uuid) { - debugPrint("[serServiceUUID]") ; - debugPrintLn(uuid) ; + debugPrint("[serServiceUUID]"); + debugPrintLn(uuid); - uint8_t len = strlen(DEFINE_SERVICE_UUID) ; - uint8_t newLen = strlen(uuid) ; + uint8_t len = strlen(DEFINE_SERVICE_UUID); + uint8_t newLen = strlen(uuid); if (newLen == 32) { // 128-bit => private service - debugPrintLn("128-bit length => private service") ; + debugPrintLn("128-bit length => private service"); } else if (newLen == 4) { // 16-bit => public service - debugPrintLn("16-bit length => public service") ; + debugPrintLn("16-bit length => public service"); } else { - debugPrintLn("UUID length is not correct") ; - return false ; + debugPrintLn("UUID length is not correct"); + return false; } - this->flush() ; - memcpy(uartBuffer, DEFINE_SERVICE_UUID, len) ; - memcpy(&uartBuffer[len], uuid, newLen) ; - sendCommand(uartBuffer) ; + this->flush(); + memcpy(uartBuffer, DEFINE_SERVICE_UUID, len); + memcpy(&uartBuffer[len], uuid, newLen); + sendCommand(uartBuffer); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -1187,54 +1334,54 @@ bool Rn487xBle::setServiceUUID(const char *uuid) // ********************************************************************************* bool Rn487xBle::setCharactUUID(const char *uuid, uint8_t property, uint8_t octetLen) { - debugPrint("[setCharactUUID]") ; - debugPrintLn(uuid) ; + debugPrint("[setCharactUUID]"); + debugPrintLn(uuid); if (octetLen < 0x01) { - octetLen = 0x01 ; - debugPrintLn("Octet Length is out of range (0x01-0x14)") ; + octetLen = 0x01; + debugPrintLn("Octet Length is out of range (0x01-0x14)"); } else if (octetLen > 0x14) { - octetLen = 0x14 ; - debugPrintLn("Octet Length is out of range (0x01-0x14)") ; + octetLen = 0x14; + debugPrintLn("Octet Length is out of range (0x01-0x14)"); } - uint8_t len = strlen(DEFINE_CHARACT_UUID) ; - uint8_t newLen = strlen(uuid) ; + //uint8_t len = strlen(DEFINE_CHARACT_UUID); + uint8_t newLen = strlen(uuid); if (newLen == PRIVATE_SERVICE_LEN) { - debugPrintLn("128-bit length => private service") ; + debugPrintLn("128-bit length => private service"); } else if (newLen == PUBLIC_SERVICE_LEN) { // 16-bit => public service - debugPrintLn("16-bit length => public service") ; + debugPrintLn("16-bit length => public service"); } else { - debugPrintLn("UUID length is not correct") ; - return false ; + debugPrintLn("UUID length is not correct"); + return false; } - String str = DEFINE_CHARACT_UUID ; - char c[2] ; - str.concat(uuid) ; - str.concat(',') ; - sprintf(c, "%02X", property) ; - str.concat(c) ; - str.concat(',') ; - sprintf(c, "%02X", octetLen) ; - str.concat(c) ; - - sendCommand(str) ; + String str = DEFINE_CHARACT_UUID; + char c[2]; + str.concat(uuid); + str.concat(','); + sprintf(c, "%02X", property); + str.concat(c); + str.concat(','); + sprintf(c, "%02X", octetLen); + str.concat(c); + + sendCommand(str); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -1248,24 +1395,24 @@ bool Rn487xBle::setCharactUUID(const char *uuid, uint8_t property, uint8_t octet // ********************************************************************************* bool Rn487xBle::writeLocalCharacteristic(uint16_t handle, const char value[]) { - debugPrint("[writeLocalCharacteristic]") ; - - uint8_t len = strlen(WRITE_LOCAL_CHARACT) ; - char c[4] ; - sprintf(c, "%04X", handle) ; - uint8_t newLen = strlen(c) ; - - this->flush() ; - memcpy(uartBuffer, WRITE_LOCAL_CHARACT, len) ; - memcpy(&uartBuffer[len], c, newLen) ; - memcpy(&uartBuffer[len+newLen], ",", 1) ; - memcpy(&uartBuffer[len+newLen+1], value, strlen(value)) ; - sendCommand(uartBuffer) ; + debugPrint("[writeLocalCharacteristic]"); + + uint8_t len = strlen(WRITE_LOCAL_CHARACT); + char c[4]; + sprintf(c, "%04X", handle); + uint8_t newLen = strlen(c); + + this->flush(); + memcpy(uartBuffer, WRITE_LOCAL_CHARACT, len); + memcpy(&uartBuffer[len], c, newLen); + memcpy(&uartBuffer[len+newLen], ",", 1); + memcpy(&uartBuffer[len+newLen+1], value, strlen(value)); + sendCommand(uartBuffer); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -1279,29 +1426,29 @@ bool Rn487xBle::writeLocalCharacteristic(uint16_t handle, const char value[]) // ********************************************************************************* bool Rn487xBle::readLocalCharacteristic(uint16_t handle) { - debugPrint("[readLocalCharacteristic]") ; + debugPrint("[readLocalCharacteristic]"); - uint16_t timeout = DEFAULT_CMD_TIMEOUT ; - unsigned long previous ; + uint16_t timeout = DEFAULT_CMD_TIMEOUT; + unsigned long previous; - uint8_t len = strlen(READ_LOCAL_CHARACT) ; - char c[4] ; - sprintf(c, "%04X", handle) ; - uint8_t newLen = strlen(c) ; + uint8_t len = strlen(READ_LOCAL_CHARACT); + char c[4]; + sprintf(c, "%04X", handle); + uint8_t newLen = strlen(c); - this->flush() ; - memcpy(uartBuffer, READ_LOCAL_CHARACT, len) ; - memcpy(&uartBuffer[len], c, newLen) ; - sendCommand(uartBuffer) ; - previous = millis() ; + this->flush(); + memcpy(uartBuffer, READ_LOCAL_CHARACT, len); + memcpy(&uartBuffer[len], c, newLen); + sendCommand(uartBuffer); + previous = millis(); while (millis() - previous < timeout) { - debugPrint(".") ; + debugPrint("."); if (this->bleSerial->available() > 0) { if (readUntilCR() > 0) { - return true ; + return true; } } } @@ -1324,17 +1471,17 @@ bool Rn487xBle::readLocalCharacteristic(uint16_t handle) // ********************************************************************************* int Rn487xBle::getConnectionStatus(void) { - debugPrint("[getConnectionStatus]") ; + debugPrint("[getConnectionStatus]"); - uint16_t timeout = DEFAULT_CMD_TIMEOUT ; - unsigned long previous ; + uint16_t timeout = DEFAULT_CMD_TIMEOUT; + unsigned long previous; - sendCommand(GET_CONNECTION_STATUS) ; + sendCommand(GET_CONNECTION_STATUS); - previous = millis() ; + previous = millis(); while (millis() - previous < timeout) { - debugPrint(".") ; + debugPrint("."); if (this->bleSerial->available() > 0) { if (readUntilCR() > 0) @@ -1343,15 +1490,15 @@ int Rn487xBle::getConnectionStatus(void) if (strstr(this->uartBuffer, NONE_RESP) != NULL) { // Not connected - return false ; + return false; } // Connected - return true ; + return true; } } } - debugPrint("[getConnectionStatus] Timeout without a response !") ; - return -1 ; + debugPrint("[getConnectionStatus] Timeout without a response !"); + return -1; } // ---------------------------------------- Private section ---------------------------------------- @@ -1364,18 +1511,18 @@ int Rn487xBle::getConnectionStatus(void) // ********************************************************************************* bool Rn487xBle::setBeaconFeatures(const char *value) { - debugPrintLn("[setBeaconFeatures]") ; + debugPrintLn("[setBeaconFeatures]"); - uint8_t len = strlen(SET_BEACON_FEATURES) ; - this->flush() ; - memcpy(uartBuffer, SET_BEACON_FEATURES, len) ; - memcpy(&uartBuffer[len], value, 1) ; - sendCommand(uartBuffer) ; + uint8_t len = strlen(SET_BEACON_FEATURES); + this->flush(); + memcpy(uartBuffer, SET_BEACON_FEATURES, len); + memcpy(&uartBuffer[len], value, 1); + sendCommand(uartBuffer); if (expectResponse(AOK_RESP, DEFAULT_CMD_TIMEOUT)) { - return true ; + return true; } - return false ; + return false; } // ********************************************************************************* @@ -1387,40 +1534,43 @@ bool Rn487xBle::setBeaconFeatures(const char *value) // ********************************************************************************* bool Rn487xBle::getSettings(uint16_t addr, uint8_t sizeToRead) { - debugPrintLn("[getSettings]") ; - - if (sizeToRead > MAX_SETTINGS_LEN) sizeToRead = MAX_SETTINGS_LEN ; - - uint16_t timeout = DEFAULT_CMD_TIMEOUT ; - unsigned long previous ; - - uint8_t len = strlen(GET_SETTINGS) ; - char c1[4] ; - sprintf(c1, "%04X", addr) ; - uint8_t newLen = strlen(c1) ; - char c2[2] ; - sprintf(c2, "%02X", sizeToRead) ; - - this->flush() ; - memcpy(uartBuffer, GET_SETTINGS, len) ; - memcpy(&uartBuffer[len], c1, newLen) ; - memcpy(&uartBuffer[len+newLen], ",", 1) ; - memcpy(&uartBuffer[len+newLen+1], c2, strlen(c2)) ; - sendCommand(uartBuffer) ; + debugPrintLn("[getSettings]"); + + if (sizeToRead > MAX_SETTINGS_LEN) + { + sizeToRead = MAX_SETTINGS_LEN; + } + + uint16_t timeout = DEFAULT_CMD_TIMEOUT; + unsigned long previous; + + uint8_t len = strlen(GET_SETTINGS); + char c1[4]; + sprintf(c1, "%04X", addr); + uint8_t newLen = strlen(c1); + char c2[2]; + sprintf(c2, "%02X", sizeToRead); + + this->flush(); + memcpy(uartBuffer, GET_SETTINGS, len); + memcpy(&uartBuffer[len], c1, newLen); + memcpy(&uartBuffer[len+newLen], ",", 1); + memcpy(&uartBuffer[len+newLen+1], c2, strlen(c2)); + sendCommand(uartBuffer); - previous = millis() ; + previous = millis(); while (millis() - previous < timeout) { - debugPrint(".") ; + debugPrint("."); if (this->bleSerial->available() > 0) { if (readUntilCR() > 0) { - return true ; + return true; } } } - return false ; + return false; } // ********************************************************************************* @@ -1434,41 +1584,41 @@ bool Rn487xBle::getSettings(uint16_t addr, uint8_t sizeToRead) // ********************************************************************************* bool Rn487xBle::setSettings(uint16_t addr, const char *data) { - debugPrintLn("[setSettings]") ; + debugPrintLn("[setSettings]"); - uint8_t dataLen = strlen(data) ; - debugPrintLn(data) ; - debugPrint("Len = ") ; - debugPrintLn(dataLen) ; + uint8_t dataLen = strlen(data); + debugPrintLn(data); + debugPrint("Len = "); + debugPrintLn(dataLen); - uint16_t timeout = DEFAULT_CMD_TIMEOUT ; - unsigned long previous ; - - uint8_t len = strlen(SET_SETTINGS) ; - char c1[4] ; - sprintf(c1, "%04X", addr) ; - uint8_t newLen = strlen(c1) ; - - this->flush() ; - memcpy(uartBuffer, SET_SETTINGS, len) ; - memcpy(&uartBuffer[len], c1, newLen) ; - memcpy(&uartBuffer[len+newLen], ",", 1) ; - memcpy(&uartBuffer[len+newLen+1], data, dataLen) ; - sendCommand(uartBuffer) ; + uint16_t timeout = DEFAULT_CMD_TIMEOUT; + unsigned long previous; + + uint8_t len = strlen(SET_SETTINGS); + char c1[4]; + sprintf(c1, "%04X", addr); + uint8_t newLen = strlen(c1); + + this->flush(); + memcpy(uartBuffer, SET_SETTINGS, len); + memcpy(&uartBuffer[len], c1, newLen); + memcpy(&uartBuffer[len+newLen], ",", 1); + memcpy(&uartBuffer[len+newLen+1], data, dataLen); + sendCommand(uartBuffer); - previous = millis() ; + previous = millis(); while (millis() - previous < timeout) { - debugPrint(".") ; + debugPrint("."); if (this->bleSerial->available() > 0) { if (readUntilCR() > 0) { - return true ; + return true; } } } - return false ; + return false; } // ********************************************************************************* @@ -1479,8 +1629,13 @@ bool Rn487xBle::setSettings(uint16_t addr, const char *data) // ********************************************************************************* void Rn487xBle::flush(void) { - uartBufferLen = DEFAULT_INPUT_BUFFER_SIZE ; - memset(uartBuffer, 0, uartBufferLen) ; + uartBufferLen = DEFAULT_INPUT_BUFFER_SIZE; + // FOR DEBUGGING, PRINT OUT ANYTHING THAT'S IN THE BUFFER +// this->diagStream->print(" * Flushing :"); +// this->diagStream->print(uartBuffer); +// this->diagStream->println(":"); + + memset(uartBuffer, 0, uartBufferLen); } // ********************************************************************************* @@ -1493,7 +1648,7 @@ void Rn487xBle::cleanInputBuffer(void) { while (bleSerial->available() > 0) { - bleSerial->read() ; + bleSerial->read(); } } @@ -1505,7 +1660,7 @@ void Rn487xBle::cleanInputBuffer(void) // ********************************************************************************* void Rn487xBle::setOperationMode(operationMode_t newMode) { - operationMode = newMode ; + operationMode = newMode; } // ********************************************************************************* @@ -1516,7 +1671,7 @@ void Rn487xBle::setOperationMode(operationMode_t newMode) // ********************************************************************************* operationMode_t Rn487xBle::getOperationMode(void) { - return(operationMode) ; + return(operationMode); } @@ -1533,8 +1688,8 @@ operationMode_t Rn487xBle::getOperationMode(void) // ********************************************************************************* uint16_t Rn487xBle::readUntilCR(char* buffer, uint16_t size, uint16_t start) { - int len = this->bleSerial->readBytesUntil(CR, buffer + start, size) ; - return len ; + int len = this->bleSerial->readBytesUntil(LF, buffer + start, size); + return len; } @@ -1548,30 +1703,30 @@ uint16_t Rn487xBle::readUntilCR(char* buffer, uint16_t size, uint16_t start) // ********************************************************************************* bool Rn487xBle::expectResponse(const char* expectedResponse, uint16_t timeout) { - debugPrint("[expectResponse] expecting ") ; - debugPrintLn(expectedResponse) ; + debugPrint("[expectResponse] expecting "); + debugPrintLn(expectedResponse); - unsigned long previous ; + unsigned long previous; - memset(uartBuffer, 0, uartBufferLen) ; // clear the buffer - cleanInputBuffer() ; - previous = millis() ; + memset(uartBuffer, 0, uartBufferLen); // clear the buffer + cleanInputBuffer(); + previous = millis(); while (millis() - previous < timeout) { - debugPrint(".") ; + debugPrint("."); if (readUntilCR() > 0) { - debugPrint("(") ; - debugPrint(this->uartBuffer) ; - debugPrint(")") ; + debugPrint("("); + debugPrint(this->uartBuffer); + debugPrint(")"); if (strstr(this->uartBuffer, expectedResponse) != NULL) { - debugPrintLn(" found a match !") ; - return true ; + debugPrintLn(" found a match !"); + return true; } - return false ; + return false; } } - return false ; + return false; } diff --git a/src/RN487x_BLE.h b/src/RN487x_BLE.h index 99da0ab..e4919a7 100644 --- a/src/RN487x_BLE.h +++ b/src/RN487x_BLE.h @@ -24,13 +24,27 @@ TERMS. */ +/* TODO: + * add support for Scan Response commands + * add support for script commands (like stop and clear) + * Bug: Init sends two "R,1"s. Why? Only one is needed. + * Add support for Set Connection Parameters ("ST") + * Add support for Modify Current Connection Parameters ("T") + * BIG ONE: Add support for async notifications - like when the phone updates a local + server characteristic, and we get a "%WC," or "%WC," string from BLE module. Maybe + have a callback mechanism for this? + */ + + #ifndef __RN487x_BLE #define __RN487x_BLE #include "RN487x_CONST.h" #include #include -#include +#if !defined(__PIC32__) + #include +#endif #include #define DEFAULT_INPUT_BUFFER_SIZE 100 @@ -39,76 +53,79 @@ typedef enum { dataMode, cmdMode -} operationMode_t ; +} operationMode_t; class Rn487xBle { // ---------------------------------------- Public section ---------------------------------------- public: - Rn487xBle() ; - virtual ~Rn487xBle() ; - uint32_t getDefaultBaudRate(void) { return(DEFAULT_BAUDRATE) ; } ; - void setDiag(Stream& stream) { diagStream = &stream ; } ; - inline void initBleStream(Uart *stream) { this->bleSerial = stream ; cleanInputBuffer() ; } ; - bool swInit(void) ; - void hwInit(void) ; - void hwReset(void) ; - void hwWakeUp(void) ; - void hwSleep(void) ; - bool enterDataMode(void) ; - bool enterCommandMode(void) ; - void sendCommand(String stream) ; - void sendData(char *data, uint16_t dataLen) ; - bool disableBeacon(void) ; - bool enableBeacon(void) ; - bool enableBeaconAndAdv(void) ; - bool factoryReset(void) ; - bool setAdvPower(uint8_t value) ; - bool setConPower(uint8_t value) ; - bool setSerializedName(const char *newName) ; - bool setDevName(const char *newName) ; - bool enableLowPower(void) ; - bool disableLowPower(void) ; - bool setSupportedFeatures(uint16_t bitmap) ; - bool setDefaultServices(uint8_t bitmap) ; - bool retrieveBtAddress(void) ; - bool getFirmwareVersion(void) ; - bool clearAllServices(void) ; - bool startAdvertising(void) ; - bool stopAdvertising(void) ; - bool clearImmediateAdvertising(void) ; - bool clearPermanentAdvertising(void) ; - bool clearImmediateBeacon(void) ; - bool clearPermanentBeacon(void) ; - bool startImmediateAdvertising(uint8_t adType, const char adData[]) ; - bool startPermanentAdvertising(uint8_t adType, const char adData[]) ; - bool startImmediateBeacon(uint8_t adType, const char adData[]) ; - bool startPermanentBeacon(uint8_t adType, const char adData[]) ; - bool startScanning(void) ; - bool startScanning(uint16_t scanInterval, uint16_t scanWindow) ; - bool stopScanning(void) ; - bool addMacAddrWhiteList(bool addrType, const char *addr) ; - bool addBondedWhiteList(void) ; - bool clearWhiteList(void) ; - bool killConnection(void) ; - bool getRSSI(void) ; - bool reboot(void) ; - bool setServiceUUID(const char *uuid) ; - bool setCharactUUID(const char *uuid, uint8_t property, uint8_t octetLen) ; - bool writeLocalCharacteristic(uint16_t handle, const char value[]) ; - bool readLocalCharacteristic(uint16_t handle) ; - int getConnectionStatus(void) ; - inline const char* getPeerAddress() { return peerAddress ; } ; - inline const char* getBtAddress() { return btAddress ; } ; - inline const char* getDeviceName() { return deviceName ; } ; - inline const char* getLastResponse() { return uartBuffer ; } ; + Rn487xBle(); + virtual ~Rn487xBle(); + uint32_t getDefaultBaudRate(void) { return(DEFAULT_BAUDRATE);}; + void setDiag(Stream& stream) { diagStream = &stream;}; + inline void initBleStream(HardwareSerial *stream) { this->bleSerial = stream ; cleanInputBuffer();}; + bool swInit(void); + void hwInit(void); + void hwInit(uint8_t resetBLEPin, uint8_t sleepBLEPin); + void hwReset(void); + void hwWakeUp(void); + void hwSleep(void); + bool enterDataMode(void); + bool enterCommandMode(void); + void sendCommand(String stream); + void sendData(char *data, uint16_t dataLen); + bool disableBeacon(void); + bool enableBeacon(void); + bool enableBeaconAndAdv(void); + bool factoryReset(void); + bool setAdvPower(uint8_t value); + bool setConPower(uint8_t value); + bool setSerializedName(const char *newName); + bool setDevName(const char *newName); + bool enableLowPower(void); + bool disableLowPower(void); + bool setSupportedFeatures(uint16_t bitmap); + bool setDefaultServices(uint8_t bitmap); + bool retrieveBtAddress(void); + bool getFirmwareVersion(void); + bool clearAllServices(void); + bool startAdvertising(void); + bool startCustomAdvertising(uint16_t interval); + bool startCustomAdvertising(uint16_t interval, uint16_t totalAdTime); + bool stopAdvertising(void); + bool clearImmediateAdvertising(void); + bool clearPermanentAdvertising(void); + bool clearImmediateBeacon(void); + bool clearPermanentBeacon(void); + bool startImmediateAdvertising(uint8_t adType, const char adData[]); + bool startPermanentAdvertising(uint8_t adType, const char adData[]); + bool startImmediateBeacon(uint8_t adType, const char adData[]); + bool startPermanentBeacon(uint8_t adType, const char adData[]); + bool startScanning(void); + bool startScanning(uint16_t scanInterval, uint16_t scanWindow); + bool stopScanning(void); + bool addMacAddrWhiteList(bool addrType, const char *addr); + bool addBondedWhiteList(void); + bool clearWhiteList(void); + bool killConnection(void); + bool getRSSI(void); + bool reboot(void); + bool setServiceUUID(const char *uuid); + bool setCharactUUID(const char *uuid, uint8_t property, uint8_t octetLen); + bool writeLocalCharacteristic(uint16_t handle, const char value[]); + bool readLocalCharacteristic(uint16_t handle); + int getConnectionStatus(void); + inline const char* getPeerAddress() { return peerAddress;}; + inline const char* getBtAddress() { return btAddress;}; + inline const char* getDeviceName() { return deviceName;}; + inline const char* getLastResponse() { return uartBuffer;}; inline bool isInputBuffer() { - if (bleSerial->available() > 0) return true ; - return false ; + if (bleSerial->available() > 0) return true; + return false; } - inline char getInputBuffer(){ return bleSerial->read() ; } ; + inline char getInputBuffer(){ return bleSerial->read();}; // --------------------------------------- Protected section --------------------------------------- protected: @@ -116,31 +133,34 @@ class Rn487xBle // ---------------------------------------- Private section ---------------------------------------- private: - bool setBeaconFeatures(const char *value) ; - bool getSettings(uint16_t addr, uint8_t sizeToRead) ; - bool setSettings(uint16_t addr, const char *data) ; - void flush(void) ; - void cleanInputBuffer(void) ; - void setOperationMode(operationMode_t newMode) ; - operationMode_t getOperationMode(void) ; - uint16_t readUntilCR(char* buffer, uint16_t size, uint16_t start = 0) ; - uint16_t readUntilCR() { return readUntilCR(this->uartBuffer, this->uartBufferLen) ; } ; - bool expectResponse(const char* expectedResponse, uint16_t timeout) ; - - Uart *bleSerial ; - Stream* diagStream ; - char *uartBuffer ; - int uartBufferLen ; - char endStreamChar ; - operationMode_t operationMode ; - bool connectionStatus ; - char btAddress[12] ; - char peerAddress[6] ; - char deviceName[MAX_DEVICE_NAME_LEN] ; - uint8_t whiteListCnt ; + bool setBeaconFeatures(const char *value); + bool getSettings(uint16_t addr, uint8_t sizeToRead); + bool setSettings(uint16_t addr, const char *data); + void flush(void); + void cleanInputBuffer(void); + void setOperationMode(operationMode_t newMode); + operationMode_t getOperationMode(void); + uint16_t readUntilCR(char* buffer, uint16_t size, uint16_t start = 0); + uint16_t readUntilCR() { return readUntilCR(this->uartBuffer, this->uartBufferLen);}; + bool expectResponse(const char* expectedResponse, uint16_t timeout); + + HardwareSerial *bleSerial; + Stream* diagStream; + char *uartBuffer; + int uartBufferLen; + char endStreamChar; + operationMode_t operationMode; + bool connectionStatus; + char btAddress[12]; + char peerAddress[6]; + char deviceName[MAX_DEVICE_NAME_LEN]; + uint8_t whiteListCnt; + bool commandPromptEnabled; + int8_t wakePin; + int8_t resetPin; } ; // external variable used by the sketch -extern Rn487xBle rn487xBle ; +extern Rn487xBle rn487xBle; #endif diff --git a/src/RN487x_CONST.h b/src/RN487x_CONST.h index ce859a7..22a5e19 100644 --- a/src/RN487x_CONST.h +++ b/src/RN487x_CONST.h @@ -154,7 +154,8 @@ // ------------------- Response ----------------------- -#define PROMPT "CMD>" // exact prompt is "CMD> " (last char is a space) +#define PROMPT "CMD> " // exact prompt is "CMD> " (last char is a space) +#define PROMPT_CR "CMD\r\n" #define PROMPT_END "END" //-- Response From 10880ad30d57146061b7cd31da121e2ad4c6cc95 Mon Sep 17 00:00:00 2001 From: EmbeddedMan Date: Wed, 13 Dec 2017 20:43:23 -0600 Subject: [PATCH 2/9] Final version of BLE_SensorApp sketch. Also added serial passthrough sketch for debugging. --- examples/BLE_SensorApp/BLE_SensorApp.ino | 260 ++++++++++++++++++ .../SerialPassthrough/SerialPassthrough.ino | 25 ++ 2 files changed, 285 insertions(+) create mode 100644 examples/BLE_SensorApp/BLE_SensorApp.ino create mode 100644 examples/SerialPassthrough/SerialPassthrough.ino diff --git a/examples/BLE_SensorApp/BLE_SensorApp.ino b/examples/BLE_SensorApp/BLE_SensorApp.ino new file mode 100644 index 0000000..f6f3406 --- /dev/null +++ b/examples/BLE_SensorApp/BLE_SensorApp.ino @@ -0,0 +1,260 @@ +#include +#include +#include + +#define debugSerial Serial +#define bleSerial Serial1 + +//#define BLUETOOTH_WAKE 12 +//#define BT_RESET 7 + +/* Analog pin that temp sensor is connected to */ +#define TEMP_SENSOR A0 +/* Analog pin that pot is connected to */ +#define POT_SENSOR A2 +/* Maximuim number of milliseconds to wait for USB serial to get ready on boot */ +#define SERIAL_TIMEOUT_MS 5000 + +const char* myDeviceName = "FB Mini"; // Custom Device name +const char* myPrivateServiceUUID = "AD11CF40063F11E5BE3E0002A5D5C51B"; // Custom private service UUID + +// Light Sensor +const char* lightCharacteristicUUID = "BF3FBD80063F11E59E690002A5D5C501"; // custom characteristic GATT +const uint8_t lightCharacteristicLen = 2; // data length (in bytes) +const uint16_t lightHandle = 0x72; +char lightPayload[lightCharacteristicLen*2 + 1]; + +// Pot +const char* potCharacteristicUUID = "BF3FBD80063F11E59E690002A5D5C502"; // custom characteristic GATT +const uint8_t potCharacteristicLen = 2; // data length (in bytes) +const uint16_t potHandle = 0x75; +char potPayload[potCharacteristicLen*2 + 1]; + +// Switch/LED +const char* switchCharacteristicUUID = "BF3FBD80063F11E59E690002A5D5C503"; // custom characteristic GATT +const uint8_t switchCharacteristicLen = 20; // data length (in bytes) +const uint16_t switchHandle = 0x78; +char switchPayload[switchCharacteristicLen*2 + 1]; +const char* ledPayload; + +// Temp +const char* temperatureCharacteristicUUID = "BF3FBD80063F11E59E690002A5D5C504"; // custom characteristic GATT +const uint8_t temperatureCharacteristicLen = 2; // data length (in bytes) +const uint16_t temperatureHandle = 0x7B; +char temperaturePayload[temperatureCharacteristicLen*2 + 1]; + +// Battery +const char* batteryCharacteristicUUID = "BF3FBD80063F11E59E690002A5D5C505"; // custom characteristic GATT +const uint8_t batteryCharacteristicLen = 2; // data length (in bytes) +const uint16_t batteryHandle = 0x7E; +char batteryPayload[batteryCharacteristicLen*2 + 1]; + + +/** + * Read Activity Board temperature sensor in degrees C + */ +float getTemperature() +{ + float accumulator = 0; + + // Make 1000 analog conversions + for (int i=0; i < 1000; i++) + { + float sensorValue = analogRead(TEMP_SENSOR); + + // Convert them to raw volts (raw ADC is 0 to 1023), added fudge factor for accuracy + float voltage = (sensorValue * (3.3 / 1024.0)) + 0.0025; + + // Sum the raw volts value into the accumulator + accumulator += voltage; + } + + // Compute the average voltage over all conversions + float volt_ave = accumulator/1000.0; + + // Compute Celsius. Sensor reads in 10mV/deg C, with 500mV offset + float celsius = ((volt_ave * 1000.0) - 500.0) / 10.0; + + return (celsius); +} + +/** + * Read pot in milivolts + */ +int getPot() +{ + return ((analogRead(POT_SENSOR) * 3.3) / 1.023); +} + +void setup() +{ + + debugSerial.begin(115200); + + // Wait for PC to connect, give up after SERIAL_TIMEOUT_MS + while ((!debugSerial) && (millis() < SERIAL_TIMEOUT_MS)); + + // Set the optional debug stream + rn487xBle.setDiag(debugSerial); + // Initialize the BLE hardware with our sleep and wakeup pins + rn487xBle.hwInit(BT_RESET, BLUETOOTH_WAKE); + // Open the communication pipe with the BLE module + bleSerial.begin(rn487xBle.getDefaultBaudRate()); + // Assign the BLE serial port to the BLE library + rn487xBle.initBleStream(&bleSerial); + // Finalize the init. process + if (rn487xBle.swInit()) + { + debugSerial.println("Init. procedure done!"); + } + else + { + debugSerial.println("Init. procedure failed!"); + while(1); + } + + // Fist, enter into command mode + rn487xBle.enterCommandMode(); + // Stop advertising before starting the demo + rn487xBle.stopAdvertising(); + rn487xBle.clearPermanentAdvertising(); + rn487xBle.clearPermanentBeacon(); + rn487xBle.clearImmediateAdvertising(); + rn487xBle.clearImmediateBeacon(); + rn487xBle.clearAllServices(); + // Set the serialized device name + rn487xBle.setSerializedName(myDeviceName); + rn487xBle.setSupportedFeatures(0x4000); // Set to no prompt (no "CMD>") + rn487xBle.setDefaultServices(DEVICE_INFO_SERVICE); + // Set the advertising output power (range: min = 5, max = 0) + rn487xBle.setAdvPower(3); + rn487xBle.reboot(); + rn487xBle.enterCommandMode(); + rn487xBle.clearAllServices(); + // Set a private service ... + rn487xBle.setServiceUUID(myPrivateServiceUUID); + // which contains ... + // ...a light sensor (unused) characteristic; readable and can perform notification, 2-octets size + rn487xBle.setCharactUUID(lightCharacteristicUUID, NOTIFY_PROPERTY, lightCharacteristicLen); + // ...a pot characteristic; readable and can perform notification, 2-octets size + rn487xBle.setCharactUUID(potCharacteristicUUID, NOTIFY_PROPERTY, potCharacteristicLen); + // ...a LED/Switch characteristic; readable and can perform notification, 20-octets size + rn487xBle.setCharactUUID(switchCharacteristicUUID, WRITE_PROPERTY | NOTIFY_PROPERTY, switchCharacteristicLen); + // ...a temperature characteristic; readable and can perform notification, 2-octets size + rn487xBle.setCharactUUID(temperatureCharacteristicUUID, NOTIFY_PROPERTY, temperatureCharacteristicLen); + // ...a battery (unused) characteristic; readable and can perform notification, 2-octets size + rn487xBle.setCharactUUID(batteryCharacteristicUUID, NOTIFY_PROPERTY, batteryCharacteristicLen); + + rn487xBle.startPermanentAdvertising(AD_TYPE_FLAGS, "06"); + rn487xBle.startPermanentAdvertising(AD_TYPE_MANUFACTURE_SPECIFIC_DATA, "CD00FE14AD11CF40063F11E5BE3E0002A5D5C51B"); + + // take into account the settings by issuing a reboot + rn487xBle.reboot(); + rn487xBle.enterCommandMode(); + + rn487xBle.startCustomAdvertising(210); + + debugSerial.println("Fubarino Mini Activity Board as a Peripheral with private service"); + debugSerial.println("================================================"); + debugSerial.println("You can now establish a connection from the Microchip SmartDiscovery App"); + debugSerial.print("with the board: ") ; debugSerial.println(rn487xBle.getDeviceName()); +} + +void loop() +{ + // Check the connection status + if (rn487xBle.getConnectionStatus()) + { + // We are connected to a peer + debugSerial.print("Connected to a peer central "); + debugSerial.println(rn487xBle.getLastResponse()); + + // Light Sensor + // 1000d = 21 lux + // 2000d = 83 lux + // Since we don't have a light sensor, just hard-code this to a known value + sprintf(lightPayload, "%04X", 2000); + rn487xBle.writeLocalCharacteristic(lightHandle, lightPayload); + + // Temperature + /* Convert to units that the Phone app wants + * 1000d = -8.47 F (Apple) --- (Android) + * 1200d = 18.29 F (Apple) 39.76 F (Android) + * 1500d = 58.84 F (Apple) 85.24 F (Android) + * 1600d = 71.8 F (Apple) + * So to convert from Celcius to counts that the app needs, we mulitply by 13.32 and add 1302 (for Apple) + * Note that the two phone apps interpret this value differently, so we can't create one formula that will + * work properly for both. This math is set up for the iPhone app. + */ + sprintf(temperaturePayload, "%04X", (uint16_t)((getTemperature() * 13.32) + 1302.0)); + rn487xBle.writeLocalCharacteristic(temperatureHandle, temperaturePayload); + + // Pot + sprintf(potPayload, "%04X", getPot()); + rn487xBle.writeLocalCharacteristic(potHandle, potPayload); + + // Battery + // 2000 = 7% + // 3000 = 78% + // Since we don't have a battery sensor, just hard code this to be a known value + sprintf(batteryPayload, "%04X", 3000); + rn487xBle.writeLocalCharacteristic(batteryHandle, batteryPayload); + + // LED + // This one is the complicated one. Every time the user moves the LED slider on the phone + // app, the readLocalCharactistic will get a value like XXXXXXXX2CYYYYYYYY where XXXXXXXX + // and YYYYYYYY are four byte hex numbers encoded as ASCII values. (So 0x89AB would be + // 38394142) I'm not exactly sure what each value is for, but we just use the first + // one to dim the LED on the Fubarino. + if (rn487xBle.readLocalCharacteristic(switchHandle)) + { + ledPayload = rn487xBle.getLastResponse(); + if ((ledPayload != NULL) && (ledPayload[0] != 'N') && (strlen(ledPayload) >= 9)) // != "N/A" response + { + // The difficult thing here is that beacuse the value is encoded as ASCII values, we have + // to convert each of the 4 ASCII values into the 4 hex bytes, then interpret the hex + // value as a number. Also, for some reason "%2hhx" doesn't seem to work in this version + // of sscanf, so we can't directly convert the ASCII values into bytes, we have to have + // sscanf convert each 2-byte ASCII value into an int, then cast that into to a byte. + // Then the resulting four byte string can be converted to a 16-bit unsigned number. + // Seems like way too much work to go through just to get a 16 bit value from the phone. + uint32_t led = 0; + uint32_t hexstring_int[4]; + uint8_t hexstring[5]; + uint8_t i; + + for (i=0; i < 4; i++) + { + sscanf(&ledPayload[i*2], "%2x", (unsigned int *)&hexstring_int[i]); + hexstring[i] = hexstring_int[i]; + } + hexstring[4] = 0; + + // led = 500 when slider is all the way right (android) or 1750 (Apple) + // led = 0 when slider is all the way left (android and Apple) + // led = 26670 when slider is just a bit in from the left side, decreasing down to 500 on the right side (28221 Apple) + sscanf((char*)hexstring, "%x", (unsigned int *)&led); + SoftPWMServoPWMWrite(PIN_LED1, map(led, 28000, 500, 0, 255)); + } + } + + // Switch + // Note that because we use the same server characteristic for sending switch data to the phone as well + // as getting LED information back from the phone, we have to do things in this order (LED read first, + // then switch write) otherwise the LED read will always return "0001" or "0000" from the switch write. + sprintf(switchPayload, "000%1d", digitalRead(PIN_BTN1)); + rn487xBle.writeLocalCharacteristic(switchHandle, switchPayload); + + // Delay inter connection polling - when connected, update every 1/4 second + delay(250); + } + else + { + // Not connected to a peer device + debugSerial.println("Not connected to a peer device"); + + // Delay inter connection polling - when not connected, check for new connections ever 1 second + delay(1000); + } +} + diff --git a/examples/SerialPassthrough/SerialPassthrough.ino b/examples/SerialPassthrough/SerialPassthrough.ino new file mode 100644 index 0000000..4d973fa --- /dev/null +++ b/examples/SerialPassthrough/SerialPassthrough.ino @@ -0,0 +1,25 @@ +#define BLE_MODE_PIN 6 +#define BLE_RESET_PIN 7 + +void setup() { + pinMode(BLE_MODE_PIN, OUTPUT); + digitalWrite(BLE_MODE_PIN, HIGH); + pinMode(BLE_RESET_PIN, OUTPUT); + digitalWrite(BLE_RESET_PIN, HIGH); + + Serial.begin(115200); + Serial1.begin(115200); + + while (!Serial) { + ; // wait for serial port to connect. + } +} + +void loop() // run over and over +{ + if (Serial.available()) + Serial1.write(Serial.read()); + if (Serial1.available()) + Serial.write(Serial1.read()); +} + From a119c4e08705f3a1ce59c2aed0930f79466a49ac Mon Sep 17 00:00:00 2001 From: EmbeddedMan Date: Wed, 13 Dec 2017 20:45:11 -0600 Subject: [PATCH 3/9] Fixed library properties. --- library.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library.properties b/library.properties index fbdcbac..a0bca5c 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=Microchip_RN487x version=1.1.0 author=M16946,Microchip Technology (c) -maintainer=Brian Schmalz +maintainer=M16946,Brian Schmalz sentence=An Arduino library for the Microchip RN487x paragraph=Command mode support for NR487x BLE modules from Microchip. Updated to work with chipKIT boards. category=Communication -url=https://github.com/chipKIT32-libraries/Microchip_RN487x +url=https://github.com/SodaqMoja/Microchip_RN487x architectures=* From 96da9140aadc25514511a0c56184452255cdd19f Mon Sep 17 00:00:00 2001 From: EmbeddedMan Date: Wed, 3 Jan 2018 21:21:39 -0600 Subject: [PATCH 4/9] Had to rename repo so that this library could get included in Arduino Library Manager (SodaqMoja hasn't accepted my PR to the original library yet). So Microchip_RN487x -> RN487x. --- Readme.md | 2 +- keywords.txt | 4 ++-- library.properties | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Readme.md b/Readme.md index 75e66e4..c2f4d34 100644 --- a/Readme.md +++ b/Readme.md @@ -1,4 +1,4 @@ -# Microchip_RN487x +# RN487x Arduino library for using the Microchip RN487x BLE module. diff --git a/keywords.txt b/keywords.txt index 2d4499b..620b5f8 100644 --- a/keywords.txt +++ b/keywords.txt @@ -1,11 +1,11 @@ ####################################### -# Syntax Coloring Map For Microchip_RN487x +# Syntax Coloring Map For RN487x ####################################### ####################################### # Datatypes (KEYWORD1) ####################################### -Microchip_RN487x KEYWORD1 +RN487x KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) diff --git a/library.properties b/library.properties index a0bca5c..0681607 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ -name=Microchip_RN487x +name=RN487x version=1.1.0 -author=M16946,Microchip Technology (c) -maintainer=M16946,Brian Schmalz +author=M16946,Microchip Technology (c),Brian Schmalz +maintainer=Brian Schmalz sentence=An Arduino library for the Microchip RN487x paragraph=Command mode support for NR487x BLE modules from Microchip. Updated to work with chipKIT boards. category=Communication -url=https://github.com/SodaqMoja/Microchip_RN487x +url=https://github.com/chipKIT32-libraries/RN487x architectures=* From 71e31279bea5bebeaf69b8a7f267eb65a799d9cb Mon Sep 17 00:00:00 2001 From: EmbeddedMan Date: Wed, 3 Jan 2018 21:27:38 -0600 Subject: [PATCH 5/9] Updated version number in library.properties file. --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 0681607..2eedd45 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=RN487x -version=1.1.0 +version=1.1.1 author=M16946,Microchip Technology (c),Brian Schmalz maintainer=Brian Schmalz sentence=An Arduino library for the Microchip RN487x From d9d1e00434825351d661e41a25147058a8e51d95 Mon Sep 17 00:00:00 2001 From: EmbeddedMan Date: Thu, 4 Jan 2018 06:35:25 -0600 Subject: [PATCH 6/9] Bumped library.properties version to 1.1.2 to match with release tag. --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 2eedd45..c5ca17c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=RN487x -version=1.1.1 +version=1.1.2 author=M16946,Microchip Technology (c),Brian Schmalz maintainer=Brian Schmalz sentence=An Arduino library for the Microchip RN487x From 0e898c9796ee3b7eacc4cd48ec24e174dfba688f Mon Sep 17 00:00:00 2001 From: EmbeddedMan Date: Wed, 31 Jan 2018 21:05:52 -0600 Subject: [PATCH 7/9] Version 1.2.0 of the library. * Reworked examples to compile and run properly on chipKIT boards like Fubarino Mini and RGB Station. --- Readme.md | 2 + examples/BLE_Peripheral/BLE_Peripheral.ino | 296 ------------------ examples/BLE_Scan_all/BLE_Scan_all.ino | 56 +--- .../BLE_Scan_specific/BLE_Scan_specific.ino | 57 +--- examples/BLE_SensorApp/BLE_SensorApp.ino | 25 +- examples/EddystoneURI/EddystoneURI.ino | 56 +--- examples/EddystoneUUID/EddystoneUUID.ino | 57 +--- .../SerialPassthrough/SerialPassthrough.ino | 14 +- examples/iBeacon/iBeacon.ino | 56 +--- library.properties | 2 +- 10 files changed, 59 insertions(+), 562 deletions(-) delete mode 100644 examples/BLE_Peripheral/BLE_Peripheral.ino diff --git a/Readme.md b/Readme.md index c2f4d34..69e5dd3 100644 --- a/Readme.md +++ b/Readme.md @@ -53,6 +53,8 @@ v1.1.0 Release * Added support for PIC32 (chipKIT) * Moved reset and wake pin definitions into hwInit() so that different boards can be supported without editing library +v1.2.0 Release +* Examples updated to work properly with chipKIT boards (like Fubarino Mini and RGB Station) ## License diff --git a/examples/BLE_Peripheral/BLE_Peripheral.ino b/examples/BLE_Peripheral/BLE_Peripheral.ino deleted file mode 100644 index 874fb08..0000000 --- a/examples/BLE_Peripheral/BLE_Peripheral.ino +++ /dev/null @@ -1,296 +0,0 @@ -// BLE_Peripheral.ino -// Author: M16946 -// Date: 2017/01/13 - -/* - (c) 2016 Microchip Technology Inc. and its subsidiaries. You may use this - software and any derivatives exclusively with Microchip products. - - THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER - EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED - WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A - PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION - WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. - - IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, - INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND - WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS - BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE - FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN - ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, - THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. - - MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE - TERMS. -*/ - -#include -#include -#include - -#define debugSerial SerialUSB - -#if defined(ARDUINO_SODAQ_EXPLORER) -#define bleSerial Serial1 -#elif defined(ARDUINO_SODAQ_ONE) || defined(ARDUINO_SODAQ_ONE_BETA) -#define bleSerial Serial -#endif - -#define SERIAL_TIMEOUT 10000 - -#define ADC_AREF 3.3f -#define BATVOLT_R1 4.7f -#define BATVOLT_R2 10.0f - -// Temperature offset for Sodaq One -#define TEMP_OFFSET 20 - -Sodaq_LIS3DE accelerometer; - -const char* myDeviceName = "My SODAQ BOARD" ; // Custom Device name -const char* myPrivateServiceUUID = "AD11CF40063F11E5BE3E0002A5D5C51B" ; // Custom private service UUID -const char* temperatureCharacteristicUUID = "BF3FBD80063F11E59E690002A5D5C501" ; // custom characteristic GATT -const uint8_t temperatureCharacteristicLen = 2 ; // data length (in bytes) -const uint16_t temperatureHandle = 0x72 ; -char temperaturePayload[temperatureCharacteristicLen*2] ; -float temperature_s ; -uint8_t newTempValue_u8 = 0 ; -uint8_t prevTempValue_u8 = 0 ; -const char* ledCharacteristicUUID = "BF3FBD80063F11E59E690002A5D5C503" ; // custom characteristic GATT -const uint8_t ledCharacteristicLen = 6 ; -uint16_t ledHandle = 0x75 ; -const char* ledPayload ; - -void initLed() -{ - #if defined(ARDUINO_SODAQ_EXPLORER) - pinMode(LED_BUILTIN, OUTPUT) ; - #endif - pinMode(LED_RED, OUTPUT) ; - pinMode(LED_GREEN, OUTPUT) ; - pinMode(LED_BLUE, OUTPUT) ; - pinMode(BUTTON, INPUT_PULLUP) ; -} - -void turnBlueLedOn() -{ - #if defined(ARDUINO_SODAQ_EXPLORER) - digitalWrite(LED_BUILTIN, HIGH) ; - #endif -} - -void turnBlueLedOff() -{ - #if defined(ARDUINO_SODAQ_EXPLORER) - digitalWrite(LED_BUILTIN, LOW) ; - #endif -} - -#define COMMON_ANODE // LED driving -void setRgbColor(uint8_t red, uint8_t green, uint8_t blue) -{ -#ifdef COMMON_ANODE - red = 255 - red ; - green = 255 - green ; - blue = 255 - blue ; -#endif - - analogWrite(LED_RED, red) ; - analogWrite(LED_GREEN, green) ; - analogWrite(LED_BLUE, blue) ; -} - -/** - * Init Temperature for ExpLoRer - */ -void initTemperature() -{ - #if defined(ARDUINO_SODAQ_EXPLORER) - pinMode(TEMP_SENSOR, INPUT) ; - //Set ADC resolution to 12 bits - analogReadResolution(12) ; - #endif -} - -/** - * Read ExpLoRer temperature sensor - */ -float getTemperature() -{ - #if defined(ARDUINO_SODAQ_EXPLORER) - float mVolts = (float)analogRead(TEMP_SENSOR) * 3300.0 / 1023.0 ; - #else - float mVolts = (float)getBoardTemperature() * 100 + 500; - #endif - float temp = (mVolts - 500.0) / 100.0 ; - return temp ; -} - -/** - * Initializes the accelerometer or puts it in power-down mode - * for the purpose of reading its temperature delta. -*/ -void setAccelerometerTempSensorActive(bool on) -{ - if (on) { - accelerometer.enable(false, Sodaq_LIS3DE::NormalLowPower100Hz, Sodaq_LIS3DE::XYZ, Sodaq_LIS3DE::Scale2g, true); - delay(300); // should be enough for initilization and 2 measurement periods - } - else { - accelerometer.disable(); - } -} - -/** - * Returns the board temperature. - * SDOAQ One -*/ -float getBoardTemperature() -{ - setAccelerometerTempSensorActive(true); - - float temp = TEMP_OFFSET + accelerometer.getTemperatureDelta(); - - setAccelerometerTempSensorActive(false); - - return temp; -} - -void setup() -{ - while ((!debugSerial) && (millis() < SERIAL_TIMEOUT)) ; - - debugSerial.begin(115200) ; - Wire.begin(); - - initLed() ; - - initTemperature() ; - - // Set the optional debug stream - rn487xBle.setDiag(debugSerial) ; - // Initialize the BLE hardware - rn487xBle.hwInit() ; - // Open the communication pipe with the BLE module - bleSerial.begin(rn487xBle.getDefaultBaudRate()) ; - // Assign the BLE serial port to the BLE library - rn487xBle.initBleStream(&bleSerial) ; - // Finalize the init. process - if (rn487xBle.swInit()) - { - setRgbColor(0, 255, 0) ; - debugSerial.println("Init. procedure done!") ; - } - else - { - setRgbColor(255, 0, 0) ; - debugSerial.println("Init. procedure failed!") ; - while(1) ; - } - - // Fist, enter into command mode - rn487xBle.enterCommandMode() ; - // Stop advertising before starting the demo - rn487xBle.stopAdvertising() ; - // Set the advertising output power (range: min = 5, max = 0) - rn487xBle.setAdvPower(3) ; - // Set the serialized device name - rn487xBle.setSerializedName(myDeviceName) ; - rn487xBle.clearAllServices() ; - rn487xBle.reboot() ; - rn487xBle.enterCommandMode() ; - // Set a private service ... - rn487xBle.setServiceUUID(myPrivateServiceUUID) ; - // which contains ... - // ...a temperature characteristic; readable and can perform notification, 2-octets size - rn487xBle.setCharactUUID(temperatureCharacteristicUUID, READ_PROPERTY | NOTIFY_PROPERTY, temperatureCharacteristicLen) ; - // ...an LED characteristic; properties: writable - rn487xBle.setCharactUUID(ledCharacteristicUUID, WRITE_PROPERTY, ledCharacteristicLen) ; - // take into account the settings by issuing a reboot - rn487xBle.reboot() ; - rn487xBle.enterCommandMode() ; - // Clear adv. packet - rn487xBle.clearImmediateAdvertising() ; - // Start adv. - rn487xBle.startImmediateAdvertising(AD_TYPE_MANUFACTURE_SPECIFIC_DATA, "CD00FE14AD11CF40063F11E5BE3E0002A5D5C51B") ; - - debugSerial.println("Starter Kit as a Peripheral with private service") ; - debugSerial.println("================================================") ; - debugSerial.print("Private service: ") ; debugSerial.println(myPrivateServiceUUID) ; - debugSerial.print("Private characteristic used for the Temperature: ") ; debugSerial.println(temperatureCharacteristicUUID) ; - debugSerial.print("Private characteristic used for the LED: ") ; debugSerial.println(ledCharacteristicUUID) ; - debugSerial.println("You can now establish a connection from the Microchip SmartDiscovery App") ; - debugSerial.print("with the starter kit: ") ; debugSerial.println(rn487xBle.getDeviceName()) ; - -} - -void loop() -{ - // Check the connection status - if (rn487xBle.getConnectionStatus()) - { - // Connected to a peer - debugSerial.print("Connected to a peer central ") ; - debugSerial.println(rn487xBle.getLastResponse()) ; - - // Temperature - prevTempValue_u8 = newTempValue_u8 ; - temperature_s = getTemperature() ; - newTempValue_u8 = (int)temperature_s ; - // Update the local characteristic only if value has changed - if (newTempValue_u8 != prevTempValue_u8) - { - uint8_t data = newTempValue_u8 ; - temperaturePayload[3] = '0' + (data % 10) ; // LSB - data /= 10 ; - temperaturePayload[2] = '0' + (data % 10) ; - data /= 10 ; - temperaturePayload[1] = '0' + (data % 10) ; - if (temperature_s > 0) temperaturePayload[0] = '0' ; // MSB = 0, positive temp. - else temperaturePayload[0] = '8' ; // MSB = 1, negative temp. - - if (rn487xBle.writeLocalCharacteristic(temperatureHandle, temperaturePayload)) - { - debugSerial.print("Temperature characteristic has been updated with the value = ") ; debugSerial.println(newTempValue_u8) ; - } - } - - // LED - if (rn487xBle.readLocalCharacteristic(ledHandle)) - { - // Read the local characteristic written by the client: smartphone/tablet - // The payload must follow the 6-bit RGB coded format: - // [0] Red MSB - // [1] Red LSB - // [2] Green MSB - // [3] Green LSB - // [4] Blue MSB - // [5] Blue LSB - // Each color can be coded from range 0x00 to 0xFF - ledPayload = rn487xBle.getLastResponse() ; - if (ledPayload != NULL) - { - if (ledPayload[0] != 'N') // != "N/A" response - { - debugSerial.println(ledPayload) ; - if (strlen(ledPayload) == ledCharacteristicLen) - { - // Filter only the 6-digit len - // Convert ASCII to integer values - uint8_t r = (ledPayload[0] - '0') * 10 + (ledPayload[1] - '0') ; - uint8_t g = (ledPayload[2] - '0') * 10 + (ledPayload[3] - '0') ; - uint8_t b = (ledPayload[4] - '0') * 10 + (ledPayload[5] - '0') ; - setRgbColor(r, g, b) ; - } - } - } - } - } - else - { - // Not connected to a peer device - debugSerial.println("Not connected to a peer device") ; - } - // Delay inter connection polling - delay(3000) ; -} diff --git a/examples/BLE_Scan_all/BLE_Scan_all.ino b/examples/BLE_Scan_all/BLE_Scan_all.ino index 03d5dff..cda6c35 100644 --- a/examples/BLE_Scan_all/BLE_Scan_all.ino +++ b/examples/BLE_Scan_all/BLE_Scan_all.ino @@ -1,6 +1,7 @@ -// Scanner.ino -// Author: M16946 -// Date: 2017/01/13 +/* BLE_Scan_all + * Based on work by M16946 (2017/01/13) for Microchip. + * Modified by Brian Schmalz of Schmalz Haus LLC (brian@schmalzhaus.com) also for Microchip, Dec 2017 + */ /* (c) 2016 Microchip Technology Inc. and its subsidiaries. You may use this @@ -27,62 +28,17 @@ #include #include -#define debugSerial SerialUSB -#if defined(ARDUINO_SODAQ_EXPLORER) +#define debugSerial Serial #define bleSerial Serial1 -#else -#define bleSerial Serial -#endif #define SERIAL_TIMEOUT 10000 -void initLed() -{ - #if defined(ARDUINO_SODAQ_EXPLORER) - pinMode(LED_BUILTIN, OUTPUT) ; - #endif - pinMode(LED_RED, OUTPUT) ; - pinMode(LED_GREEN, OUTPUT) ; - pinMode(LED_BLUE, OUTPUT) ; - pinMode(BUTTON, INPUT_PULLUP) ; -} - -void turnBlueLedOn() -{ - #if defined(ARDUINO_SODAQ_EXPLORER) - digitalWrite(LED_BUILTIN, HIGH) ; - #endif -} - -void turnBlueLedOff() -{ - #if defined(ARDUINO_SODAQ_EXPLORER) - digitalWrite(LED_BUILTIN, LOW) ; - #endif -} - -#define COMMON_ANODE // LED driving -void setRgbColor(uint8_t red, uint8_t green, uint8_t blue) -{ -#ifdef COMMON_ANODE - red = 255 - red ; - green = 255 - green ; - blue = 255 - blue ; -#endif - - analogWrite(LED_RED, red) ; - analogWrite(LED_GREEN, green) ; - analogWrite(LED_BLUE, blue) ; -} - void setup() { while ((!debugSerial) && (millis() < SERIAL_TIMEOUT)) ; debugSerial.begin(115200) ; - initLed() ; - // Set the optional debug stream rn487xBle.setDiag(debugSerial) ; // Initialize the BLE hardware @@ -94,12 +50,10 @@ void setup() // Finalize the init. process if (rn487xBle.swInit()) { - setRgbColor(0, 255, 0) ; debugSerial.println("Init. procedure done!") ; } else { - setRgbColor(255, 0, 0) ; debugSerial.println("Init. procedure failed!") ; while(1) ; } diff --git a/examples/BLE_Scan_specific/BLE_Scan_specific.ino b/examples/BLE_Scan_specific/BLE_Scan_specific.ino index 393d96f..05a209a 100644 --- a/examples/BLE_Scan_specific/BLE_Scan_specific.ino +++ b/examples/BLE_Scan_specific/BLE_Scan_specific.ino @@ -1,6 +1,7 @@ -// BLE_Scan_whiteList.ino -// Author: M16946 -// Date: 2017/01/13 +/* BLE_Scan_specific + * Based on work by M16946 (2017/01/13) for Microchip. + * Modified by Brian Schmalz of Schmalz Haus LLC (brian@schmalzhaus.com) also for Microchip, Dec 2017 + */ /* (c) 2016 Microchip Technology Inc. and its subsidiaries. You may use this @@ -27,64 +28,20 @@ #include #include -#define debugSerial SerialUSB -#if defined(ARDUINO_SODAQ_EXPLORER) +#define debugSerial Serial #define bleSerial Serial1 -#else -#define bleSerial Serial -#endif + #define SERIAL_TIMEOUT 10000 // MAC address added to the white list const char* peerAddressToScan = "F0A1B40302D3" ; -void initLed() -{ - #if defined(ARDUINO_SODAQ_EXPLORER) - pinMode(LED_BUILTIN, OUTPUT) ; - #endif - pinMode(LED_RED, OUTPUT) ; - pinMode(LED_GREEN, OUTPUT) ; - pinMode(LED_BLUE, OUTPUT) ; - pinMode(BUTTON, INPUT_PULLUP) ; -} - -void turnBlueLedOn() -{ - #if defined(ARDUINO_SODAQ_EXPLORER) - digitalWrite(LED_BUILTIN, HIGH) ; - #endif -} - -void turnBlueLedOff() -{ - #if defined(ARDUINO_SODAQ_EXPLORER) - digitalWrite(LED_BUILTIN, LOW) ; - #endif -} - -#define COMMON_ANODE // LED driving -void setRgbColor(uint8_t red, uint8_t green, uint8_t blue) -{ -#ifdef COMMON_ANODE - red = 255 - red ; - green = 255 - green ; - blue = 255 - blue ; -#endif - - analogWrite(LED_RED, red) ; - analogWrite(LED_GREEN, green) ; - analogWrite(LED_BLUE, blue) ; -} - void setup() { while ((!debugSerial) && (millis() < SERIAL_TIMEOUT)) ; debugSerial.begin(115200) ; - initLed() ; - // Set the optional debug stream rn487xBle.setDiag(debugSerial) ; // Initialize the BLE hardware @@ -96,12 +53,10 @@ void setup() // Finalize the init. process if (rn487xBle.swInit()) { - setRgbColor(0, 255, 0) ; debugSerial.println("Init. procedure done!") ; } else { - setRgbColor(255, 0, 0) ; debugSerial.println("Init. procedure failed!") ; while(1) ; } diff --git a/examples/BLE_SensorApp/BLE_SensorApp.ino b/examples/BLE_SensorApp/BLE_SensorApp.ino index f6f3406..b1c3920 100644 --- a/examples/BLE_SensorApp/BLE_SensorApp.ino +++ b/examples/BLE_SensorApp/BLE_SensorApp.ino @@ -1,12 +1,20 @@ +/* Sample sketch for illustrating BLE communications with a mobile device app. + * Designed to be used with a chipKIT Fubarino Mini board, but can be used with any Arduino + * compatible board. Uses Microchip's RN4870 or RN4871 BLE module. + * See https://chipkit.net/wiki/index.php?title=Basic_BLE for a tutorial explaining this sketch. + * + * Written by Brian Schmalz (brian@schmalzhaus.com) for Microchip, fall 2017. + * Based on an example from https://github.com/SodaqMoja/Microchip_RN487x + * This sketch is in the public domain + */ + #include #include #include -#define debugSerial Serial -#define bleSerial Serial1 - -//#define BLUETOOTH_WAKE 12 -//#define BT_RESET 7 +/* These are the serial ports to use with a Fubarino Mini. Edit for your hardware setup. */ +#define debugSerial Serial // Serial is Fubarini Mini's USB port +#define bleSerial Serial1 // Serial1 is UART2 on pins 26 (TX) and 25 (RX) to BLE module /* Analog pin that temp sensor is connected to */ #define TEMP_SENSOR A0 @@ -96,8 +104,8 @@ void setup() // Set the optional debug stream rn487xBle.setDiag(debugSerial); - // Initialize the BLE hardware with our sleep and wakeup pins - rn487xBle.hwInit(BT_RESET, BLUETOOTH_WAKE); + // Initialize the BLE hardware + rn487xBle.hwInit(); // Open the communication pipe with the BLE module bleSerial.begin(rn487xBle.getDefaultBaudRate()); // Assign the BLE serial port to the BLE library @@ -256,5 +264,4 @@ void loop() // Delay inter connection polling - when not connected, check for new connections ever 1 second delay(1000); } -} - +} \ No newline at end of file diff --git a/examples/EddystoneURI/EddystoneURI.ino b/examples/EddystoneURI/EddystoneURI.ino index 72f14e1..c128886 100644 --- a/examples/EddystoneURI/EddystoneURI.ino +++ b/examples/EddystoneURI/EddystoneURI.ino @@ -1,6 +1,7 @@ -// Eddystone.ino -// Author: M16946 -// Date: 2017/01/13 +/* EddystoneURI + * Based on work by M16946 (2017/01/13) for Microchip. + * Modified by Brian Schmalz of Schmalz Haus LLC (brian@schmalzhaus.com) also for Microchip, Dec 2017 + */ /* (c) 2016 Microchip Technology Inc. and its subsidiaries. You may use this @@ -28,65 +29,20 @@ #include #include -#define debugSerial SerialUSB -#if defined(ARDUINO_SODAQ_EXPLORER) +#define debugSerial Serial #define bleSerial Serial1 -#else -#define bleSerial Serial -#endif #define SERIAL_TIMEOUT 10000 const char* myEddystoneURI = "http://www.microchip.com" ; const uint8_t myTxPower = 0xC5 ; -void initLed() -{ - #if defined(ARDUINO_SODAQ_EXPLORER) - pinMode(LED_BUILTIN, OUTPUT) ; - #endif - pinMode(LED_RED, OUTPUT) ; - pinMode(LED_GREEN, OUTPUT) ; - pinMode(LED_BLUE, OUTPUT) ; - pinMode(BUTTON, INPUT_PULLUP) ; -} - -void turnBlueLedOn() -{ - #if defined(ARDUINO_SODAQ_EXPLORER) - digitalWrite(LED_BUILTIN, HIGH) ; - #endif -} - -void turnBlueLedOff() -{ - #if defined(ARDUINO_SODAQ_EXPLORER) - digitalWrite(LED_BUILTIN, LOW) ; - #endif -} - -#define COMMON_ANODE // LED driving -void setRgbColor(uint8_t red, uint8_t green, uint8_t blue) -{ -#ifdef COMMON_ANODE - red = 255 - red ; - green = 255 - green ; - blue = 255 - blue ; -#endif - - analogWrite(LED_RED, red) ; - analogWrite(LED_GREEN, green) ; - analogWrite(LED_BLUE, blue) ; -} - void setup() { while ((!debugSerial) && (millis() < SERIAL_TIMEOUT)) ; debugSerial.begin(115200) ; - initLed() ; - // Set the optional debug stream rn487xBle.setDiag(debugSerial) ; // Initialize the BLE hardware @@ -98,12 +54,10 @@ void setup() // Finalize the init. process if (rn487xBle.swInit()) { - setRgbColor(0, 255, 0) ; debugSerial.println("Init. procedure done!") ; } else { - setRgbColor(255, 0, 0) ; debugSerial.println("Init. procedure failed!") ; while(1) ; } diff --git a/examples/EddystoneUUID/EddystoneUUID.ino b/examples/EddystoneUUID/EddystoneUUID.ino index 9c3661e..34bf332 100644 --- a/examples/EddystoneUUID/EddystoneUUID.ino +++ b/examples/EddystoneUUID/EddystoneUUID.ino @@ -1,6 +1,7 @@ -// EddystoneUUID.ino -// Author: M16946 -// Date: 2017/01/13 +/* EddystoneUUID + * Based on work by M16946 (2017/01/13) for Microchip. + * Modified by Brian Schmalz of Schmalz Haus LLC (brian@schmalzhaus.com) also for Microchip, Dec 2017 + */ /* (c) 2016 Microchip Technology Inc. and its subsidiaries. You may use this @@ -28,64 +29,20 @@ #include #include -#define debugSerial SerialUSB -#if defined(ARDUINO_SODAQ_EXPLORER) +#define debugSerial Serial #define bleSerial Serial1 -#else -#define bleSerial Serial -#endif + #define SERIAL_TIMEOUT 10000 const char* myEddystoneUUID = "AD11CF40063F11E5BE3E0002A5D5C51B" ; const uint8_t myTxPower = 0xC5 ; -void initLed() -{ - #if defined(ARDUINO_SODAQ_EXPLORER) - pinMode(LED_BUILTIN, OUTPUT) ; - #endif - pinMode(LED_RED, OUTPUT) ; - pinMode(LED_GREEN, OUTPUT) ; - pinMode(LED_BLUE, OUTPUT) ; - pinMode(BUTTON, INPUT_PULLUP) ; -} - -void turnBlueLedOn() -{ - #if defined(ARDUINO_SODAQ_EXPLORER) - digitalWrite(LED_BUILTIN, HIGH) ; - #endif -} - -void turnBlueLedOff() -{ - #if defined(ARDUINO_SODAQ_EXPLORER) - digitalWrite(LED_BUILTIN, LOW) ; - #endif -} - -#define COMMON_ANODE // LED driving -void setRgbColor(uint8_t red, uint8_t green, uint8_t blue) -{ -#ifdef COMMON_ANODE - red = 255 - red ; - green = 255 - green ; - blue = 255 - blue ; -#endif - - analogWrite(LED_RED, red) ; - analogWrite(LED_GREEN, green) ; - analogWrite(LED_BLUE, blue) ; -} - void setup() { while ((!debugSerial) && (millis() < SERIAL_TIMEOUT)) ; debugSerial.begin(115200) ; - initLed() ; - // Set the optional debug stream rn487xBle.setDiag(debugSerial) ; // Initialize the BLE hardware @@ -97,12 +54,10 @@ void setup() // Finalize the init. process if (rn487xBle.swInit()) { - setRgbColor(0, 255, 0) ; debugSerial.println("Init. procedure done!") ; } else { - setRgbColor(255, 0, 0) ; debugSerial.println("Init. procedure failed!") ; while(1) ; } diff --git a/examples/SerialPassthrough/SerialPassthrough.ino b/examples/SerialPassthrough/SerialPassthrough.ino index 4d973fa..8972b25 100644 --- a/examples/SerialPassthrough/SerialPassthrough.ino +++ b/examples/SerialPassthrough/SerialPassthrough.ino @@ -1,4 +1,16 @@ -#define BLE_MODE_PIN 6 +/* SerialPassthrough + * Written by Brian Schmalz of Schmalz Haus LLC (brian@schmalzhaus.com) for Microchip, Dec 2017 + * + * This sketch simply provides a way to directly talk to an RN4870 or RN4871 module. It assumes that + * the USB serial connection is Serial, and the serial connection to the BLE module is on Serial1. + * + * If you open up a terminal emulator like TeraTerm and connect to your board's serial port, you can + * talk through the microcontroller to the BLE module. This is very useful for figuring out what commands + * the BLE module understand, and debugging connection problems. + */ + +/* These pins are correct for RGB Station boards. Adjust to fit your hardware. */ +#define BLE_MODE_PIN 21 #define BLE_RESET_PIN 7 void setup() { diff --git a/examples/iBeacon/iBeacon.ino b/examples/iBeacon/iBeacon.ino index 06c5a2a..ae73a7c 100644 --- a/examples/iBeacon/iBeacon.ino +++ b/examples/iBeacon/iBeacon.ino @@ -1,6 +1,7 @@ -// iBeacon.ino -// Author: M16946 -// Date: 2017/01/13 +/* iBeacon + * Based on work by M16946 (2017/01/13) for Microchip. + * Modified by Brian Schmalz of Schmalz Haus LLC (brian@schmalzhaus.com) also for Microchip, Dec 2017 + */ /* (c) 2016 Microchip Technology Inc. and its subsidiaries. You may use this @@ -28,12 +29,8 @@ #include #include -#define debugSerial SerialUSB -#if defined(ARDUINO_SODAQ_EXPLORER) +#define debugSerial Serial #define bleSerial Serial1 -#else -#define bleSerial Serial -#endif #define SERIAL_TIMEOUT 10000 @@ -42,53 +39,12 @@ const uint16_t myMajor = 0x0C ; const uint16_t myMinor = 0x0D ; const uint8_t myTxPower = 0xC5 ; -void initLed() -{ - #if defined(ARDUINO_SODAQ_EXPLORER) - pinMode(LED_BUILTIN, OUTPUT) ; - #endif - pinMode(LED_RED, OUTPUT) ; - pinMode(LED_GREEN, OUTPUT) ; - pinMode(LED_BLUE, OUTPUT) ; - pinMode(BUTTON, INPUT_PULLUP) ; -} - -void turnBlueLedOn() -{ - #if defined(ARDUINO_SODAQ_EXPLORER) - digitalWrite(LED_BUILTIN, HIGH) ; - #endif -} - -void turnBlueLedOff() -{ - #if defined(ARDUINO_SODAQ_EXPLORER) - digitalWrite(LED_BUILTIN, LOW) ; - #endif -} - -#define COMMON_ANODE // LED driving -void setRgbColor(uint8_t red, uint8_t green, uint8_t blue) -{ -#ifdef COMMON_ANODE - red = 255 - red ; - green = 255 - green ; - blue = 255 - blue ; -#endif - - analogWrite(LED_RED, red) ; - analogWrite(LED_GREEN, green) ; - analogWrite(LED_BLUE, blue) ; -} - void setup() { while ((!debugSerial) && (millis() < SERIAL_TIMEOUT)) ; debugSerial.begin(115200) ; - initLed() ; - // Set the optional debug stream rn487xBle.setDiag(debugSerial) ; // Initialize the BLE hardware @@ -100,12 +56,10 @@ void setup() // Finalize the init. process if (rn487xBle.swInit()) { - setRgbColor(0, 255, 0) ; debugSerial.println("Init. procedure done!") ; } else { - setRgbColor(255, 0, 0) ; debugSerial.println("Init. procedure failed!") ; while(1) ; } diff --git a/library.properties b/library.properties index c5ca17c..3edc7c8 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=RN487x -version=1.1.2 +version=1.2.0 author=M16946,Microchip Technology (c),Brian Schmalz maintainer=Brian Schmalz sentence=An Arduino library for the Microchip RN487x From 1967e07de887683c3a593f62bfe7a338dfd3a96f Mon Sep 17 00:00:00 2001 From: per1234 Date: Mon, 16 Jul 2018 15:57:12 -0700 Subject: [PATCH 8/9] Remove leading space from keywords.txt identifier token Each field of keywords.txt is separated by a single true tab. Leading spaces on a keyword identifier causes it to not be recognized by the Arduino IDE. On Arduino IDE 1.6.5 and newer an unrecognized keyword identifier causes the default editor.function.style highlighting to be used (as with KEYWORD2, KEYWORD3). Reference: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#keywords --- keywords.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keywords.txt b/keywords.txt index 620b5f8..43a3d3b 100644 --- a/keywords.txt +++ b/keywords.txt @@ -5,7 +5,7 @@ ####################################### # Datatypes (KEYWORD1) ####################################### -RN487x KEYWORD1 +RN487x KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) From 8cb943e911fd58c7a0365969fe96fa9d38f80319 Mon Sep 17 00:00:00 2001 From: Majenko Technologies Date: Fri, 23 Nov 2018 14:55:17 +0000 Subject: [PATCH 9/9] Create uecide.json This file allows automatic packaging in UECIDE --- uecide.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 uecide.json diff --git a/uecide.json b/uecide.json new file mode 100644 index 0000000..f11e43f --- /dev/null +++ b/uecide.json @@ -0,0 +1,19 @@ +{ + "name": "RN487x", + "provides": "RN487x_BLE.h", + "license": "Readme.md", + "readme": "Readme.md", + "description": "Microchip RN487x BLE module", + "category": "Communications", + "subcategory": "Wireless", + "maintainer": "Brian Schmalz ", + "version": "1.2.0", + "family": "pic32", + "core": "chipkit", + "install": { + "examples": "/", + "src": "/", + "keywords.txt": "/", + "library.properties": "/" + } +}