Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp
- Committer:
- Fedor Chervyakov
- Date:
- 2019-09-07
- Revision:
- 2:45ed62566694
- Parent:
- 1:667b9825e7ee
File content as of revision 2:45ed62566694:
/* BME280 BLE sensor -- main.cpp
*
* 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.
*
* Copyright 2019 Fedor Chervyakov
*/
#include "mbed.h"
#include <stdio.h>
#include "events/EventQueue.h"
#include "platform/Callback.h"
#include "platform/NonCopyable.h"
#include "ble/BLE.h"
#include "ble/Gap.h"
#include "ble/GattClient.h"
#include "ble/GattServer.h"
#include "ble/GapAdvertisingParams.h"
#include "ble/GapAdvertisingData.h"
#include "ble/FunctionPointerWithContext.h"
#include "ble/services/EnvironmentalService.h"
#include "bme280_wrapper.h"
#include "stats_report.h"
using mbed::callback;
Thread t;
Thread stats_report_thread;
AnalogIn lm35_input(A0); /* ADC input pin connected to Vout of LM35 */
#define SLEEP_TIME 5 /* loop delay in seconds */
#define V_SUPPLY 3.3 /* System voltage */
#define K_LM35 0.01 /* Linear coefficient in transfer function of LM35: Vout = K [V/degC] * T [degC] */
#define BLE_DEVICE_NAME "BME280 sensor"
#define UPDATE_RATE 5000 /* ms */
class BME280BLE : private mbed::NonCopyable<BME280BLE>, public ble::Gap::EventHandler {
public:
BME280BLE(events::EventQueue &event_queue, BLE &ble_interface) :
_ble_interface(ble_interface),
_gap(_ble_interface.gap()),
_event_queue(event_queue),
_post_init_cb(),
_bme280(BME280(I2C_SDA, I2C_SCL)),
_env_service(NULL),
_env_service_uuid(GattService::UUID_ENVIRONMENTAL_SERVICE)
{
}
~BME280BLE() {
stop();
}
void on_init(mbed::Callback<void(BLE&, events::EventQueue&)> cb) {
_post_init_cb = cb;
}
bool start() {
printf("BLE process has started. \r\n");
if (_ble_interface.hasInitialized()) {
printf("Error: the BLE instance has already been initialized! \r\n");
return false;
}
/* Set Gap EventHandler to this class */
_gap.setEventHandler(this);
_ble_interface.onEventsToProcess(
makeFunctionPointer(this, &BME280BLE::schedule_ble_events)
);
/* Initialize BLE interface */
ble_error_t error = _ble_interface.init(this, &BME280BLE::when_init_complete);
if (error) {
printf("Error: %u returned by BLE::init.\r\n", error);
return false;
}
_event_queue.call_every(UPDATE_RATE, this, &BME280BLE::update_measurements);
return true;
}
void stop() {
if (_ble_interface.hasInitialized()) {
_ble_interface.shutdown();
printf("BLE process stopped.\r\n");
}
}
private:
void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *event) {
_event_queue.call(mbed::callback(&event->ble, &BLE::processEvents));
}
void when_init_complete(BLE::InitializationCompleteCallbackContext *event) {
if (event->error) {
printf("Error %u during the initialization.\r\n", event->error);
}
printf("BLE instance initialized.\r\n");
/* Setup environmental service */
_env_service = new EnvironmentalService(_ble_interface);
if (!set_advertising_parameters()) {
return;
}
if (!set_advertising_data()) {
return;
}
if (!start_advertising()){
return;
}
if (_post_init_cb) {
_post_init_cb(_ble_interface, _event_queue);
}
}
bool set_advertising_parameters() {
ble_error_t error = _gap.setAdvertisingParameters(
ble::LEGACY_ADVERTISING_HANDLE,
ble::AdvertisingParameters(
ble::advertising_type_t::CONNECTABLE_UNDIRECTED,
ble::adv_interval_t(ble::millisecond_t(1000))
)
);
if (error) {
printf("Gap::setAdvertisingParameters() failed with error %d", error);
return false;
}
return true;
}
bool set_advertising_data() {
/* Use the simple builder to construct the payload; it fails at runtime
* if there is not enough space left in the buffer */
ble_error_t error = _gap.setAdvertisingPayload(
ble::LEGACY_ADVERTISING_HANDLE,
ble::AdvertisingDataSimpleBuilder<ble::LEGACY_ADVERTISING_MAX_SIZE>()
.setFlags()
.setLocalServiceList(mbed::make_Span(&_env_service_uuid, 1))
.setName(BLE_DEVICE_NAME)
.getAdvertisingData()
);
if (error) {
printf("Gap::setAdvertisingPayload() failed with error %d", error);
return false;
}
return true;
}
bool start_advertising() {
/* Start advertising the set */
ble_error_t error = _gap.startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
if (error) {
printf("Error %u during gap.startAdvertising.\r\n", error);
return false;
} else {
printf("Advertising started.\r\n");
return true;
}
}
private:
/* Gap::EventHandler */
virtual void onConnectionComplete(const ble::ConnectionCompleteEvent &event) {
printf("Connected.\r\n");
}
virtual void onDisconnectionComplete(const ble::DisconnectionCompleteEvent &event) {
printf("Disconnected.\r\n");
start_advertising();
}
private:
/* EnvironmentalService */
void update_measurements() {
struct bme280_data *comp_data;
EnvironmentalService::HumidityType_t humidity; // uint16_t
EnvironmentalService::PressureType_t pressure; // uint32_t
float temperature; // int16_t
_bme280.force_measurement();
comp_data = &_bme280.comp_data;
temperature = comp_data->temperature;
humidity = comp_data->humidity;
pressure = comp_data->pressure;
_env_service->updateTemperature(temperature);
_env_service->updatePressure(pressure);
_env_service->updateHumidity(humidity);
}
private:
BLE &_ble_interface;
Gap &_gap;
EnvironmentalService *_env_service;
UUID _env_service_uuid;
events::EventQueue &_event_queue;
mbed::Callback<void(BLE&, events::EventQueue&)> _post_init_cb;
BME280 _bme280;
};
void print_sensor_data(struct bme280_data *comp_data)
{
float temp, press, hum;
temp = comp_data->temperature;
press = 0.01 * comp_data->pressure;
hum = comp_data->humidity;
printf("BME280 %0.2lf deg C, %0.2lf hPa, %0.2lf%%\n", temp, press, hum);
}
float lm35_temperature() {
float temperature;
temperature = lm35_input.read() * V_SUPPLY / (K_LM35 * (1+10/4.7)) ;
return temperature;
}
void print_stats() {
SystemReport sys_report(SLEEP_TIME * 1000);
while (true) {
sys_report.report_state();
wait(SLEEP_TIME);
}
}
// main() runs in its own thread in the OS
int main()
{
events::EventQueue event_queue; /* Event queue */
BLE &ble_interface = BLE::Instance(); /* Bluetooth interface */
BME280BLE ble_process(event_queue, ble_interface);
ble_process.start();
t.start(mbed::callback(&event_queue, &EventQueue::dispatch_forever));
stats_report_thread.start(print_stats);
while (true) {
printf("LM35 %.2f deg C; ", lm35_temperature());
wait(SLEEP_TIME);
}
}