仕倫 林 / Mbed OS 12_1

Dependencies:   X_NUCLEO_IKS01A2

source/main.cpp

Committer:
jim_lsj
Date:
2020-04-29
Revision:
1:b12ac7b02a21
Parent:
0:9c0e0ac79e75
Child:
2:5da515ba10ff

File content as of revision 1:b12ac7b02a21:

/* mbed Microcontroller Library
 * Copyright (c) 2006-2015 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.
 */

#include <events/mbed_events.h>
#include <mbed.h>
#include "ble/BLE.h"
#include "ble/gap/Gap.h"
//#include "ble/services/EnvironmentalSensingService2.h"
#include "ble/services/BatteryService.h"
#include "ble/services/HeartRateService.h"
#include "ble/services/DeviceInformationService.h"
#include "pretty_printer.h"

//#include "BLEDevice.h"
#include "blecommon.h"
#include "Gap.h"
#include "GattServer.h"
//#include "BLEDeviceInstanceBase.h"

#include "XNucleoIKS01A2.h"
#include "ESS.h"
#include "ESS2.h"

//const static char DEVICE_NAME[] = "Heartrate";



// new code
Serial pc(USBTX, USBRX);
static XNucleoIKS01A2 *mems_expansion_board = XNucleoIKS01A2::instance(D14, D15, D4, D5);
static LSM303AGRMagSensor *magnetometer = mems_expansion_board->magnetometer;
static HTS221Sensor *hum_temp = mems_expansion_board->ht_sensor;
static LPS22HBSensor *press_temp = mems_expansion_board->pt_sensor;
static LSM6DSLSensor *acc_gyro = mems_expansion_board->acc_gyro;
static LSM303AGRAccSensor *accelerometer = mems_expansion_board->accelerometer;
volatile float TEMPERATURE_C=20;
volatile float TEMPERATURE_F;
volatile float TEMPERATURE_K;
volatile float HUMIDITY=50;
volatile float PRESSURE=1000;
volatile float WIND_DIRECTION=0;
int16_t MagRaw[3];
int16_t * MAGNETIC = new int16_t[3];
const static char     DEVICE_NAME[]        = "WEATHER";

static volatile bool  triggerSensorPolling = false;
//end

static events::EventQueue event_queue(/* event count */ 16 * EVENTS_EVENT_SIZE);

class HeartrateDemo : ble::Gap::EventHandler {
public:
    HeartrateDemo(BLE &ble, events::EventQueue &event_queue) :
        _ble(ble),
        _event_queue(event_queue),
        _led1(LED1, 1),
        _connected(false),
        _hr_counter(100),
        _bt_service(ble, 25),
        //_hr_service(ble, _hr_counter, HeartRateService::LOCATION_FINGER),
        _deviceInfo(ble, "ST", "Nucleo", "SN1" ),
        _adv_data_builder(_adv_buffer),
        
        _air (ble, (uint16_t) HUMIDITY, (int16_t) TEMPERATURE_C ),
        _wind (ble, (uint16_t) WIND_DIRECTION, (uint32_t) PRESSURE)
        { 
            uuid16_list = new UUID[1]{0x181A};
            //_uuid_list = new UUID(3);
//            _uuid_list[0] = GattService::UUID_HEART_RATE_SERVICE;
//            _uuid_list[1] = GattService::UUID_BATTERY_SERVICE;
//            _uuid_list[2] = GattService::UUID_DEVICE_INFORMATION_SERVICE;
        }
    ~HeartrateDemo(){
        delete [] uuid16_list;
    }

    void start() {
        _ble.gap().setEventHandler(this);

        _ble.init(this, &HeartrateDemo::on_init_complete);

        _event_queue.call_every(500, this, &HeartrateDemo::blink);
        _event_queue.call_every(1000, this, &HeartrateDemo::update_sensor_value);

        _event_queue.dispatch_forever();
    }

private:
    /** Callback triggered when the ble initialization process has finished */
    void on_init_complete(BLE::InitializationCompleteCallbackContext *params) {
        if (params->error != BLE_ERROR_NONE) {
            printf("Ble initialization failed.");
            return;
        }

        print_mac_address();

        start_advertising();
    }

    void start_advertising() {
        /* Create advertising parameters and payload */

        ble::AdvertisingParameters adv_parameters(
            ble::advertising_type_t::CONNECTABLE_UNDIRECTED,
            ble::adv_interval_t(ble::millisecond_t(1000))
        );

        _adv_data_builder.setFlags();
        _adv_data_builder.setAppearance(ble::adv_data_appearance_t::GENERIC_THERMOMETER);
        _adv_data_builder.setLocalServiceList(mbed::make_Span(uuid16_list, 1));
        _adv_data_builder.setName(DEVICE_NAME);

        /* Setup advertising */

        ble_error_t error = _ble.gap().setAdvertisingParameters(
            ble::LEGACY_ADVERTISING_HANDLE,
            adv_parameters
        );

        if (error) {
            printf("_ble.gap().setAdvertisingParameters() failed\r\n");
            return;
        }

        error = _ble.gap().setAdvertisingPayload(
            ble::LEGACY_ADVERTISING_HANDLE,
            _adv_data_builder.getAdvertisingData()
        );

        if (error) {
            printf("_ble.gap().setAdvertisingPayload() failed\r\n");
            return;
        }

        /* Start advertising */

        error = _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);

