Jurica Resetar / Mbed OS iBeacon acnsensa

Dependencies:   LSM9DS1 Si7006A20 aconno_SEGGER_RTT aconno_bsp adc52832_common

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002  * aconno.de
00003  * Made by Jurica Resetar
00004  * Edited by Karlo Milicevic
00005  * Edited by Dominik Bartolovic
00006  * All right reserved
00007  *
00008  */
00009 
00010 #include "mbed.h"
00011 #include "ble/BLE.h"
00012 #include "acd52832_bsp.h"
00013 #include "GapAdvertisingData.h"
00014 #include "Si7006A20.h"
00015 #include "LSM9DS1.h"
00016 #include "math.h"
00017 #include "nrf52_digital.h"
00018 #include "adc52832_common/utilities.h"
00019 #include "MPL115A1.h"
00020 #include "acd_nrf52_saadc.h"
00021 #include "service.h"
00022 #include <events/mbed_events.h>
00023 #include "aconnoConfig.h"
00024 
00025 uint8_t gConnected = 0;
00026 
00027 static NRF52_SAADC analogIn;
00028 static NRF52_DigitalOut lightPower(p28);
00029 static NRF52_DigitalOut temperaturePower(p31);
00030 static NRF52_DigitalOut shdn(p6);
00031 static NRF52_DigitalOut power(p2);
00032 static NRF52_DigitalOut cs(p7);
00033 static Si7006   *si;
00034 static LSM9DS1  *mems;
00035 static SPI      *spi;
00036 static MPL115A1 *mpl115a1;
00037 
00038 static EventQueue eventQueue(32 * EVENTS_EVENT_SIZE);
00039 uint8_t myMacAddress[6] = {};
00040 MACService *macServicePtr;
00041 
00042 #if DEBUG_PRINT
00043     #include "SEGGER_RTT.h"
00044     #define printf(...) SEGGER_RTT_printf(0, __VA_ARGS__)
00045 #else
00046     #define printf(...)
00047 #endif
00048 
00049 static vector3_s memsAccelerometerInit;
00050 static vector3_s memsGyroscopeInit;
00051 static vector3_s memsMagnetometerInit;
00052 
00053 static GapAdvertisingData adv_data = GapAdvertisingData();
00054 
00055 struct __attribute__((packed, aligned(1))) iBeaconMSD_t
00056 {
00057     // AppleID is constant
00058     uint16_t appleID;
00059     // secondID is constant
00060     uint8_t  secondID;
00061     // DataSize is constant
00062     uint8_t  dataSize;
00063     uint8_t  UUID[16];
00064     uint16_t  major;
00065     uint16_t  minor;
00066     int8_t   RSSI;
00067 }static iBeaconMSD = {.appleID = 0x004C,
00068                       .secondID = 0x02,
00069                       .dataSize = 0x15,
00070                       .UUID = {UUID_INIT},
00071                       .major = MAJOR,
00072                       .minor = MINOR,
00073                       .RSSI = RSSI_INIT};
00074 
00075 struct __attribute__((packed, aligned(1))) advertising_packet
00076 {
00077     uint32_t header;
00078     uint8_t  type;
00079     union{
00080         struct{
00081             int16_t gyroscope[3];
00082             int16_t accelerometer[3];
00083             int16_t magnetometer[3];
00084             uint16_t acc_lsb_value;
00085         };
00086         struct{
00087             float temperature;
00088             float humidity;
00089             float pressure;
00090             float light;
00091             uint8_t battery;
00092         };
00093     };
00094 };
00095 
00096 void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context)
00097 {
00098     BLE &ble = context->ble;
00099     eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
00100 }
00101 
00102 static advertising_packet advertisementPacket;
00103 const int advDataSize = sizeof(advertising_packet);
00104 
00105 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
00106 {
00107     //  Restart Advertising on disconnection
00108     gConnected = 0;
00109     BLE::Instance().gap().startAdvertising();
00110 }
00111 
00112 void onConnectionCallback(const Gap::ConnectionCallbackParams_t *params)
00113 {
00114     printf("Connection callback.\n");
00115     gConnected = 1;
00116 }
00117 
00118 /**
00119  * Callback triggered when the ble initialization process has finished
00120  */
00121 void bleInitCompleteSensors(BLE::InitializationCompleteCallbackContext *params)
00122 {
00123     BLE&        ble   = params->ble;
00124     ble_error_t error = params->error;
00125 
00126     if (error != BLE_ERROR_NONE){
00127         return;
00128     }
00129 
00130     /* Ensure that it is the default instance of BLE */
00131     if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE){
00132         return;
00133     }
00134 
00135     uint8_t mac[6] = {0,0,0,0,0,0};
00136     uint8_t initAdvData[] = {0};
00137     BLEProtocol::AddressType_t temp_address_type;
00138     ble.gap().getAddress(&temp_address_type, myMacAddress);
00139     macServicePtr = new MACService(ble, mac, initAdvData);
00140     macServicePtr->updateMacAddress(myMacAddress);    // Update MAC address
00141 
00142     ble.gap().onConnection(onConnectionCallback);
00143     ble.gap().onDisconnection(disconnectionCallback);
00144 
00145     /* setup advertising */
00146     ble.gap().accumulateAdvertisingPayload(
00147         GapAdvertisingData::BREDR_NOT_SUPPORTED);
00148     ble.gap().accumulateAdvertisingPayload(
00149         GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA,
00150         (uint8_t *)&advertisementPacket, sizeof(advertisementPacket));
00151     ble.gap().setAdvertisingType(
00152         GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
00153     ble.gap().setAdvertisingInterval(ADV_INTERVAL);
00154     printf("Init started....\t\t");
00155     ble.gap().setTxPower(TX_POWER_DB);        // Set TX power to TX_POWER_DB
00156     ble.gap().startAdvertising();
00157     printf("Init done.\n");
00158 }
00159 
00160 float getLight()
00161 {
00162     return ((float)analogIn.getData()[1])/ADC_RESOLUTION * VALUE_TO_PERCENTAGE;
00163 }
00164 
00165 float voltage2temp(float vOut)
00166 {
00167     return ((float)vOut - (float)V0)/((float)TC);
00168 }
00169 
00170 float getTemperature()
00171 {
00172     return voltage2temp(((float)analogIn.getData()[2])/ADC_RESOLUTION * (float)VCC);
00173 }
00174 
00175 uint8_t getBattery()
00176 {
00177     uint16_t batteryVoltage = analogIn.getData()[0];
00178     const uint16_t zero_percent_limit = 739;
00179     const uint16_t onehundred_percent_limit = 810;
00180     const uint16_t percentage_increments = 5;
00181     uint8_t percentage;
00182 
00183     if (batteryVoltage < zero_percent_limit)
00184     {
00185         percentage = 0;
00186     }
00187     else if(batteryVoltage > onehundred_percent_limit)
00188     {
00189         percentage = 100;
00190     }
00191     else
00192     {
00193         batteryVoltage -= zero_percent_limit;
00194         percentage = (batteryVoltage*100)/(onehundred_percent_limit - zero_percent_limit);
00195         percentage = percentage/percentage_increments*percentage_increments;
00196     }
00197 
00198     return percentage;
00199 }
00200 
00201 float getHumidity()
00202 {
00203     float result;
00204     si->getHumidity(&result);
00205     return result;
00206 }
00207 
00208 void readGyroscope(vector3_s *gyroscopeData)
00209 {
00210     mems->readGyroscope((int16_t *)gyroscopeData);
00211     *gyroscopeData -= memsGyroscopeInit;
00212 }
00213 
00214 void readAccelerometer(vector3_s *accelerometerData)
00215 {
00216     mems->readAccelerometer((int16_t *)accelerometerData);
00217     *accelerometerData -= memsAccelerometerInit;
00218 }
00219 
00220 void readMagnetometer(vector3_s *magnetometerData){
00221     mems->readMagnetometer((int16_t *)magnetometerData);
00222     *magnetometerData -= memsMagnetometerInit;
00223 }
00224 
00225 void calibrateAccelerometer(){
00226     vector3_s accelerometerData;
00227     for(uint8_t counter = 0; counter < CALIBRATION_STEPS; ++counter)
00228     {
00229         readAccelerometer(&accelerometerData);
00230         memsAccelerometerInit += accelerometerData;
00231     }
00232     memsAccelerometerInit /= CALIBRATION_STEPS;
00233 }
00234 
00235 void calibrateGyroscope(){
00236     vector3_s gyroscopeData;
00237     for(uint8_t counter = 0; counter < CALIBRATION_STEPS; ++counter)
00238     {
00239         readGyroscope(&gyroscopeData);
00240         memsGyroscopeInit += gyroscopeData;
00241     }
00242     memsGyroscopeInit /= CALIBRATION_STEPS;
00243 }
00244 
00245 void calibrateMag(){
00246     vector3_s magnetometerData;
00247     for(uint8_t counter = 0; counter < CALIBRATION_STEPS; ++counter)
00248     {
00249         readMagnetometer(&magnetometerData);
00250         memsMagnetometerInit += magnetometerData;
00251     }
00252     memsMagnetometerInit /= CALIBRATION_STEPS;
00253 }
00254 
00255 void updateData(){
00256     static uint16_t serviceUuid = macServicePtr->SERVICE_UUID;
00257     static uint8_t advertisementType = 0;
00258     int16_t temp_acc[3];
00259     BLE &ble = BLE::Instance();
00260 
00261     if(!advertisementType && !gConnected)
00262     {
00263         power = 1;
00264         wait_ms(WAKEUP_TIME_DELAY_MS);
00265         mems->startAccelerometer();
00266         mems->startGyroscope();
00267         mems->startMagnetometer();
00268 
00269         printf("Sensor format 1.\n");
00270         ble.gap().clearAdvertisingPayload();
00271         /* setup advertising */
00272         ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)&(serviceUuid), sizeof(serviceUuid));
00273         ble.gap().accumulateAdvertisingPayload(
00274             GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA,
00275             (uint8_t *)&advertisementPacket, sizeof(advertisementPacket));
00276         ble.gap().setAdvertisingType(
00277             GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
00278 
00279         adv_data = ble.getAdvertisingData();
00280         advertisementPacket.type = 0x00;
00281         
00282         wait_ms(WAKEUP_TIME_DELAY_MS);
00283         
00284         readGyroscope((vector3_s *)advertisementPacket.gyroscope);
00285         readAccelerometer((vector3_s *)temp_acc);
00286         readMagnetometer((vector3_s *)advertisementPacket.magnetometer);
00287         advertisementPacket.acc_lsb_value = (0xF9E);
00288         // ^--- That's in ug cuz MSB is 1
00289         #if INVERT_AXES
00290             advertisementPacket.accelerometer[0] = temp_acc[1];
00291             advertisementPacket.accelerometer[1] = temp_acc[0];
00292             advertisementPacket.accelerometer[2] = temp_acc[2];
00293         #endif
00294 
00295         adv_data.updateData(adv_data.MANUFACTURER_SPECIFIC_DATA,
00296             (uint8_t *)&advertisementPacket, sizeof(advertisementPacket));
00297         ble.setAdvertisingData(adv_data);
00298 
00299         power = 0;
00300         wait_ms(WAKEUP_TIME_DELAY_MS);
00301     }
00302     else if (advertisementType == 1 && !gConnected)
00303     {
00304         power = 1;
00305         wait_ms(WAKEUP_TIME_DELAY_MS);
00306         temperaturePower = 1;
00307         lightPower = 1;
00308         shdn = 1; // Wake up the pressure sensor
00309         
00310         wait_ms(WAKEUP_TIME_DELAY_MS);
00311 
00312         printf("Sensor format 2.\n");
00313         analogIn.updateData();
00314         adv_data = ble.getAdvertisingData();
00315         advertisementPacket.type = 0x01;
00316         advertisementPacket.temperature = getTemperature();
00317         advertisementPacket.light       = getLight();
00318         advertisementPacket.humidity    = getHumidity();
00319         advertisementPacket.pressure    = mpl115a1->getPressure();
00320         advertisementPacket.battery     = getBattery();
00321 
00322         adv_data.updateData(adv_data.MANUFACTURER_SPECIFIC_DATA,
00323             (uint8_t *)&advertisementPacket, sizeof(advertisementPacket));
00324         ble.setAdvertisingData(adv_data);
00325 
00326         power = 0;
00327         wait_ms(WAKEUP_TIME_DELAY_MS);
00328         temperaturePower = 0;
00329         lightPower = 0;
00330         shdn = 0; // Wake up the pressure sensor
00331     }
00332 
00333     else if (!gConnected)
00334     {
00335         printf("Beacon format!\n");
00336         ble.gap().clearAdvertisingPayload();
00337         ble.gap().accumulateAdvertisingPayload(
00338             GapAdvertisingData::BREDR_NOT_SUPPORTED);
00339         ble.gap().accumulateAdvertisingPayload(
00340             GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA,
00341             (uint8_t*)&iBeaconMSD, sizeof(iBeaconMSD_t));
00342         ble.gap().startAdvertising();
00343     }
00344     if(++advertisementType > 2) advertisementType = 0;
00345     
00346     macServicePtr->setAdvData((uint8_t*)&advertisementPacket);
00347 }
00348 
00349 int main()
00350 {
00351     Thread bleT;
00352 
00353     power = 1;
00354     wait_ms(WAKEUP_TIME_DELAY_MS);
00355     temperaturePower = 1;
00356     lightPower = 1;
00357     shdn = 1; // Wake up the pressure sensor
00358 
00359     analogIn.addChannel(9); // Set VDD  as source to SAADC
00360     analogIn.addChannel(6); // Light
00361     analogIn.addChannel(7); // Temp
00362     analogIn.calibrate();
00363 
00364     BLE &ble = BLE::Instance();
00365     ble.init(bleInitCompleteSensors);
00366     while(ble.hasInitialized() == false){
00367         /* spin loop */
00368     }
00369     ble.onEventsToProcess(scheduleBleEventsProcessing);
00370     advertisementPacket.header = APPLICATION_ID;
00371 
00372     I2C i2c(I2C_DATA, I2C_CLK);
00373     si       = new Si7006(&i2c);
00374     mems     = new LSM9DS1(&i2c);
00375     spi      = new SPI(SPI_MOSI, SPI_MISO, SPI_SCLK);
00376     mpl115a1 = new MPL115A1(*spi, cs);
00377 
00378     eventQueue.call_every(UPDATE_SENSORS_TIME_MS, updateData);
00379 
00380     // This call stops main thread
00381     eventQueue.dispatch_forever();
00382 }