Pull request for i.a. sensor buffer template

Dependencies:   BLE_API MPU6050 mbed nRF51822

main.cpp

Committer:
JustinAtAlten
Date:
2018-11-15
Revision:
11:8c38e284e9f7
Parent:
10:eed92ffd0bba

File content as of revision 11:8c38e284e9f7:

#include "mbed.h"
#include "mbed_mem_trace.h"
#include "nrf51.h"
#include "nrf51_bitfields.h"
#include "MPU6050.h"

#include "BLE.h"
#include "DFUService.h"
#include "UARTService.h"
#include "BatteryService.h"
#include "DeviceInformationService.h"
#include "TemperatureService.h"
#include "AccelerationService.h"

#include "ReadIntervals.h"
#include "Util.h"
#include "IO.h"
#include "MeasurementBufferTemplate.h"

//https://os.mbed.com/handbook/SDFileSystem
// http://os.mbed.com/users/mbed_official/code/SDFileSystem/
// needs: https://os.mbed.com/teams/mbed-official/code/FATFileSystem/pull-request/4
// #include "SDFileSystem.h"
//https://os.mbed.com/cookbook/SD-Card-File-System


///////////////////////////////////////
//              DEFINES              //
///////////////////////////////////////

// Starting sampling rate.
#define DEFAULT_MPU_HZ  (100)

// --- Device Information --- //
#define MANUFACTURER "PM @ ALTEN"
#define MODELNUMBER "IoT BLE"
#define SERIALNUMBER "123456"
#define HARDWAREREVISION "Seeed demo IoT"
#define FIRMWAREREVISION "1.0"
#define SOFTWAREREVISION "1.0"

/////////////////////////////////////////
//              CONSTANTS              //
/////////////////////////////////////////

// --- UUIDs --- //
const char acceleration128bitUUIDlist[] = { 0x53, 0xF8, 0x0E, 0x12, 0xAD, 0xBB, 0xF1, 0x38, 0xAC, 0x07, 0xD2, 0x3D, 0xF0, 0xE2, 0x34, 0x5D };
const UUID uuidTempBulkService("11111111-1000-2222-3333-444455556666");
const UUID uuidTempBulkCharRead("11111111-1001-2222-3333-444455556666");

// --- Temperature Buffer Data --- //
const unsigned int TemperatureBufferSize = 100;
const unsigned int TemperatureBulkUpdateSize = 6;
	// https://devzone.nordicsemi.com/f/nordic-q-a/519/reading-a-subset-of-data-on-a-ble-server
	//  characteristic data max 512 bytes
	//	https://github.com/pieterm/bledemo#step-8-add-callback-function-on-data-written-event
	//  	GattWriteCallbackParams


/////////////////////////////////////////////////////
//              FUNCTION DECLARATIONS              //
/////////////////////////////////////////////////////

uint16_t readTemperature();

////////////////////////////////////////
//              TYPEDEFS              //
////////////////////////////////////////

typedef MeasurementBufferTemplate<uint16_t, TemperatureBufferSize, TemperatureBulkUpdateSize, ReadIntervals::TemperatureSensorPeriod, readTemperature> TemperatureBuffer;

/////////////////////////////////////////
//              VARIABLES              //
/////////////////////////////////////////

// --- Buffers --- //
TemperatureBuffer temperatureBuffer;
TemperatureBuffer::BulkUpdate tempUpdate;

// --- Timing --- //
Ticker ticker;

// --- BLE --- //
GattCharacteristic * tempBulkUpdateCharacteristic;

// --- Flags --- //
volatile bool batteryVoltageChanged = false;
volatile bool tempUpdateFlag = false;
volatile bool startMeasure = false;

/////////////////////////////////////////
//              FUNCTIONS              //
/////////////////////////////////////////


uint16_t readTemperature(){
	//read temperature (raw)
	int16_t tempRaw = mpu.getTempRaw();
	// convert into 0.1 degrees Celsius
	tempRaw *= 10;
	tempRaw += 5210;
	tempRaw /= 340;
	tempRaw += 350;

	return tempRaw;
}


void connectionCallback(const Gap::ConnectionCallbackParams_t *params)
{
	LOG("Connected!\n");
	// bleIsConnected = true;
}

void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *cbParams)
{
	LOG("Disconnected!\n");
	LOG("Restarting the advertising process\n");
	BLE & ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
	ble.gap().startAdvertising();
	// bleIsConnected = false;
}

void tick(void)
{
	static int tickerSleepTime=0;
	blue = !blue;

	//update time
	ReadIntervals::updateTimeLeft(tickerSleepTime);

	//perform actions
	if(ReadIntervals::temperatureSensorPeriodPassed()){
		green = !green;
		startMeasure = true;	// notify the main-loop to start measuring the MPU6050
	}
	if(ReadIntervals::batteryMonitorPeriodPassed()){
		red = !red;
		batteryVoltageChanged = true;
	}

	//prep next ticker-sleep
	tickerSleepTime = ReadIntervals::getTickerSleepTime();
	ticker.attach(tick, tickerSleepTime);
}

// void detect(void)
// {
// 	LOG("Button pressed\n");  
// 	blue = !blue;
// }

void setAdvertisingPayload(BLE & ble){
	ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
	ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
	ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
									 (const uint8_t *)acceleration128bitUUIDlist, sizeof(acceleration128bitUUIDlist));
}

