First Revision of sample code for interfacing ROHM Multi-Sensor Shield board with Nordic Semiconductor's nRF51-DK Development Kit Host BTLE Board

Dependencies:   BLE_API mbed nRF51822 Nordic_UART_TEMPLATE_ROHM

Dependents:   Nordic_UART_TEMPLATE_ROHM

Fork of UART_TEMPLATE by daniel veilleux

Code Example for ROHM Multi-Sensor Shield on the Nordic Semiconductor nRF51-DK

This code was written to be used with the Nordic Semiconductor nRF51-DK.

This is the basic example code for interfacing ROHM's Multi-sensor Shield Board onto this board.

Additional information about the ROHM MultiSensor Shield Board can be found at the following link: https://github.com/ROHMUSDC/ROHM_SensorPlatform_Multi-Sensor-Shield

For code example for the ROHM SENSORSHLD1-EVK-101, please see the following link: https://developer.mbed.org/teams/ROHMUSDC/code/Nordic_UART_TEMPLATE_ROHM_SHLD1Update/

Operation

Ultimately, this code will initialize all the sensors on the Multi-sensor shield board and then poll the sensors. The sensor data will then be returned to the BTLE COM port link and will be view-able on any BTLE enabled phone that can connect to the Nordic UART Application.

Supported ROHM Sensor Devices

  • BDE0600G Temperature Sensor
  • BM1383GLV Pressure Sensor
  • BU52014 Hall Sensor
  • ML8511 UV Sensor
  • RPR-0521 ALS/PROX Sensor
  • BH1745NUC Color Sensor
  • KMX62 Accel/Mag Sensor
  • KX122 Accel Sensor
  • KXG03 Gyro/Accel Sensor

Sensor Applicable Code Sections

  • Added a Section in "Main" to act as initialization
  • Added to the "Periodic Callback" to read sensor data and return to Phone/Host

Questions/Feedback

Please feel free to let us know any questions/feedback/comments/concerns on the shield implementation by contacting the following e-mail:

main.cpp

Committer:
kbahar3
Date:
2015-07-19
Revision:
1:2c0ab5cd1a7f
Parent:
0:442c7a6f1978
Child:
2:c7b9d588c80f

File content as of revision 1:2c0ab5cd1a7f:

/* 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.
 */

#define AnalogALS   //BH1620    //Change 0: Remove this completely
#define AnalogTemp  //BDE0600
#define AnalogUV    //ML8511
#define HallSensor  //BU52011   //Change 1: Change to use GPIO for BU52014
#define DigitalALS  //BH1721    //Change 2: Remove This and add in the RPR-0521
                                //Change 3: Add Code For BH1745, KX022, BM1383GLV, KMX62


#include "mbed.h"
#include "BLEDevice.h"
#include "UARTService.h"
#include "nrf_temp.h"

#define MAX_REPLY_LEN           (UARTService::BLE_UART_SERVICE_MAX_DATA_LEN)    //Actually equal to 20
#define SENSOR_READ_INTERVAL_S  (2.0F) 
#define ADV_INTERVAL_MS         (1000UL)
#define UART_BAUD_RATE          (19200UL)
#define DEVICE_NAME             ("DEMO SENSOR") // This can be read AFTER connecting to the device.
#define SHORT_NAME              ("ROHMKRIS")    // Keep this short: max 8 chars if a 128bit UUID is also advertised.

#define DEBUG(...)              { m_serial_port.printf(__VA_ARGS__); }

// Function Prototypes
void PBTrigger();   //Interrupt function for PB4

// Global Variables
BLEDevice   m_ble;
Serial      m_serial_port(p9, p11);  // TX pin, RX pin
DigitalOut  m_cmd_led(LED1);
DigitalOut  m_error_led(LED2);
UARTService *m_uart_service_ptr;
DigitalIn   testButton(p20);
InterruptIn sw4Press(p20);
I2C         i2c(p30,p7);

//Sensor Variables
AnalogIn    BH1620_ALS(p1);
uint16_t    BH1620_ALS_value;
float       BH1620_output;

AnalogIn    BDE0600_Temp(p2);
uint16_t    BDE0600_Temp_value;
float       BDE0600_output;

AnalogIn    ML8511_UV(p3);
uint16_t    ML8511_UV_value;
float       ML8511_output;

DigitalIn   Hall_GPIO0(p28);
DigitalIn   Hall_GPIO1(p29);
int         Hall_Return1;
int         Hall_Return0;

