LIS3DH & BLE broadcast example for VTT Node V3 & mbed
Dependencies: BLE_API TMP_nrf51 mbed nRF51822
main.cpp
- Committer:
- jejuho
- Date:
- 2015-12-08
- Revision:
- 0:de3e4a57ebe0
- Child:
- 1:bd7fd35251ab
File content as of revision 0:de3e4a57ebe0:
#include "mbed.h" #include "ble/BLE.h" #define USE_DFU #ifdef USE_DFU #include "DFUService.h" #endif #include "AT45.h" #include "LIS3DH.h" //interrupt /gpio configuration #include "nrf_gpio.h" #include "nrf_gpiote.h" #include "nrf_soc.h" //SPI stuff #define MOSI p8 #define MISO p9 #define SCLK p7 #define CS p2 //#include "app_error.h" //void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name) { } //const static char DEVICE_NAME[] = "BAc0N"; //static const uint16_t uuid16_list[] = {GattService::UUID_STREAMING_SERVICE}; BLE ble; static LIS3DH lis(MOSI, MISO, CS, SCLK); #define LED_0 p20 #define LED_1 p23 //#define LED_2 p24 DigitalOut myled1(LED_0); DigitalOut myled2(LED_1); //DigitalOut myled3(LED_2); //#define UART_TX p17 //#define UART_RX p18 //Serial pc(UART_TX, UART_RX); // tx, rx /** @brief Function for initializing the GPIO Tasks/Events peripheral. */ static void gpiote_init(void) { // Configure accelerometer interrupt pin nrf_gpio_cfg_input(3, NRF_GPIO_PIN_PULLDOWN); //nrf_gpio_cfg_input(4, NRF_GPIO_PIN_PULLDOWN); // Configure GPIOTE channel 0 to generate event when MOTION_INTERRUPT_PIN_NUMBER goes from Low to High nrf_gpiote_event_config(0, 3, NRF_GPIOTE_POLARITY_LOTOHI); //accelerometer int1 //nrf_gpiote_event_config(1, 4, NRF_GPIOTE_POLARITY_LOTOHI); //accelerometer int2 // Enable interrupt for NRF_GPIOTE->EVENTS_IN[0] event NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN0_Msk; //NRF_GPIOTE->INTENSET |= GPIOTE_INTENSET_IN1_Msk; } extern "C" void GPIOTE_IRQHandler(void) { // Event causing the interrupt must be cleared NRF_GPIOTE->EVENTS_IN[0] = 0; //NRF_GPIOTE->EVENTS_IN[1] = 0; lis.LIS3DH_ResetInt1Latch(); myled1 = !myled1; myled2 = !myled2; } void disconnect_input_buffers() { for(uint8_t i = 0; i < 3; i++) { NRF_GPIO->PIN_CNF[i] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos); } //Omit accelerometer interrupt pins (3&4) for(uint8_t i = 5; i < 21; i++) { NRF_GPIO->PIN_CNF[i] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos); } //Omit I2C pins (21 & 22) for(uint8_t i = 23; i < 31; i++) { NRF_GPIO->PIN_CNF[i] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos); } } __packed struct ApplicationData_t { uint16_t applicationSpecificId; /* An ID used to identify temperature value in the manufacture specific AD data field */ //TMP_nrf51::tmpSensorValue_t tmpSensorValue; /* User defined application data */ int8_t accel_temp; //uint16_t lis; AxesRaw_t accel_raw; }; void setupApplicationData(ApplicationData_t &appData) { static const uint16_t APP_SPECIFIC_ID_TEST = 0xFEFE; appData.applicationSpecificId = APP_SPECIFIC_ID_TEST; //appData.tmpSensorValue = tempSensor.get(); lis.LIS3DH_GetAccAxesRaw(&appData.accel_raw); lis.LIS3DH_GetTempRaw(&appData.accel_temp); //uint8_t asdf; //lis.LIS3DH_GetWHO_AM_I(&asdf); //uint8_t val = 100; //appData.lis = (asdf << 8) | val; //appData.lis = lis.whoami(); } void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) { ble.gap().startAdvertising(); } void senseCallback(void) { ApplicationData_t appData; setupApplicationData(appData); ble.gap().updateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, (uint8_t *)&appData, sizeof(ApplicationData_t)); } int main() { //LEDS off myled1 = 0; myled2 = 0; //myled3 = 0; //Without this setup CS lines of AT45 & LIS3DH are in conflict, causing huge current consumption //i.e. both are connected to same SPI interface at the same time #if defined(TARGET_NRF51822_NODE_V3_OTA) || defined(TARGET_NRF51822_NODE_V3) || defined(TARGET_NRF51822_NODE_V3_BOOT) DigitalOut LIS_CS_0(CS); LIS_CS_0 = 1; //not selected DigitalOut AT_CS(p5); DigitalOut AT_RS(p6); AT_CS = 1; //not selected AT_RS = 0; //asserted == reset state wait_ms(100); AT_RS = 1; #endif //Initialize SPI interface SPI spi(MOSI, MISO, SCLK); // mosi, miso, sclk spi.format(8,3); spi.frequency(8000000); //setup AT45 dataflash to powersaving mode AT45* flash = new AT45(spi, p5); flash->ultra_deep_power_down(true); //Accelerometer interrupt pin configuration gpiote_init(); //Disconnect input buffers to save power //disabled for testing //disconnect_input_buffers(); //Initialize LIS3DH driver lis.InitLIS3DH(LIS3DH_NORMAL, LIS3DH_ODR_100Hz, LIS3DH_FULLSCALE_2); //Init Acc-sensor //lis.LIS3DH_SetTemperature(MEMS_ENABLE); //lis.LIS3DH_SetADCAux(MEMS_ENABLE); //lis.LIS3DH_SetBDU(MEMS_ENABLE); //enable threshold to generate interrupt lis.SetLIS3DHActivityDetection(3, LIS3DH_INT_MODE_6D_POSITION, 1); //disable... //lis.SetLIS3DHActivityDetection(20, LIS3DH_INT_MODE_OR, 0); // Enable GPIOTE interrupt in Nested Vector Interrupt Controller. NVIC_ClearPendingIRQ(GPIOTE_IRQn); NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_PORT_Set << GPIOTE_INTENSET_PORT_Pos; NVIC_SetPriority(GPIOTE_IRQn, 1); NVIC_EnableIRQ(GPIOTE_IRQn); //sd_nvic_EnableIRQ(GPIOTE_IRQn); //osDelay(osWaitForever); //Was Getting 13.2uA with these settings (flash deep power down). //With ultra deep power down 7.8uA... rose back to ~11uA??? Seems to fluctuate. Now getting 9.4... IO issue? //Now getting 5.4uA //device current //3.8uA idle (SYSTEM-ON base current with 32 kB RAM enabled.). Executing code from flash memory 4.1uA. From ram 2.4uA //32.768 kHz crystal oscillator 0.4uA / 32.768 kHz RC oscillator (32k RCOSC) 1.1uA (kumpi on?) //RTC Timer (LFCLK source) 0.1uA //==3.8 + (0.4) + 0.1uA + 5*0.1 (digitalout active) = 4.8uA //(watchdog) 0.1uA //GPIO as input = 22uA (Run current with 1 or more GPIOTE active channels in Input mode.) //as output 0.1A (Run current with 1 or more GPIOTE active channels in Output mode) //Peripherals current //BMP 180 0.1uA standby, 5uA standard mode, 7uA high resolution mode //LIS3DH 0.5uA standby mode, varies a lot in measurement mode //Si7021 0.06uA standby mode, 150uA active //AT45 Ultra deep power down 0,4uA, deep power down 5uA. Standby 25uA. 11mA active //== 0.1uA + 0.5uA + 0.06uA + 0.4uA = 1.06uA //total should be ~5.86 (or 5.46 depending on whether oscillator is included in system idle current) //Initialize BLE stuff ble.init(); ble.gap().onDisconnection(disconnectionCallback); #ifdef USE_DFU DFUService dfu(ble); #endif /* Setup advertising. */ ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_THERMOMETER); ApplicationData_t appData; setupApplicationData(appData); //ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); //ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, (uint8_t *)&appData, sizeof(ApplicationData_t)); ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); //ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED); ble.gap().setAdvertisingInterval(100); /* 1000ms. */ ble.gap().startAdvertising(); Ticker ticker; ticker.attach(senseCallback, 0.1); ///Could have main loop here doing something while(true) { ble.waitForEvent(); } }