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 Bluetooth Low Energy

Please refer follows.
/users/kenjiArai/notebook/ty51822r3-current-consumption-using-nrf51_wakeup-l/#

main.cpp

Committer:
kenjiArai
Date:
2016-06-11
Revision:
16:c8f4e56fa239
Parent:
15:d7764da3f37c

File content as of revision 16:c8f4e56fa239:

/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 *  /////// 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:    June      11th, 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 ---------------------------------------------------------------------------------------
#include <string.h>
#include "mbed.h"
#include "BLE.h"
#include "UARTService.h"
#include "nRF51_Vdd.h"
#include "nRF51_WakeUp.h"
#include "nRF51_lowpwr.h"

//  Definition ------------------------------------------------------------------------------------
//  Before using this function, please specify your program are used following functions or not.
#define    USE_DEVICE_STDIO_MESSAGES       0   // printf
#define    USE_DEVICE_SERIAL               0   // Serial or DEBUG & etc.
#define    USE_DEVICE_I2C                  0   // Sensors with I2C, LCD, EEPROM, Driver chips & etc.
#define    USE_DEVICE_SPI                  0   // Sensors with SOI, LCD, EEPROM, Driver chips & etc.
#define    USE_DEVICE_SPISLAVE             0   // Communication with master vis SPI
#define    USE_DEVICE_PWMOUT               0   // PWM duty output, Serve & etc.
#define    USE_DEVICE_ANALOGIN             0   // Analog adc

#if USE_DEVICE_STDIO_MESSAGES   // See disable_cpu_functions.h
#define DEBUG(...) { printf(__VA_ARGS__); }
#else
#define DEBUG(...)
#endif

#define HIGH_PWR                1
#define TXRX_BUF_LEN            22              // send & receive number = 20
#define PWR_RANG_NO             8

enum TX_Content {
                TX_VDD = 1,
                TX_TEMP,
                TX_PWR_UP,
                TX_PWR_DWN,
                TX_QUIT,
                TX_HELP
                };

//  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, ONLY4VDD);
UARTService     *uartServicePtr;
Ticker          ticker;
#if USE_DEVICE_STDIO_MESSAGES
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.  */
                    };
const nRF51_LOWPWR_TypeDef lowpwr_table = 
                    {
                    #if USE_DEVICE_STDIO_MESSAGES 
                        true,
                    #else
                        false,
                    #endif
                    #if USE_DEVICE_SERIAL
                        true,
                    #else
                        false,
                    #endif
                    #if USE_DEVICE_I2C
                        true,
                    #else
                        false,
                    #endif
                    #if USE_DEVICE_SPI
                        true,
                    #else
                        false,
                    #endif
                    #if USE_DEVICE_SPISLAVE
                        true,
                    #else
                        false,
                    #endif
                    #if USE_DEVICE_PWMOUT
                        true,
                    #else
                        false,
                    #endif
                    #if USE_DEVICE_ANALOGIN
                        true
                    #else
                        false
                    #endif
                    };

//  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 = 30;
volatile bool time_out = false;

//  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);

//-------------------------------------------------------------------------------------------------
//  Control Program
//-------------------------------------------------------------------------------------------------
int main(void){
    LowPwr set_lowpwr(&lowpwr_table);
    myled = 1;
    ticker.attach(periodicCallback, 1);
    // 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 *)deviceName,
                                     strlen(deviceName)
                                    );
    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
                                    (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(30);
            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();
        }
    }
}

void led_control(float t){
    myled = !myled;
    wait(t);
}

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(30);
    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;
}