You can control from iPhone and put some command. h=show commands help, v=show TY51822r3 VDD data, t=show chip temperature, q=you can make deep sleep condition.
Dependencies: BLE_API mbed nRF51822 nRF51_Vdd nRF51_WakeUp nRF51_LowPwr
Fork of BLE_LoopbackUART by
Please refer follows.
/users/kenjiArai/notebook/ty51822r3-current-consumption-using-nrf51_wakeup-l/#
Diff: main.cpp
- Revision:
- 14:f9b4d659d717
- Parent:
- 13:15764cc1f12c
- Child:
- 15:d7764da3f37c
--- a/main.cpp Tue Sep 29 12:02:15 2015 +0000 +++ b/main.cpp Sat Apr 02 06:35:44 2016 +0000 @@ -14,72 +14,351 @@ * limitations under the License. */ -#include "mbed.h" -#include "ble/BLE.h" +/* + * /////// Tested on Switch Science mbed TY51822r3 /////// + * Modified by Kenji Arai + * http://www.page.sannet.ne.jp/kenjia/index.html + * http://mbed.org/users/kenjiArai/ + * + * Started: March 7th, 2016 + * Revised: March 30th, 2016 + * + * Original program: + * BLE_LoopbackUART + * https://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_LoopbackUART/ + * Tested Controller Device: + * iPhone6 nRF UART by Nordic + * https://itunes.apple.com/us/app/nrf-uart/id614594903?mt=8 + * + */ -#include "ble/services/UARTService.h" +// Include --------------------------------------------------------------------------------------- +#include <string.h> +#include "mbed.h" +#include "BLE.h" +#include "UARTService.h" +#include "nRF51_Vdd.h" +#include "nRF51_WakeUp.h" -#define NEED_CONSOLE_OUTPUT 0 /* Set this if you need debug messages on the console; - * it will have an impact on code-size and power consumption. */ - +// Definition ------------------------------------------------------------------------------------ +#define NEED_CONSOLE_OUTPUT 1 /* Set this if you need debug messages on the console; + * it will have an impact on code-size and power consumption. */ #if NEED_CONSOLE_OUTPUT #define DEBUG(...) { printf(__VA_ARGS__); } #else #define DEBUG(...) /* nothing */ #endif /* #if NEED_CONSOLE_OUTPUT */ -BLEDevice ble; -DigitalOut led1(LED1); +#define HIGH_PWR 1 +#define TXRX_BUF_LEN 22 // send & receive number = 20 +#define PWR_RANG_NO 8 -UARTService *uartServicePtr; +enum TX_Content { + TX_VDD = 1, + TX_TEMP, + TX_PWR_UP, + TX_PWR_DWN, + TX_QUIT, + TX_HELP + }; -void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) -{ - DEBUG("Disconnected!\n\r"); - DEBUG("Restarting the advertising process\n\r"); - ble.startAdvertising(); -} +// Object ---------------------------------------------------------------------------------------- +BLEDevice ble; +DigitalOut myled(LED2); +InterruptIn wake_up_sw(P0_1); // If you change P0_1, you also need to change PORT_OUTPUT. +nRF51_WakeUp wakeup(LED1, P0_0); +nRF51_Vdd vdd(3.0f, 2.2f); +UARTService *uartServicePtr; +Ticker ticker; +#if DEBUG +Serial pc(P0_4,P0_0); +#endif + +// ROM / Constant data --------------------------------------------------------------------------- +const char *deviceName = "JH1PJL"; +const uint8_t pwr_range[PWR_RANG_NO] = + { + RADIO_TXPOWER_TXPOWER_Neg30dBm,/*!< -30dBm. */ + RADIO_TXPOWER_TXPOWER_Neg20dBm,/*!< -20dBm. */ + RADIO_TXPOWER_TXPOWER_Neg16dBm,/*!< -16dBm. */ + RADIO_TXPOWER_TXPOWER_Neg12dBm,/*!< -12dBm. */ + RADIO_TXPOWER_TXPOWER_Neg8dBm, /*!< -8dBm. */ + RADIO_TXPOWER_TXPOWER_Neg4dBm, /*!< -4dBm. */ + RADIO_TXPOWER_TXPOWER_0dBm, /*!< 0dBm. */ + RADIO_TXPOWER_TXPOWER_Pos4dBm, /*!< +4dBm. */ + }; -void onDataWritten(const GattWriteCallbackParams *params) -{ - if ((uartServicePtr != NULL) && (params->handle == uartServicePtr->getTXCharacteristicHandle())) { - uint16_t bytesRead = params->len; - DEBUG("received %u bytes\n\r", bytesRead); - ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), params->data, bytesRead); - } -} +// RAM ------------------------------------------------------------------------------------------- +uint8_t tx_buf[TXRX_BUF_LEN]; +uint8_t tx_len=0; +uint8_t time_data[TXRX_BUF_LEN]; +uint8_t pwr_selection; +volatile bool trigger_transmit = false; +volatile bool trigger_receive = false; +volatile uint8_t command_continue = 0; +TX_Content transmit_contents; +uint8_t time_out_cntr = 120; +volatile bool time_out = false; -void periodicCallback(void) -{ - led1 = !led1; -} +// Function prototypes --------------------------------------------------------------------------- +// BLE +void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params); +void onDataWritten(const GattWriteCallbackParams *params); +void periodicCallback(void); +// Application related +void action_tx_help(void); +void action_tx_vdd(void); +void action_tx_temperature(void); +void action_tx_pwrup(void); +void action_tx_pwrdwn(void); +void fill_space_n(uint8_t *bf, uint8_t n); +void Update_Values(void); +// Interrupt related +void action_tx_quit(void); +void interrupt_by_sw(void); -int main(void) -{ - led1 = 1; - Ticker ticker; +//------------------------------------------------------------------------------------------------- +// Control Program +//------------------------------------------------------------------------------------------------- +int main(void){ + myled = 1; ticker.attach(periodicCallback, 1); - - DEBUG("Initialising the nRF51822\n\r"); + // Interrupt by switch + wake_up_sw.fall(&interrupt_by_sw); + DEBUG("Initialising the nRF51822\r\n"); ble.init(); + //ble.setDeviceName((const uint8_t *)deviceName); ble.onDisconnection(disconnectionCallback); ble.onDataWritten(onDataWritten); - /* setup advertising */ ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED); ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, - (const uint8_t *)"BLE UART", sizeof("BLE UART") - 1); + (const uint8_t *)deviceName, + strlen(deviceName) + ); ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, - (const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed)); - + (const uint8_t *)UARTServiceUUID_reversed, + sizeof(UARTServiceUUID_reversed) + ); + // Power +#if HIGH_PWR + pwr_selection = 7; +#else + pwr_selection = 0; +#endif + ble.gap().setTxPower(pwr_range[pwr_selection]); + // Advertize Interval ble.setAdvertisingInterval(1000); /* 1000ms; in multiples of 0.625ms. */ + // Start ble.startAdvertising(); - UARTService uartService(ble); uartServicePtr = &uartService; + while(true){ + if (time_out){ + myled = 0; + wakeup.set_and_wait(120); + while(true){ // never come here but just in case + deepsleep(); + } + } + if (trigger_transmit){ + trigger_transmit = false; + switch(transmit_contents){ + case TX_VDD: + action_tx_vdd(); + break; + case TX_TEMP: + action_tx_temperature(); + break; + case TX_QUIT: + action_tx_quit(); + break; + case TX_PWR_UP: + action_tx_pwrup(); + break; + case TX_PWR_DWN: + action_tx_pwrdwn(); + break; + case TX_HELP: + action_tx_help(); + break; + default: + break; + } + } else { + myled = !myled; + ble.waitForEvent(); + } + } +} - while (true) { - ble.waitForEvent(); +void onDataWritten(const GattWriteCallbackParams *params){ + uint8_t buf[TXRX_BUF_LEN]; + uint16_t bytesRead; + + if ((uartServicePtr != NULL) && + (params->handle == uartServicePtr->getTXCharacteristicHandle())) + { + strcpy((char *)buf, (const char *)params->data); + bytesRead = params->len; + switch (buf[0]){ + case 'v': + trigger_transmit = true; + transmit_contents = TX_VDD; + break; + case 't': + trigger_transmit = true; + transmit_contents = TX_TEMP; + break; + case 'u': + trigger_transmit = true; + transmit_contents = TX_PWR_UP; + break; + case 'd': + trigger_transmit = true; + transmit_contents = TX_PWR_DWN; + break; + case 'q': + trigger_transmit = true; + transmit_contents = TX_QUIT; + break; + case 'h': + case '?': + trigger_transmit = true; + transmit_contents = TX_HELP; + break; + default: + break; + } + fill_space_n(buf, bytesRead); + DEBUG("RX_data\r\n"); + DEBUG("Length: %d\r\n", bytesRead); + DEBUG("Data: "); + DEBUG("%s", buf); + DEBUG("\r\n"); } } + +void action_tx_help(){ + // 12345678901234567890 + sprintf((char *)tx_buf,"?:help by JH1PJL"); + tx_len = strlen((const char *)tx_buf); + Update_Values(); + wait(0.1); + // 12345678901234567890 + sprintf((char *)tx_buf,"v:vdd"); + tx_len = strlen((const char *)tx_buf); + Update_Values(); + wait(0.1); + // 12345678901234567890 + sprintf((char *)tx_buf,"t:temperature"); + tx_len = strlen((const char *)tx_buf); + Update_Values(); + wait(0.1); + // 12345678901234567890 + sprintf((char *)tx_buf,"u:power up"); + tx_len = strlen((const char *)tx_buf); + Update_Values(); + wait(0.1); + // 12345678901234567890 + sprintf((char *)tx_buf,"d:power down"); + tx_len = strlen((const char *)tx_buf); + Update_Values(); + wait(0.1); + // 12345678901234567890 + sprintf((char *)tx_buf,"q(0x71):quit/sleep"); + tx_len = strlen((const char *)tx_buf); + Update_Values(); +} + +void action_tx_pwrup(){ + if (pwr_selection != 0){ + --pwr_selection; + } + ble.gap().setTxPower(pwr_range[pwr_selection]); + sprintf((char *)tx_buf,"Pwr:%+ddBm", (4 - (pwr_selection * 4))); + tx_len = strlen((const char *)tx_buf); + Update_Values(); +} + +void action_tx_pwrdwn(){ + if (pwr_selection != (PWR_RANG_NO - 1)){ + ++pwr_selection; + } + ble.gap().setTxPower(pwr_range[pwr_selection]); + sprintf((char *)tx_buf,"Pwr:%+ddBm", (4 - (pwr_selection * 4))); + tx_len = strlen((const char *)tx_buf); + Update_Values(); +} + +void action_tx_vdd(){ + sprintf((char *)tx_buf,"Vdd:%3.2fV", vdd.read_real_value()); + tx_len = strlen((const char *)tx_buf); + Update_Values(); +} + +void action_tx_temperature(){ + int32_t p_temp; + float temperature; + + // Update a temperature (inside nRF51822 chip) + sd_temp_get(&p_temp); + // -16.0f is offset vale for chip die temp to ambient temp (depend on your board) + temperature = float(p_temp) / 4; // Original = float(p_temp)/4.0f - 16.0f; + sprintf((char *)tx_buf,"T:%+4.1fdC", temperature); + tx_len = strlen((const char *)tx_buf); + Update_Values(); +} + +void action_tx_quit(){ + ticker.detach(); + // 12345678901234567890 + sprintf((char *)tx_buf,"Terminated the BLE"); + tx_len = strlen((const char *)tx_buf); + Update_Values(); + myled = 0; + wait(1.0); + wakeup.set_and_wait(120); + while(true){ // never come here but just in case + deepsleep(); + } +} + +void interrupt_by_sw(){ // Go to sleep + NVIC_SystemReset(); + // Not come here (Just in case) + deepsleep(); +} + +void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params){ + DEBUG("Disconnected!\r\n"); + DEBUG("Restarting the advertising process\r\n"); + ble.startAdvertising(); +} + +void periodicCallback(void){ + if (--time_out_cntr == 0){ + time_out = true; + } +} + +void fill_space_n(uint8_t *bf, uint8_t n){ + bf += n; + for (uint8_t i = n; i <= 20; bf++, i++){ + *bf = ' '; + } + *bf = '.'; + *(bf + 1) = 0; +} + +void Update_Values(void){ + ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), + tx_buf, + tx_len + ); + DEBUG("TX_data: %s\r\n", tx_buf); + DEBUG("Length: %d\r\n", tx_len); + tx_len = 0; +} +