aconno acnsensa project for iOS devices with iBeacon packets support.
Dependencies: LSM9DS1 Si7006A20 aconno_SEGGER_RTT aconno_bsp adc52832_common
main.cpp
- Committer:
- jurica238814
- Date:
- 2017-11-27
- Revision:
- 0:12899fa39f88
- Child:
- 1:326ce5e200fb
File content as of revision 0:12899fa39f88:
/* * aconno.de * Made by Jurica Resetar * 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" #define V0 0.47 /* In volts */ #define TC 0.01 /* In volts */ #define VCC (3.6) #define DEBUG_PRINT (0) #define SLEEP_TIME (0.150) /* Sleep time in seconds */ #define WAKE_UP_TIME (0.150) /* Awake time in ms */ #define MSD_SIZE (25) /* Manufacturer Specific Data lenght (in B) */ #define ADV_INTERVAL (100) /* Advertising interval in ms */ #define TX_POWER (4) /* TX power (in dB) */ #define GO_TO_SLEEP (0) /* Sleep flag: 0 -> Device will not go to sleep, 1 -> Will go to sleep mode */ // Definitions of the location within MSD for the data #define ADV_TYPE (4) #define GYRO (5) #define ACC (11) #define MAGNETO (17) #define TEMPERATURE (5) #define HUMIDITY (9) #define PRESSURE (13) #define LIGHT (17) AnalogIn temperature(ADC_TEMP); AnalogIn light(ADC_LIGHT); NRF52_DigitalOut lightPower(p28); NRF52_DigitalOut temperaturePower(p31); SPI spi(p3, p5, p4); // mosi, miso, sclk NRF52_DigitalOut cs(p7); NRF52_DigitalOut shdn(p6); NRF52_DigitalOut led(p23); NRF52_DigitalOut power(p2); Si7006 *si; LSM9DS1 *mems; #if DEBUG_PRINT #include "nrf52_uart.h" NRF52_UART serial = NRF52_UART(p25,p26,Baud9600); //Tx, RX BaudRate uint8_t charCounter; char buffer[256] = {0}; #define SEND(...) {uint8_t len = sprintf(buffer, __VA_ARGS__); serial.send(buffer, len);} #else #define SEND(...); #endif bool SLEEP = true; int8_t txPower = 4; union float2bytes{ float f; char b[sizeof(float)]; }; float2bytes temp2byte; float2bytes hum2byte; float2bytes light2byte; float2bytes pressure2byte; uint16_t a0_frac_mask = 0x0007; uint8_t a0_frac_bits = 3; uint16_t b1_frac_mask = 0x1FFF; uint8_t b1_frac_bits = 13; uint16_t b2_frac_mask = 0x3FFF; uint8_t b2_frac_bits = 14; uint16_t c12_frac_mask = 0x1FFF; uint8_t c12_frac_bits = 22; int16_t memsBuffer[3]; int16_t memsAccInit[3]={0,0,0}; int16_t memsGyroInit[3]={0,0,0}; int16_t memsMagInit[3]={0,0,0}; BLE &ble = BLE::Instance(); GapAdvertisingData adv_data = GapAdvertisingData(); uint8_t MSD[MSD_SIZE] = {0x59, 0x00, 0x17, 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /** * Restart Advertising on disconnection */ void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params){ BLE::Instance().gap().startAdvertising(); } /** * Function for waking the core up */ void wakeMeUp(void){ SLEEP = false; } /** * This function is called when the ble initialization process has failed */ void onBleInitError(BLE &ble, ble_error_t error){ /* Avoid compiler warnings */ (void) ble; (void) error; /* Initialization error handling should go here */ } /** * 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) { /* In case of error, forward the error handling to onBleInitError */ onBleInitError(ble, error); 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 *)MSD, MSD_SIZE); ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED); ble.gap().setAdvertisingInterval(ADV_INTERVAL); ble.gap().startAdvertising(); } void getLight(uint8_t *light_data){ light2byte.f = light.read() * 100; *(light_data+0) = light2byte.b[0]; *(light_data+1) = light2byte.b[1]; *(light_data+2) = light2byte.b[2]; *(light_data+3) = light2byte.b[3]; } float voltage2temp(float vOut){ return ((float)vOut - (float)V0)/((float)TC); } void getTemperature(uint8_t *temperature_data){ temp2byte.f = voltage2temp(temperature.read()*(float)VCC); *(temperature_data+0) = temp2byte.b[0]; *(temperature_data+1) = temp2byte.b[1]; *(temperature_data+2) = temp2byte.b[2]; *(temperature_data+3) = temp2byte.b[3]; } void getHumidity(uint8_t *hum_data){ //float temp; float humid; si->getHumidity(&humid); //si.getTemperature(&temp); hum2byte.f = humid; *(hum_data+0) = hum2byte.b[0]; *(hum_data+1) = hum2byte.b[1]; *(hum_data+2) = hum2byte.b[2]; *(hum_data+3) = hum2byte.b[3]; } void readGyro(int8_t *gyro_data){ mems->readGyro(memsBuffer); // Use init data values memsBuffer[0] -= memsGyroInit[0]; memsBuffer[1] -= memsGyroInit[1]; memsBuffer[2] -= memsGyroInit[2]; gyro_data[0] = memsBuffer[0] & 0xFF; // X axis gyro_data[1] = (memsBuffer[0] >> 8); // X axis gyro_data[2] = memsBuffer[1] & 0xFF; // Y axis gyro_data[3] = (memsBuffer[1] >> 8); // Y axis gyro_data[4] = memsBuffer[2] & 0xFF; // Z axis gyro_data[5] = (memsBuffer[2] >> 8); // Z axis } void readMyAcc(int8_t *acc_data){ mems->readAcc(memsBuffer); // Use init data values memsBuffer[0] -= memsAccInit[0]; memsBuffer[1] -= memsAccInit[1]; memsBuffer[2] -= memsAccInit[2]; acc_data[0] = memsBuffer[0] & 0xFF; // X axis acc_data[1] = (memsBuffer[0] >> 8); // X axis acc_data[2] = memsBuffer[1] & 0xFF; // Y axis acc_data[3] = (memsBuffer[1] >> 8); // Y axis acc_data[4] = memsBuffer[2] & 0xFF; // Z axis acc_data[5] = (memsBuffer[2] >> 8); // Z axis } void readMagneto(int8_t *magneto_data){ mems->readMag(memsBuffer); // Use init data values memsBuffer[0] -= memsMagInit[0]; memsBuffer[1] -= memsMagInit[1]; memsBuffer[2] -= memsMagInit[2]; magneto_data[0] = memsBuffer[0] * 0xFF; // X axis magneto_data[1] = (memsBuffer[0] >> 8); // X axis magneto_data[2] = memsBuffer[1] * 0xFF; // X axis magneto_data[3] = (memsBuffer[1] >> 8); // X axis magneto_data[4] = memsBuffer[2] * 0xFF; // X axis magneto_data[5] = (memsBuffer[2] >> 8); // X axis } void calibrateAcc(){ uint8_t counter=0; int8_t acc_data[6]; for(counter=0; counter<20; counter++){ readMyAcc(acc_data); memsAccInit[0] += acc_data[0]; memsAccInit[1] += acc_data[1]; memsAccInit[2] += acc_data[2]; } memsAccInit[0] /= counter; memsAccInit[1] /= counter; memsAccInit[2] /= counter; } void calibrateGyro(){ uint8_t counter; int8_t gyro_data[6]; for(counter=0; counter<20; counter++){ readMyAcc(gyro_data); memsGyroInit[0] += gyro_data[0]; memsGyroInit[1] += gyro_data[1]; memsGyroInit[2] += gyro_data[2]; } memsGyroInit[0] /= counter; memsGyroInit[1] /= counter; memsGyroInit[2] /= counter; } void calibrateMag(){ uint8_t counter=0; int8_t mag_data[6]; for(counter=0; counter<20; counter++){ readMyAcc(mag_data); memsMagInit[0] += mag_data[0]; memsMagInit[1] += mag_data[1]; memsMagInit[2] += mag_data[2]; } memsMagInit[0] /= counter; memsMagInit[1] /= counter; memsMagInit[2] /= counter; } float get_a0(uint16_t a0){ float temp_a0; float temp_frac; int temp_a0_int; uint8_t negative_flag = 0; if(a0& 0x8000){ a0 ^= 0xFFFF; // Transform from 2's complement a0 -= 1; negative_flag = 1; } temp_a0_int = a0 & 0x7FF8; temp_a0_int = temp_a0_int >> a0_frac_bits; temp_a0 = temp_a0_int * 1.0; // Int part temp_frac = (1.0/(pow(2.0,3))); temp_frac *= (a0 & a0_frac_mask); temp_a0 = temp_a0 + temp_frac; if(negative_flag) temp_a0 = -temp_a0; return temp_a0; } float get_b1(uint16_t b1){ float temp_b1; float temp_frac; int temp_b1_int; uint8_t negative_flag = 0; if (b1 & 0x8000){ b1 ^= 0xFFFF; b1 -= 1; negative_flag = 1; } temp_b1_int = b1 & 0x6000; temp_b1_int = temp_b1_int >> b1_frac_bits; temp_b1 = temp_b1_int * 1.0; temp_frac = (b1 & b1_frac_mask) * (1.0/(pow(2.0,b1_frac_bits))); temp_b1 = temp_b1 + temp_frac; if (negative_flag) temp_b1 = -temp_b1; return temp_b1; } float get_b2(uint16_t b2){ float temp_b2; float temp_frac; int temp_b2_int; uint8_t negative_flag = 0; if (b2 & 0x8000){ b2 ^= 0xFFFF; b2 -= 1; negative_flag = 1; } temp_b2_int = b2 & 0x4000; temp_b2_int = temp_b2_int >> b2_frac_bits; temp_b2 = temp_b2_int * 1.0; temp_frac = (b2 & b2_frac_mask) * (1.0/(pow(2.0,b2_frac_bits))); temp_b2 = temp_b2 + temp_frac; if (negative_flag) temp_b2 = -temp_b2; return temp_b2; } float get_c12(uint16_t c12){ float temp_c12; float temp_frac; uint8_t negative_flag = 0; c12 = c12 >> 2; if (c12 & 0x2000){ c12 ^= 0xFFFF; c12 -= 1; negative_flag = 1; } temp_c12 = 0.000000000; temp_frac = (c12 & c12_frac_mask) * (1.0/(pow(2.0,c12_frac_bits))); temp_c12 = temp_c12 + temp_frac; if (negative_flag) temp_c12 = -temp_c12; return temp_c12; } void get_pressure(uint8_t *pressure_ret){ float pcomp = 0x00; volatile float pressure; uint16_t a0 = 0; uint16_t b1 = 0; uint16_t b2 = 0; uint16_t c12 = 0; uint16_t padc = 0; uint16_t tadc = 0; float a0_f, b1_f, b2_f, c12_f; cs = 0; spi.write(0x88); // MSB a0 a0 = spi.write(0x00); a0 = a0 << 8; wait_ms(1); spi.write(0x8A); // LSB a0 a0 |= spi.write(0x00); wait_ms(1); spi.write(0x8C); // MSB b1 b1 = spi.write(0x00); b1 = b1 << 8; wait_ms(1); spi.write(0x8E); // LSB b1 b1 |= spi.write(0x00); wait_ms(1); spi.write(0x90); // MSB b2 b2 = spi.write(0x00); b2 = b2 << 8; wait_ms(1); spi.write(0x92); // LSB b2 b2 |= spi.write(0x00); wait_ms(1); spi.write(0x94); // MSB c12 c12 = spi.write(0x00); c12 = c12 << 8; wait_ms(1); spi.write(0x96); // LSB c12 c12 |= spi.write(0x00); wait_ms(1); spi.write(0x00); cs = 1; cs = 0; spi.write(0x24); // Start conversion spi.write(0x00); cs = 1; wait_ms(3); cs = 0; spi.write(0x80); padc = spi.write(0x00); // MSB Padc padc = padc << 8; spi.write(0x82); padc |= spi.write(0x00); // LSB Padc padc = padc >> 6; spi.write(0x84); tadc = spi.write(0x00); // MSB Padc tadc = tadc << 8; spi.write(0x86); tadc |= spi.write(0x00); // LSB Padc tadc = tadc >> 6; spi.write(0x00); cs = 1; a0_f = get_a0(a0); b1_f = get_b1(b1); b2_f = get_b2(b2); c12_f = get_c12(c12); /* float c12x2 = c12_f * tadc; float a1_f = b1_f + c12x2; float a1x1 = a1_f * padc; float y1 = a0_f + a1x1; float a2x2 = b2_f * tadc; pcomp = y1 + a2x2; */ pcomp = a0_f + (b1_f + c12_f * tadc) * padc + b2_f * tadc; pressure = pcomp * ((115-50)/(1023.0)) + 52; // Was + 50 pressure *= 10; // Calculate in hPa pressure2byte.f = pressure; *(pressure_ret+0) = pressure2byte.b[0]; *(pressure_ret+1) = pressure2byte.b[1]; *(pressure_ret+2) = pressure2byte.b[2]; *(pressure_ret+3) = pressure2byte.b[3]; } void updateData(){ uint8_t temperature_data[4]; uint8_t light_data[4]; int8_t gyro_data[6]; int8_t acc_data[6]; int8_t magneto_data[6]; uint8_t hum_data[4]; uint8_t pressure_data[4]; static uint8_t adv_type = 0; if(adv_type < 1){ // Set adv type MSD[ADV_TYPE] = 0x00; // Read gyro readGyro(gyro_data); MSD[GYRO+0] = *(gyro_data+0); // X axis MSD[GYRO+1] = *(gyro_data+1); // X axis MSD[GYRO+2] = *(gyro_data+2); // Y axis MSD[GYRO+3] = *(gyro_data+3); // Y axis MSD[GYRO+4] = *(gyro_data+4); // Z axis MSD[GYRO+5] = *(gyro_data+5); // Z axis // Read acc readMyAcc(acc_data); MSD[ACC+0] = *(acc_data+0); // X axis MSD[ACC+1] = *(acc_data+1); // X axis MSD[ACC+2] = *(acc_data+2); // Y axis MSD[ACC+3] = *(acc_data+3); // Y axis MSD[ACC+4] = *(acc_data+4); // Z axis MSD[ACC+5] = *(acc_data+5); // Z axis // Read magneto readMagneto(magneto_data); //magneto_data[0] = 0x11; //magneto_data[1] = 0x23; MSD[MAGNETO+0] = *(magneto_data+0); // X axis MSD[MAGNETO+1] = *(magneto_data+1); // X axis MSD[MAGNETO+2] = *(magneto_data+2); // Y axis MSD[MAGNETO+3] = *(magneto_data+3); // Y axis MSD[MAGNETO+4] = *(magneto_data+4); // Z axis MSD[MAGNETO+5] = *(magneto_data+5); // Z axis } else{ // Set adv type MSD[ADV_TYPE] = 0x01; // Read temperature getTemperature(temperature_data); MSD[TEMPERATURE+0] = *(temperature_data+0); MSD[TEMPERATURE+1] = *(temperature_data+1); MSD[TEMPERATURE+2] = *(temperature_data+2); MSD[TEMPERATURE+3] = *(temperature_data+3); // Read light getLight(light_data); MSD[LIGHT+0] = *(light_data+0); MSD[LIGHT+1] = *(light_data+1); MSD[LIGHT+2] = *(light_data+2); MSD[LIGHT+3] = *(light_data+3); // Read Pressure get_pressure(pressure_data); MSD[PRESSURE+0] = *(pressure_data+0); MSD[PRESSURE+1] = *(pressure_data+1); MSD[PRESSURE+2] = *(pressure_data+2); MSD[PRESSURE+3] = *(pressure_data+3); // Read Humidity getHumidity(hum_data); MSD[HUMIDITY+0] = *(hum_data+0); MSD[HUMIDITY+1] = *(hum_data+1); MSD[HUMIDITY+2] = *(hum_data+2); MSD[HUMIDITY+3] = *(hum_data+3); } adv_type++; if(adv_type>2) adv_type = 0; adv_data = ble.getAdvertisingData(); adv_data.updateData(adv_data.MANUFACTURER_SPECIFIC_DATA, MSD, 25); ble.setAdvertisingData(adv_data); } int main(void){ SEND("Main started.\r\n"); power = 1; SEND("Main power regulator turned ON.\r\n"); wait_ms(150); temperaturePower = 1; SEND("Temperature power turned ON.\r\n"); lightPower = 1; SEND("Light power turned ON.\r\n"); shdn = 1; // Wake up the pressure sensor SEND("Pressure sensor woken up.\r\n"); /* while(1){ led = !led; wait_ms(500); } */ I2C i2c(p19, p20); si = new Si7006(&i2c); mems = new LSM9DS1(i2c); mems->startAcc(); mems->startGyro(); mems->startMag(); led = 1; Ticker ticker; ticker.attach(wakeMeUp, SLEEP_TIME); // Wake the device up ble.init(bleInitComplete); ble.gap().setTxPower(TX_POWER); // Set TX power to TX_POWER /* SpinWait for initialization to complete. This is necessary because the * BLE object is used in the main loop below. */ while (ble.hasInitialized() == false) { /* spin loop */ } while (true){ if (SLEEP && GO_TO_SLEEP){ ble.gap().stopAdvertising(); sleep(); ble.waitForEvent(); } else{ // I'm awake updateData(); ble.gap().startAdvertising(); wait_ms(WAKE_UP_TIME); SLEEP = true; } } }