int         ALS_addr_w = 0x46;   //7bit addr = 0x23, with write bit 0
int         ALS_addr_r = 0x47;  //7bit addr = 0x23, with read bit 1
char        ALS_PwrOn_cmd = 0x01;
char        ALS_ContAuto_cmd = 0x10;
char        ALS_ReturnData_raw[2];
float       ALS_Return = 0;

/**
 * This callback is used whenever a disconnection occurs.
 */
void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
{
    switch (reason) {
    case Gap::REMOTE_USER_TERMINATED_CONNECTION:
        DEBUG("Disconnected (REMOTE_USER_TERMINATED_CONNECTION)\n\r");
        break;
    case Gap::LOCAL_HOST_TERMINATED_CONNECTION:
        DEBUG("Disconnected (LOCAL_HOST_TERMINATED_CONNECTION)\n\r");
        break;
    case Gap::CONN_INTERVAL_UNACCEPTABLE:
        DEBUG("Disconnected (CONN_INTERVAL_UNACCEPTABLE)\n\r");
        break;
    }

    DEBUG("Restarting the advertising process\n\r");
    m_ble.startAdvertising();
}


/**
 * This callback is used whenever the host writes data to one of our GATT characteristics.
 */
void dataWrittenCallback(const GattCharacteristicWriteCBParams *params)
{
    // Ensure that initialization is finished and the host has written to the TX characteristic.
    if ((m_uart_service_ptr != NULL) && (params->charHandle == m_uart_service_ptr->getTXCharacteristicHandle())) {
        uint8_t  buf[MAX_REPLY_LEN];
        uint32_t len = 0;

        if (1 == params->len) {
            switch (params->data[0]) {
            case '0':
                m_cmd_led = m_cmd_led ^ 1;
                len = snprintf((char*) buf, MAX_REPLY_LEN, "OK... LED ON");
                break;
            case '1':
                m_cmd_led = m_cmd_led ^ 1;
                len = snprintf((char*) buf, MAX_REPLY_LEN, "OK... LED OFF");
                break;
            case 'a':
                len = snprintf((char*) buf, MAX_REPLY_LEN, "ALSRaw = %d", BH1620_ALS_value);
                break;
            case 'b':
                len = snprintf((char*) buf, MAX_REPLY_LEN, "ALS = %.2f lx", BH1620_output);
                break;
            default:
                len = snprintf((char*) buf, MAX_REPLY_LEN, "ERROR");
                break;
            }
        }
        else
        {
            len = snprintf((char*) buf, MAX_REPLY_LEN, "ERROR");
        }

        m_ble.updateCharacteristicValue(m_uart_service_ptr->getRXCharacteristicHandle(), buf, len);

        DEBUG("%d bytes received from host\n\r", params->len);
    }
}


/**
 * This callback is used whenever a write to a GATT characteristic causes data to be sent to the host.
 */
void dataSentCallback(unsigned count)
{
    // NOTE: The count always seems to be 1 regardless of data.
    DEBUG("%d bytes sent to host\n\r", count);
}


/**
 * This callback is scheduled to be called periodically via a low-priority interrupt.
 */