        if (error) {
            printf("_ble.gap().startAdvertising() failed\r\n");
            return;
        }
    }

    void update_sensor_value() {
        if (_connected) {
            // Do blocking calls or whatever is necessary for sensor polling.
            // In our case, we simply update the HRM measurement.
            hum_temp->get_temperature((float *)&TEMPERATURE_C);
            hum_temp->get_humidity((float *)&HUMIDITY);
            press_temp->get_pressure((float *)&PRESSURE);
            magnetometer->get_m_axes_raw((int16_t *)MAGNETIC);
            TEMPERATURE_C = TEMPERATURE_C*100;  //2 decimals
            HUMIDITY = HUMIDITY*100;                        //2 decimals
            PRESSURE = PRESSURE*1000;           //hPa to Pa + 1 decimal
            
            
            //Calcule the direction where the system is pointing relative to North.
            //I have used a simple empirical method to distinguish between 8 directions. 
            if (MAGNETIC[0] < 140) WIND_DIRECTION = 0; //North
            else if (MAGNETIC[0] >= 140 && MAGNETIC[0] < 200 && -MAGNETIC[1] > 250 ) WIND_DIRECTION = 45;  //Northeast
            else if (MAGNETIC[0] >= 140 && MAGNETIC[0] < 200 && -MAGNETIC[1] < 250 ) WIND_DIRECTION = 315; //Northwest
            else if (MAGNETIC[0] >= 200 && MAGNETIC[0] < 280 && -MAGNETIC[1] > 250 ) WIND_DIRECTION = 90;  //East
            else if (MAGNETIC[0] >= 200 && MAGNETIC[0] < 280 && -MAGNETIC[1] < 250 ) WIND_DIRECTION = 270; //Weast
            else if (MAGNETIC[0] >= 280 && MAGNETIC[0] < 380 && -MAGNETIC[1] > 250 ) WIND_DIRECTION = 135; //Southeast
            else if (MAGNETIC[0] >= 280 && MAGNETIC[0] < 380 && -MAGNETIC[1] < 250 ) WIND_DIRECTION = 225; //Soutwest           
            else if (MAGNETIC[0] >= 380) WIND_DIRECTION = 180; //South
            
            WIND_DIRECTION *=100;                             //2 decimals
            
            _air.updateTemperature((uint16_t)TEMPERATURE_C);   
            _air.updateHumidity((uint16_t)HUMIDITY);
            _wind.updateWinddirection((uint16_t)WIND_DIRECTION);
            _wind.updatePressure((uint16_t)PRESSURE);
            
            
            TEMPERATURE_F = (TEMPERATURE_C * 1.8f) + 32.0f; //Convert the temperature from Celsius to Fahrenheit
            TEMPERATURE_K = (TEMPERATURE_C + 273.15f);          //Convert the temperature from Celsius to Kelvin
            pc.printf("Temperature:\t %.2f C / %.2f F / %.2f K\r\n", TEMPERATURE_C, TEMPERATURE_F, TEMPERATURE_K);
            pc.printf("Humidity:\t %.2f%%\r\n", HUMIDITY);
            pc.printf("Pressure:\t %.2f hPa\r\n", PRESSURE); 
            pc.printf("\r\n");
    
        }
    }

    void blink(void) {
        _led1 = !_led1;
    }

private:
    /* Event handler */

    void onDisconnectionComplete(const ble::DisconnectionCompleteEvent&) {
        _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
        _connected = false;
    }

    virtual void onConnectionComplete(const ble::ConnectionCompleteEvent &event) {
        if (event.getStatus() == BLE_ERROR_NONE) {
            _connected = true;
        }
    }

private:
    BLE &_ble;
    events::EventQueue &_event_queue;
    DigitalOut _led1;

    bool _connected;

    uint8_t _hr_counter;
    //HeartRateService _hr_service;
    
    uint8_t _battery_level;
    BatteryService _bt_service;
    
    EnvironmentalSensingService _air;
    EnvironmentalSensingService2 _wind;
    
    UUID * uuid16_list;
    
    DeviceInformationService _deviceInfo;    

    uint8_t _adv_buffer[ble::LEGACY_ADVERTISING_MAX_SIZE];
    ble::AdvertisingDataBuilder _adv_data_builder;
};

/** Schedule processing of events from the BLE middleware in the event queue. */
void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context) {
    event_queue.call(Callback<void()>(&context->ble, &BLE::processEvents));
}

int main()
{
    static XNucleoIKS01A2 *Sensors = XNucleoIKS01A2::instance(D14, D15, D4, D5);
    hum_temp->enable();
    press_temp->enable();
    magnetometer->enable();
    accelerometer->enable();
    acc_gyro->enable_x();
    acc_gyro->enable_g();
    
    BLE &ble = BLE::Instance();
    ble.onEventsToProcess(schedule_ble_events);
    
    HeartrateDemo demo(ble, event_queue);
    demo.start();

    return 0;
}