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-07-23
- Branch:
- normal_axis
- Revision:
- 12:46fbc77fab33
- Parent:
- 9:0453d592221b
- Child:
- 13:4747e6e8396a
File content as of revision 12:46fbc77fab33:
/* * 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" #define V0 0.47 /* In volts */ #define TC 0.01 /* In volts */ #define VCC (3.6) #define VALUE_TO_PERCENTAGE (100) #define WAKEUP_TIME_DELAY_MS (150) #define APPLICATION_ID (0xCF170059) #define ADC_REFERENCE (3.6f) /* adc reference voltage */ #define ADC_RESOLUTION (1024) /* 10-bit adc */ #define I2C_DATA (p19) #define I2C_CLK (p20) #define SPI_MISO (p5) #define SPI_MOSI (p3) #define SPI_SCLK (p4) #define DEBUG (0) #define DEBUG_PRINT (1) #define SLEEP_TIME (0.150) /* Sleep time in seconds */ #define WAKE_UP_TIME (0.150) /* Awake time in ms */ #define ADV_INTERVAL (100) /* Advertising interval in ms */ #define GO_TO_SLEEP (0) /* Sleep flag: 0 -> Device will not go to sleep, 1 -> Will go to sleep mode */ #define CALIBRATION_STEPS (20) #define TX_POWER (4) static NRF52_SAADC analogIn; static NRF52_DigitalOut lightPower(p28); static NRF52_DigitalOut temperaturePower(p31); static NRF52_DigitalOut shdn(p6); static NRF52_DigitalOut led(p23); static NRF52_DigitalOut power(p2); static NRF52_DigitalOut cs(p7); static Si7006 *si; static LSM9DS1 *mems; static SPI *spi; static MPL115A1 *mpl115a1; #if DEBUG_PRINT #include "nrf52_uart.h" NRF52_UART serial = NRF52_UART(p25, p26, Baud9600); //Tx, RX BaudRate char buffer[256] = {0}; #define SEND(...) {uint8_t len = sprintf(buffer, __VA_ARGS__); serial.send(buffer, len);} #define SENDN(...) {uint8_t len = sprintf(buffer "\n\r", __VA_ARGS__); serial.send(buffer, len);} #else #define SEND(...); #define SENDN(...); #endif static bool sleepFlag = true; static vector3_s memsAccelerometerInit; static vector3_s memsGyroscopeInit; static vector3_s memsMagnetometerInit; static BLE &ble = BLE::Instance(); static GapAdvertisingData adv_data = GapAdvertisingData(); 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; }; }; }; static advertising_packet advertisementPacket; void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params){ // Restart Advertising on disconnection BLE::Instance().gap().startAdvertising(); } /** * Function for waking the core up */ void wakeMeUp(){ sleepFlag = false; } /** * Callback triggered when the ble initialization process has finished */ void bleInitComplete(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; } 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_NON_CONNECTABLE_UNDIRECTED); ble.gap().setAdvertisingInterval(ADV_INTERVAL); ble.gap().setTxPower(TX_POWER); // Set TX power to TX_POWER ble.gap().startAdvertising(); } 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 uint8_t advertisementType = 0; if(advertisementType < 1){ advertisementPacket.type = 0x00; readGyroscope((vector3_s *)advertisementPacket.gyroscope); readAccelerometer((vector3_s *)advertisementPacket.accelerometer); readMagnetometer((vector3_s *)advertisementPacket.magnetometer); advertisementPacket.acc_lsb_value = (0xF9E);//(0x3D80); // ^--- That's in ug cuz MSB is 1 } else{ analogIn.updateData(); advertisementPacket.type = 0x01; advertisementPacket.temperature = getTemperature(); advertisementPacket.light = getLight(); advertisementPacket.humidity = getHumidity(); advertisementPacket.pressure = mpl115a1->getPressure(); advertisementPacket.battery = getBattery(); } #if DEBUG == 0 if(++advertisementType > 2) advertisementType = 0; #endif adv_data = ble.getAdvertisingData(); adv_data.updateData(adv_data.MANUFACTURER_SPECIFIC_DATA, (uint8_t *)&advertisementPacket, sizeof(advertisementPacket)); ble.setAdvertisingData(adv_data); } #if DEBUG void do_per() { /* SEND("T: %f\r\nL: %f\r\nH: %f\r\nP: %f\r\nB: %d\r\n", advertisementPacket.temperature, advertisementPacket.light, advertisementPacket.humidity, advertisementPacket.pressure, advertisementPacket.battery); */ SEND("G: %6d %6d %6d\r\nA: %6d %6d %6d\r\nM: %6d %6d %6d\r\n", advertisementPacket.gyroscope[0], advertisementPacket.gyroscope[1], advertisementPacket.gyroscope[2], advertisementPacket.accelerometer[0], advertisementPacket.accelerometer[1], advertisementPacket.accelerometer[2], advertisementPacket.magnetometer[0], advertisementPacket.magnetometer[1], advertisementPacket.magnetometer[2]); } #endif int main(){ 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(); advertisementPacket.header = APPLICATION_ID; ble.init(bleInitComplete); 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); mems->startAccelerometer(); mems->startGyroscope(); mems->startMagnetometer(); led = 1; Ticker ticker; ticker.attach(wakeMeUp, SLEEP_TIME); // Wake the device up #if DEBUG Ticker per; per.attach(do_per, 1); #endif while(ble.hasInitialized() == false){ /* spin loop */ } while(true){ if (sleepFlag && GO_TO_SLEEP){ ble.gap().stopAdvertising(); sleep(); ble.waitForEvent(); } else{ // I'm awake updateData(); ble.gap().startAdvertising(); wait_ms(WAKE_UP_TIME); sleepFlag = true; } } }