void periodicCallback(void)
{
    uint8_t  buf[MAX_REPLY_LEN];
    uint32_t len = 0;
    
    
#ifdef AnalogALS    
    if (m_ble.getGapState().connected) {
        BH1620_ALS_value = BH1620_ALS.read_u16();
        BH1620_output = (float)BH1620_ALS_value * 1.543;
        
        len = snprintf((char*) buf, MAX_REPLY_LEN, "ALS = %.2f lx", BH1620_output);
        m_ble.updateCharacteristicValue(m_uart_service_ptr->getRXCharacteristicHandle(), buf, len);
    }
#endif

#ifdef AnalogTemp
    if (m_ble.getGapState().connected) {
        BDE0600_Temp_value = BDE0600_Temp.read_u16();
        BDE0600_output = (float)BDE0600_Temp_value * 0.00283; //(value * (2.9V/1024))
        BDE0600_output = (BDE0600_output-1.753)/(-0.01068) + 30;
        
        len = snprintf((char*) buf, MAX_REPLY_LEN, "Temp = %.2f C", BDE0600_output);
        m_ble.updateCharacteristicValue(m_uart_service_ptr->getRXCharacteristicHandle(), buf, len);

    }
#endif

#ifdef AnalogUV
    if (m_ble.getGapState().connected) {
        ML8511_UV_value = ML8511_UV.read_u16();
        ML8511_output = (float)ML8511_UV_value * 0.00283; //(value * (2.9V/1024))   //Note to self: when playing with this, a negative value is seen... Honestly, I think this has to do with my ADC converstion...
        ML8511_output = (ML8511_output-2.2)/(0.129) + 15;                           // Added +5 to the offset so when inside (aka, no UV, readings show 0)... this is the wrong approach... and the readings don't make sense... Fix this.
        
        len = snprintf((char*) buf, MAX_REPLY_LEN, "UV = %.1f mW/cm2", ML8511_output);
        m_ble.updateCharacteristicValue(m_uart_service_ptr->getRXCharacteristicHandle(), buf, len);
    }
#endif

#ifdef HallSensor
    if (m_ble.getGapState().connected) {
        Hall_Return0 = Hall_GPIO0;
        Hall_Return1 = Hall_GPIO1;
        
        len = snprintf((char*) buf, MAX_REPLY_LEN, "H0 = %d, H1 = %d", Hall_Return0, Hall_Return1);
        m_ble.updateCharacteristicValue(m_uart_service_ptr->getRXCharacteristicHandle(), buf, len);
    }
#endif

#ifdef DigitalALS
    if (m_ble.getGapState().connected) {
        i2c.read(ALS_addr_r, ALS_ReturnData_raw, 2);
        ALS_Return = (ALS_ReturnData_raw[0]<<8) | ALS_ReturnData_raw[1];
        ALS_Return = ALS_Return/1.2;
        
        len = snprintf((char*) buf, MAX_REPLY_LEN, "DALS= %0.2f lx", ALS_Return);
        m_ble.updateCharacteristicValue(m_uart_service_ptr->getRXCharacteristicHandle(), buf, len);
    }
#endif




    if (m_ble.getGapState().connected) {
        len = snprintf((char*) buf, MAX_REPLY_LEN, "                ");         //Print and Extra Line to show new data
        m_ble.updateCharacteristicValue(m_uart_service_ptr->getRXCharacteristicHandle(), buf, len);
    }

}


void error(ble_error_t err, uint32_t line)
{
    m_error_led = 1;
    DEBUG("Error %d on line number %d\n\r", err, line);
}

void PBTrigger()
{
    uint8_t  buf[MAX_REPLY_LEN];
    uint32_t len = 0;
    
    m_cmd_led = !m_cmd_led;
    
    if (m_ble.getGapState().connected) {
        BH1620_ALS_value = BH1620_ALS.read_u16();
        BH1620_output = (float)BH1620_ALS_value * 1.543;
        
        len = snprintf((char*) buf, MAX_REPLY_LEN, "ALS = %.2f lx", BH1620_output);
        m_ble.updateCharacteristicValue(m_uart_service_ptr->getRXCharacteristicHandle(), buf, len);
    }
}

int main(void)
{
    ble_error_t err;
    Ticker      ticker;

    m_serial_port.baud(UART_BAUD_RATE);

    DEBUG("Initialising\n\r");

    m_cmd_led      = 0;
    m_error_led    = 0;
    BH1620_ALS_value    = 0;

    ticker.attach(periodicCallback, SENSOR_READ_INTERVAL_S);

    sw4Press.fall(&PBTrigger);

#ifdef DigitalALS
    i2c.write(ALS_addr_w, &ALS_PwrOn_cmd, 1);
    i2c.write(ALS_addr_w, &ALS_ContAuto_cmd, 1);
#endif

    m_ble.init();
    m_ble.onDisconnection(disconnectionCallback);
    m_ble.onDataWritten(dataWrittenCallback);
    m_ble.onDataSent(dataSentCallback);

    // Set the TX power in dBm units.
    // Possible values (in decreasing order): 4, 0, -4, -8, -12, -16, -20.
    err = m_ble.setTxPower(4);
    if (BLE_ERROR_NONE != err) {
        error(err, __LINE__);
    }

    // Setup advertising (GAP stuff).
    err = m_ble.setDeviceName(DEVICE_NAME);
    if (BLE_ERROR_NONE != err) {
        error(err, __LINE__);
    }

    err = m_ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
    if (BLE_ERROR_NONE != err) {
        error(err, __LINE__);
    }

    m_ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);

    err = m_ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
                                                (const uint8_t *)SHORT_NAME,
                                                (sizeof(SHORT_NAME) - 1));
    if (BLE_ERROR_NONE != err) {
        error(err, __LINE__);
    }

    err = m_ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
                                                (const uint8_t *)UARTServiceUUID_reversed,
                                                sizeof(UARTServiceUUID_reversed));
    if (BLE_ERROR_NONE != err) {
        error(err, __LINE__);
    }

    m_ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(ADV_INTERVAL_MS));
    m_ble.startAdvertising();

    // Create a UARTService object (GATT stuff).
    UARTService uartService(m_ble);
    m_uart_service_ptr = &uartService;

    while (true) {
        m_ble.waitForEvent();
    }
}