tinyble get started
Dependencies: BLE_API eMPL_MPU6050 mbed nRF51822
Revision 0:c566f0efb062, committed 2017-09-08
- Comitter:
- IoTer
- Date:
- Fri Sep 08 12:02:42 2017 +0000
- Commit message:
- tiny ble get started
Changed in this revision
diff -r 000000000000 -r c566f0efb062 BLE_API.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BLE_API.lib Fri Sep 08 12:02:42 2017 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#65474dc93927
diff -r 000000000000 -r c566f0efb062 battery.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/battery.h Fri Sep 08 12:02:42 2017 +0000 @@ -0,0 +1,43 @@ + + +#ifndef __BATTERY_H__ +#define __BATTERY_H__ + +#include "mbed.h" + +class Battery { +public: + Battery(PinName pin) { + uint32_t n = (uint32_t) pin; + channel = 1 << (1 + n); + } + + float read() { + uint32_t pre_enable_register = NRF_ADC->ENABLE; + uint32_t pre_config_register = NRF_ADC->CONFIG; + + + NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Enabled; + NRF_ADC->CONFIG = (ADC_CONFIG_RES_10bit << ADC_CONFIG_RES_Pos) | + (ADC_CONFIG_INPSEL_AnalogInputNoPrescaling << ADC_CONFIG_INPSEL_Pos) | + (ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) | + (channel << ADC_CONFIG_PSEL_Pos) | + (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos); + + NRF_ADC->TASKS_START = 1; + while (((NRF_ADC->BUSY & ADC_BUSY_BUSY_Msk) >> ADC_BUSY_BUSY_Pos) == ADC_BUSY_BUSY_Busy) { + } + + uint16_t value = NRF_ADC->RESULT; + + NRF_ADC->ENABLE = pre_enable_register; + NRF_ADC->CONFIG = pre_config_register; + + return (float)value * (1.0f / (float)0x3FF) * 1.2 * 12.2 / 2.2; + } + +private: + uint32_t channel; +}; + +#endif // __BATTERY_H__
diff -r 000000000000 -r c566f0efb062 eMPL_MPU6050.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/eMPL_MPU6050.lib Fri Sep 08 12:02:42 2017 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/teams/Seeed/code/eMPL_MPU6050/#6aedb937cb38
diff -r 000000000000 -r c566f0efb062 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Fri Sep 08 12:02:42 2017 +0000 @@ -0,0 +1,298 @@ + +#include "mbed.h" +#include "mbed_i2c.h" +#include "inv_mpu.h" +#include "inv_mpu_dmp_motion_driver.h" +#include "nrf51.h" +#include "nrf51_bitfields.h" + +#include "BLE.h" +#include "DFUService.h" +#include "UARTService.h" + + +#define LOG(...) { pc.printf(__VA_ARGS__); } + +#define LED_GREEN p21 +#define LED_RED p22 +#define LED_BLUE p23 +#define BUTTON_PIN p17 +#define BATTERY_PIN p1 + +#define MPU6050_SDA p12 +#define MPU6050_SCL p13 + +#define UART_TX p9 +#define UART_RX p11 +#define UART_CTS p8 +#define UART_RTS p10 + +/* Starting sampling rate. */ +#define DEFAULT_MPU_HZ (100) + +DigitalOut blue(LED_BLUE); +DigitalOut green(LED_GREEN); +DigitalOut red(LED_RED); + +InterruptIn button(BUTTON_PIN); +AnalogIn battery(BATTERY_PIN); +Serial pc(UART_TX, UART_RX); + +InterruptIn motion_probe(p14); + +int read_none_count = 0; + +BLEDevice ble; +UARTService *uartServicePtr; + +volatile bool bleIsConnected = false; +volatile uint8_t tick_event = 0; +volatile uint8_t motion_event = 0; +static signed char board_orientation[9] = { + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 +}; + + +void check_i2c_bus(void); +unsigned short inv_orientation_matrix_to_scalar( const signed char *mtx); + + +void connectionCallback(const Gap::ConnectionCallbackParams_t *params) +{ + LOG("Connected!\n"); + bleIsConnected = true; +} + +void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *cbParams) +{ + LOG("Disconnected!\n"); + LOG("Restarting the advertising process\n"); + ble.startAdvertising(); + bleIsConnected = false; +} + +void tick(void) +{ + static uint32_t count = 0; + + LOG("%d\r\n", count++); + green = !green; +} + +void detect(void) +{ + LOG("Button pressed\n"); + blue = !blue; +} + +void motion_interrupt_handle(void) +{ + motion_event = 1; +} + +void tap_cb(unsigned char direction, unsigned char count) +{ + LOG("Tap motion detected\n"); +} + +void android_orient_cb(unsigned char orientation) +{ + LOG("Oriention changed\n"); +} + + +int main(void) +{ + blue = 1; + green = 1; + red = 1; + + pc.baud(115200); + + wait(1); + + LOG("---- Seeed Tiny BLE ----\n"); + + mbed_i2c_clear(MPU6050_SDA, MPU6050_SCL); + mbed_i2c_init(MPU6050_SDA, MPU6050_SCL); + + + if (mpu_init(0)) { + LOG("failed to initialize mpu6050\r\n"); + } + + /* Get/set hardware configuration. Start gyro. */ + /* Wake up all sensors. */ + mpu_set_sensors(INV_XYZ_GYRO | INV_XYZ_ACCEL); + /* Push both gyro and accel data into the FIFO. */ + mpu_configure_fifo(INV_XYZ_GYRO | INV_XYZ_ACCEL); + mpu_set_sample_rate(DEFAULT_MPU_HZ); + + /* Read back configuration in case it was set improperly. */ + unsigned char accel_fsr; + unsigned short gyro_rate, gyro_fsr; + mpu_get_sample_rate(&gyro_rate); + mpu_get_gyro_fsr(&gyro_fsr); + mpu_get_accel_fsr(&accel_fsr); + + dmp_load_motion_driver_firmware(); + dmp_set_orientation( + inv_orientation_matrix_to_scalar(board_orientation)); + dmp_register_tap_cb(tap_cb); + dmp_register_android_orient_cb(android_orient_cb); + + uint16_t dmp_features = DMP_FEATURE_6X_LP_QUAT | DMP_FEATURE_TAP | + DMP_FEATURE_ANDROID_ORIENT | DMP_FEATURE_SEND_RAW_ACCEL | DMP_FEATURE_SEND_CAL_GYRO | + DMP_FEATURE_GYRO_CAL; + dmp_enable_feature(dmp_features); + dmp_set_fifo_rate(DEFAULT_MPU_HZ); + mpu_set_dmp_state(1); + + dmp_set_interrupt_mode(DMP_INT_GESTURE); + dmp_set_tap_thresh(TAP_XYZ, 50); + + + motion_probe.fall(motion_interrupt_handle); + + + + Ticker ticker; + ticker.attach(tick, 3); + + button.fall(detect); + + LOG("Initialising the nRF51822\n"); + ble.init(); + ble.gap().onDisconnection(disconnectionCallback); + ble.gap().onConnection(connectionCallback); + + + /* setup advertising */ + ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED); + ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); + ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, + (const uint8_t *)"smurfs", sizeof("smurfs")); + ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, + (const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed)); + DFUService dfu(ble); + UARTService uartService(ble); + uartServicePtr = &uartService; + //uartService.retargetStdout(); + + ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */ + ble.gap().startAdvertising(); + + while (true) { + if (motion_event) { + + unsigned long sensor_timestamp; + short gyro[3], accel[3], sensors; + long quat[4]; + unsigned char more = 1; + + while (more) { + /* This function gets new data from the FIFO when the DMP is in + * use. The FIFO can contain any combination of gyro, accel, + * quaternion, and gesture data. The sensors parameter tells the + * caller which data fields were actually populated with new data. + * For example, if sensors == (INV_XYZ_GYRO | INV_WXYZ_QUAT), then + * the FIFO isn't being filled with accel data. + * The driver parses the gesture data to determine if a gesture + * event has occurred; on an event, the application will be notified + * via a callback (assuming that a callback function was properly + * registered). The more parameter is non-zero if there are + * leftover packets in the FIFO. + */ + dmp_read_fifo(gyro, accel, quat, &sensor_timestamp, &sensors, + &more); + + + /* Gyro and accel data are written to the FIFO by the DMP in chip + * frame and hardware units. This behavior is convenient because it + * keeps the gyro and accel outputs of dmp_read_fifo and + * mpu_read_fifo consistent. + */ + if (sensors & INV_XYZ_GYRO) { + // LOG("GYRO: %d, %d, %d\n", gyro[0], gyro[1], gyro[2]); + } + if (sensors & INV_XYZ_ACCEL) { + //LOG("ACC: %d, %d, %d\n", accel[0], accel[1], accel[2]); + } + + /* Unlike gyro and accel, quaternions are written to the FIFO in + * the body frame, q30. The orientation is set by the scalar passed + * to dmp_set_orientation during initialization. + */ + if (sensors & INV_WXYZ_QUAT) { + // LOG("QUAT: %ld, %ld, %ld, %ld\n", quat[0], quat[1], quat[2], quat[3]); + } + + if (sensors) { + read_none_count = 0; + } else { + read_none_count++; + if (read_none_count > 3) { + read_none_count = 0; + + LOG("I2C may be stuck @ %d\r\n", sensor_timestamp); + mbed_i2c_clear(MPU6050_SDA, MPU6050_SCL); + } + } + } + + motion_event = 0; + } else { + ble.waitForEvent(); + } + } +} + +/* These next two functions converts the orientation matrix (see + * gyro_orientation) to a scalar representation for use by the DMP. + * NOTE: These functions are borrowed from Invensense's MPL. + */ +static inline unsigned short inv_row_2_scale(const signed char *row) +{ + unsigned short b; + + if (row[0] > 0) + b = 0; + else if (row[0] < 0) + b = 4; + else if (row[1] > 0) + b = 1; + else if (row[1] < 0) + b = 5; + else if (row[2] > 0) + b = 2; + else if (row[2] < 0) + b = 6; + else + b = 7; // error + return b; +} + +unsigned short inv_orientation_matrix_to_scalar( + const signed char *mtx) +{ + unsigned short scalar; + + /* + XYZ 010_001_000 Identity Matrix + XZY 001_010_000 + YXZ 010_000_001 + YZX 000_010_001 + ZXY 001_000_010 + ZYX 000_001_010 + */ + + scalar = inv_row_2_scale(mtx); + scalar |= inv_row_2_scale(mtx + 3) << 3; + scalar |= inv_row_2_scale(mtx + 6) << 6; + + + return scalar; +} +
diff -r 000000000000 -r c566f0efb062 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Fri Sep 08 12:02:42 2017 +0000 @@ -0,0 +1,1 @@ +https://mbed.org/users/mbed_official/code/mbed/builds/a330f0fddbec \ No newline at end of file
diff -r 000000000000 -r c566f0efb062 nRF51822.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nRF51822.lib Fri Sep 08 12:02:42 2017 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/teams/Nordic-Semiconductor/code/nRF51822/#c90ae1400bf2
diff -r 000000000000 -r c566f0efb062 tiny_ble.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tiny_ble.h Fri Sep 08 12:02:42 2017 +0000 @@ -0,0 +1,19 @@ + +#ifndef __TINY_BLE_H__ +#define __TINY_BLE_H__ + +#define LED_GREEN p21 +#define LED_RED p22 +#define LED_BLUE p23 +#define BUTTON_PIN p17 +#define BATTERY_PIN p1 + +#define MPU6050_SDA p12 +#define MPU6050_SCL p13 + +#define UART_TX p9 +#define UART_RX p11 +#define UART_CTS p8 +#define UART_RTS p10 + +#endif // __TINY_BLE_H__