void setScanResponsePayload(BLE & ble){
	uint8_t name[] = "iot aabbccddeeff";
	Gap::AddressType_t addr_type;
	Gap::Address_t address;
	ble_error_t error = ble.gap().getAddress(&addr_type, address);
	if(error == BLE_ERROR_NONE){
		for(int i = 5; i >= 0; i--){
			char buffer[3];
			sprintf(buffer, "%02x", address[i]);
			name[4 + ((5-i)*2)] = buffer[0];
			name[4 + ((5-i)*2) + 1] = buffer[1];
		}
	}
	
	ble.gap().accumulateScanResponse(GapAdvertisingData::COMPLETE_LOCAL_NAME,
									 name, sizeof(name));
}


void onDataWritten(const GattWriteCallbackParams * context)
{
	if(context->handle == tempBulkUpdateCharacteristic->getValueHandle()){
		const time_t & newSelectedTime = *(time_t*)context->data;
		tempUpdate = temperatureBuffer.getBulkUpdate(newSelectedTime);
		tempUpdateFlag = true;
	}
}

int main(void)
{
	///Start global timer
	AppTime::init();

	///Initialize led values
	blue  = 0;
	green = 1;
	red   = 1;

	wait(1);

#ifdef USE_SERIAL
	pc.baud(115200);
#endif /* USE_SERIAL */
	
	LOG("---- Seeed Tiny BLE ----\n");
	
	///Initialize MPU6050
	LOG("MPU6050 testConnection \n");
	bool mpu6050TestResult = mpu.testConnection();
	if(mpu6050TestResult) {
		LOG("MPU6050 test passed \n");
	} else {
		LOG("MPU6050 test failed \n");
	}
	
	///Initialize temperature buffer & update
	uint16_t temperature = temperatureBuffer.performMeasurement();
	tempUpdate = temperatureBuffer.getBulkUpdate(0);

	///Initialize ticker
	ticker.attach(tick, ReadIntervals::TemperatureSensorPeriod);
	
	// button.fall(detect);

	///Initialize BLE
	LOG("Initialising the nRF51822\n");
	BLE & ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
	ble.init();
	ble.gap().onDisconnection(disconnectionCallback);
	ble.gap().onConnection(connectionCallback);

	// -> Initialize BLE - custom services
	tempBulkUpdateCharacteristic = new GattCharacteristic(uuidTempBulkCharRead, NULL, 1, sizeof(tempUpdate), 
			GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE);
	GattService tempBulkService(uuidTempBulkService, &tempBulkUpdateCharacteristic, 1);
	ble.gattServer().addService(tempBulkService);
	ble.gattServer().onDataWritten(onDataWritten);
	
	// -> Initialize BLE - advertising and scan payloads
	setAdvertisingPayload(ble);
	setScanResponsePayload(ble);
	
	// -> Initialize BLE - generic services
	DFUService dfu(ble);
	UARTService uartService(ble);
	BatteryService batteryService(ble);
	DeviceInformationService deviceInfo(ble, MANUFACTURER, MODELNUMBER, SERIALNUMBER, HARDWAREREVISION, FIRMWAREREVISION, SOFTWAREREVISION);
	TemperatureService tempService(ble);
	AccelerationService accelerationService(ble);

	// -> Initialize BLE - start advertising
	ble.gap().setAdvertisingInterval(160); // 100ms; in multiples of 0.625ms.
	ble.gap().startAdvertising();

	tempService.updateTemperature(temperature);
	
	while(true) {
		ble.waitForEvent();

		// update battery level after the level is measured
		if(batteryVoltageChanged == true) {
			float batteryVoltage = battery.read();
			// LOG("VBat: %4.3f, ADC: %4.3f, Vadc: %4.3f\n", batteryVoltage*2.0f, batteryVoltage, batteryVoltage*3.3f);
			LOG("VBat: %s, ADC: %s, Vadc: %s\n", floatToCharArray(batteryVoltage*2.0f), floatToCharArray(batteryVoltage), floatToCharArray(batteryVoltage*3.3f));
			batteryService.updateBatteryLevel((uint8_t)(batteryVoltage*100.0f));	// input is 0-1.0 of 3.3V -> *100 = percentage of 3.3V
			batteryVoltageChanged = false;
		}

		if(startMeasure == true) {
			//uartService.write("test\n", 5);
			//float a[3];
			//mpu.getAccelero(a);
			//LOG("Acceleration %.2f;%.2f;%.2f\n", a[0], a[1], a[2]);
 
			///Acceleration
			//read accelerometer data
			int a[3];
			mpu.getAcceleroRaw(a);
			//convert to format accepted by accelerionService
			int16_t a_16[3];
			castArray(a, a_16, 3); 	//cannot simply cast 'a' to int16_t*, memory won't move accordingly
			// update BLE acceleration
			accelerationService.addAcceleration(a_16);
			LOG("Acceleration 0x%x;0x%x;0x%x\n", a[0], a[1], a[2]);
			
			///Temperature
			uint16_t temperature = temperatureBuffer.performMeasurement();
			tempService.updateTemperature(temperature);

			///Reset measure flag
			startMeasure = false;
		}

		if(tempUpdateFlag){
			ble_error_t err = ble.gattServer().write(tempBulkUpdateCharacteristic->getValueHandle(), (const uint8_t*)&tempUpdate, sizeof(tempUpdate));
			LOG("err:[%d]\n", err);
			LOG("rT:[%d]\n", tempUpdate.requestedTime);
			LOG("iT:[%d]\n", tempUpdate.initialTime);
			LOG("nR:[%d]\n", tempUpdate.numberOfReadings);
			LOG("pT:[%s]\n", floatToCharArray(tempUpdate.sensorReadingInterval));
				// LOG("pT:[%f]\n", tempUpdate.sensorReadingInterval);
			for(unsigned int i=0; i < tempUpdate.numberOfReadings; i++){
				LOG("%#010x\n", tempUpdate.readings[i]);
			}
			tempUpdateFlag = false;
		}
	}
}