aconno acnsensa project for iOS devices with iBeacon packets support.
Dependencies: LSM9DS1 Si7006A20 aconno_SEGGER_RTT aconno_bsp adc52832_common
main.cpp
- Committer:
- dbartolovic
- Date:
- 2018-08-17
- Branch:
- sensaformatfix
- Revision:
- 38:c90e1670ffb3
- Parent:
- 36:9e40cdef6bd6
File content as of revision 38:c90e1670ffb3:
/*
* aconno.de
* Made by Jurica Resetar
* Edited by Karlo Milicevic
* Edited by Dominik Bartolovic
* All right reserved
*
*/
#include "mbed.h"
#include "ble/BLE.h"
#include "acd52832_bsp.h"
#include "GapAdvertisingData.h"
#include "Si7006A20.h"
#include "LSM9DS1.h"
#include "math.h"
#include "nrf52_digital.h"
#include "adc52832_common/utilities.h"
#include "MPL115A1.h"
#include "acd_nrf52_saadc.h"
#include "service.h"
#include <events/mbed_events.h>
#include "aconnoConfig.h"
uint8_t gConnected = 0;
static NRF52_SAADC analogIn;
static NRF52_DigitalOut lightPower(p28);
static NRF52_DigitalOut temperaturePower(p31);
static NRF52_DigitalOut shdn(p6);
static NRF52_DigitalOut power(p2);
static NRF52_DigitalOut cs(p7);
static Si7006 *si;
static LSM9DS1 *mems;
static SPI *spi;
static MPL115A1 *mpl115a1;
static EventQueue eventQueue(32 * EVENTS_EVENT_SIZE);
uint8_t myMacAddress[6] = {};
MACService *macServicePtr;
#if DEBUG_PRINT
#include "SEGGER_RTT.h"
#define printf(...) SEGGER_RTT_printf(0, __VA_ARGS__)
#else
#define printf(...)
#endif
static vector3_s memsAccelerometerInit;
static vector3_s memsGyroscopeInit;
static vector3_s memsMagnetometerInit;
static GapAdvertisingData adv_data = GapAdvertisingData();
struct __attribute__((packed, aligned(1))) iBeaconMSD_t
{
// AppleID is constant
uint16_t appleID;
// secondID is constant
uint8_t secondID;
// DataSize is constant
uint8_t dataSize;
uint8_t UUID[16];
uint16_t major;
uint16_t minor;
int8_t RSSI;
}static iBeaconMSD = {.appleID = 0x004C,
.secondID = 0x02,
.dataSize = 0x15,
.UUID = {UUID_INIT},
.major = MAJOR,
.minor = MINOR,
.RSSI = RSSI_INIT};
struct __attribute__((packed, aligned(1))) advertising_packet
{
uint32_t header;
uint8_t type;
union{
struct{
int16_t gyroscope[3];
int16_t accelerometer[3];
int16_t magnetometer[3];
uint16_t acc_lsb_value;
};
struct{
float temperature;
float humidity;
float pressure;
float light;
uint8_t battery;
};
};
};
void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context)
{
BLE &ble = context->ble;
eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
}
static advertising_packet advertisementPacket;
const int advDataSize = sizeof(advertising_packet);
void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
{
// Restart Advertising on disconnection
gConnected = 0;
BLE::Instance().gap().startAdvertising();
}
void onConnectionCallback(const Gap::ConnectionCallbackParams_t *params)
{
printf("Connection callback.\n");
gConnected = 1;
}
/**
* Callback triggered when the ble initialization process has finished
*/
void bleInitCompleteSensors(BLE::InitializationCompleteCallbackContext *params)
{
BLE& ble = params->ble;
ble_error_t error = params->error;
if (error != BLE_ERROR_NONE){
return;
}
/* Ensure that it is the default instance of BLE */
if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE){
return;
}
uint8_t mac[6] = {0,0,0,0,0,0};
uint8_t initAdvData[] = {0};
BLEProtocol::AddressType_t temp_address_type;
ble.gap().getAddress(&temp_address_type, myMacAddress);
macServicePtr = new MACService(ble, mac, initAdvData);
macServicePtr->updateMacAddress(myMacAddress); // Update MAC address
ble.gap().onConnection(onConnectionCallback);
ble.gap().onDisconnection(disconnectionCallback);
/* setup advertising */
ble.gap().accumulateAdvertisingPayload(
GapAdvertisingData::BREDR_NOT_SUPPORTED);
ble.gap().accumulateAdvertisingPayload(
GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA,
(uint8_t *)&advertisementPacket, sizeof(advertisementPacket));
ble.gap().setAdvertisingType(
GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
ble.gap().setAdvertisingInterval(ADV_INTERVAL);
printf("Init started....\t\t");
ble.gap().setTxPower(TX_POWER_DB); // Set TX power to TX_POWER_DB
ble.gap().startAdvertising();
printf("Init done.\n");
}
float getLight()
{
return ((float)analogIn.getData()[1])/ADC_RESOLUTION * VALUE_TO_PERCENTAGE;
}
float voltage2temp(float vOut)
{
return ((float)vOut - (float)V0)/((float)TC);
}
float getTemperature()
{
return voltage2temp(((float)analogIn.getData()[2])/ADC_RESOLUTION * (float)VCC);
}
uint8_t getBattery()
{
uint16_t batteryVoltage = analogIn.getData()[0];
const uint16_t zero_percent_limit = 739;
const uint16_t onehundred_percent_limit = 810;
const uint16_t percentage_increments = 5;
uint8_t percentage;
if (batteryVoltage < zero_percent_limit)
{
percentage = 0;
}
else if(batteryVoltage > onehundred_percent_limit)
{
percentage = 100;
}
else
{
batteryVoltage -= zero_percent_limit;
percentage = (batteryVoltage*100)/(onehundred_percent_limit - zero_percent_limit);
percentage = percentage/percentage_increments*percentage_increments;
}
return percentage;
}
float getHumidity()
{
float result;
si->getHumidity(&result);
return result;
}
void readGyroscope(vector3_s *gyroscopeData)
{
mems->readGyroscope((int16_t *)gyroscopeData);
*gyroscopeData -= memsGyroscopeInit;
}
void readAccelerometer(vector3_s *accelerometerData)
{
mems->readAccelerometer((int16_t *)accelerometerData);
*accelerometerData -= memsAccelerometerInit;
}
void readMagnetometer(vector3_s *magnetometerData){
mems->readMagnetometer((int16_t *)magnetometerData);
*magnetometerData -= memsMagnetometerInit;
}
void calibrateAccelerometer(){
vector3_s accelerometerData;
for(uint8_t counter = 0; counter < CALIBRATION_STEPS; ++counter)
{
readAccelerometer(&accelerometerData);
memsAccelerometerInit += accelerometerData;
}
memsAccelerometerInit /= CALIBRATION_STEPS;
}
void calibrateGyroscope(){
vector3_s gyroscopeData;
for(uint8_t counter = 0; counter < CALIBRATION_STEPS; ++counter)
{
readGyroscope(&gyroscopeData);
memsGyroscopeInit += gyroscopeData;
}
memsGyroscopeInit /= CALIBRATION_STEPS;
}
void calibrateMag(){
vector3_s magnetometerData;
for(uint8_t counter = 0; counter < CALIBRATION_STEPS; ++counter)
{
readMagnetometer(&magnetometerData);
memsMagnetometerInit += magnetometerData;
}
memsMagnetometerInit /= CALIBRATION_STEPS;
}
void updateData(){
static uint16_t serviceUuid = macServicePtr->SERVICE_UUID;
static uint8_t advertisementType = 0;
int16_t temp_acc[3];
BLE &ble = BLE::Instance();
if(!advertisementType && !gConnected)
{
power = 1;
wait_ms(WAKEUP_TIME_DELAY_MS);
mems->startAccelerometer();
mems->startGyroscope();
mems->startMagnetometer();
printf("Sensor format 1.\n");
ble.gap().clearAdvertisingPayload();
/* setup advertising */
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)&(serviceUuid), sizeof(serviceUuid));
ble.gap().accumulateAdvertisingPayload(
GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA,
(uint8_t *)&advertisementPacket, sizeof(advertisementPacket));
ble.gap().setAdvertisingType(
GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
adv_data = ble.getAdvertisingData();
advertisementPacket.type = 0x00;
wait_ms(WAKEUP_TIME_DELAY_MS);
readGyroscope((vector3_s *)advertisementPacket.gyroscope);
readAccelerometer((vector3_s *)temp_acc);
readMagnetometer((vector3_s *)advertisementPacket.magnetometer);
advertisementPacket.acc_lsb_value = (0xF9E);
// ^--- That's in ug cuz MSB is 1
#if INVERT_AXES
advertisementPacket.accelerometer[0] = temp_acc[1];
advertisementPacket.accelerometer[1] = temp_acc[0];
advertisementPacket.accelerometer[2] = temp_acc[2];
#endif
adv_data.updateData(adv_data.MANUFACTURER_SPECIFIC_DATA,
(uint8_t *)&advertisementPacket, sizeof(advertisementPacket));
ble.setAdvertisingData(adv_data);
power = 0;
wait_ms(WAKEUP_TIME_DELAY_MS);
}
else if (advertisementType == 1 && !gConnected)
{
power = 1;
wait_ms(WAKEUP_TIME_DELAY_MS);
temperaturePower = 1;
lightPower = 1;
shdn = 1; // Wake up the pressure sensor
wait_ms(WAKEUP_TIME_DELAY_MS);
printf("Sensor format 2.\n");
analogIn.updateData();
adv_data = ble.getAdvertisingData();
advertisementPacket.type = 0x01;
advertisementPacket.temperature = getTemperature();
advertisementPacket.light = getLight();
advertisementPacket.humidity = getHumidity();
advertisementPacket.pressure = mpl115a1->getPressure();
advertisementPacket.battery = getBattery();
adv_data.updateData(adv_data.MANUFACTURER_SPECIFIC_DATA,
(uint8_t *)&advertisementPacket, sizeof(advertisementPacket));
ble.setAdvertisingData(adv_data);
power = 0;
wait_ms(WAKEUP_TIME_DELAY_MS);
temperaturePower = 0;
lightPower = 0;
shdn = 0; // Wake up the pressure sensor
}
else if (!gConnected)
{
printf("Beacon format!\n");
ble.gap().clearAdvertisingPayload();
ble.gap().accumulateAdvertisingPayload(
GapAdvertisingData::BREDR_NOT_SUPPORTED);
ble.gap().accumulateAdvertisingPayload(
GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA,
(uint8_t*)&iBeaconMSD, sizeof(iBeaconMSD_t));
ble.gap().startAdvertising();
}
if(++advertisementType > 2) advertisementType = 0;
macServicePtr->setAdvData((uint8_t*)&advertisementPacket);
}
int main()
{
Thread bleT;
power = 1;
wait_ms(WAKEUP_TIME_DELAY_MS);
temperaturePower = 1;
lightPower = 1;
shdn = 1; // Wake up the pressure sensor
analogIn.addChannel(9); // Set VDD as source to SAADC
analogIn.addChannel(6); // Light
analogIn.addChannel(7); // Temp
analogIn.calibrate();
BLE &ble = BLE::Instance();
ble.init(bleInitCompleteSensors);
while(ble.hasInitialized() == false){
/* spin loop */
}
ble.onEventsToProcess(scheduleBleEventsProcessing);
advertisementPacket.header = APPLICATION_ID;
I2C i2c(I2C_DATA, I2C_CLK);
si = new Si7006(&i2c);
mems = new LSM9DS1(&i2c);
spi = new SPI(SPI_MOSI, SPI_MISO, SPI_SCLK);
mpl115a1 = new MPL115A1(*spi, cs);
eventQueue.call_every(UPDATE_SENSORS_TIME_MS, updateData);
// This call stops main thread
eventQueue.dispatch_forever();
}


