Rotate the Cube Puck to invoke actions on your smartphone. Built on the Puck IOT platform.

Dependencies:   Puck MPU6050 mbed

The Cube Puck is an innovative bluetooth-enabled remote control device. It is a six-sided cube that can be rotated to any of its sides to invoke actions linked to that side. The cube puck is completely customizable and therefore also quite versatile.

A tutorial for the Cube Puck is available on GitHub.

Tutorials and in-depth documentation for the Puck platform is available at the project's GitHub page

Committer:
aleksanb
Date:
Wed Jul 09 15:02:59 2014 +0000
Revision:
2:b9b42ff80e9a
Parent:
0:449ee9595cf6
Child:
3:6a7310ea51f7
Update cube direction and Gatt in ticker handler. Enable Gatt notifications for subscribers.; ; This resolves issue where IMU suddenly would die on itself due too high; query frequency.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
aleksanb 0:449ee9595cf6 1 #include "mbed.h"
aleksanb 0:449ee9595cf6 2 #include "BLEDevice.h"
aleksanb 0:449ee9595cf6 3 #include "nRF51822n.h"
aleksanb 0:449ee9595cf6 4 #include "MPU6050.h"
aleksanb 2:b9b42ff80e9a 5 #include <math.h>
aleksanb 0:449ee9595cf6 6
aleksanb 0:449ee9595cf6 7 #define DEBUG 1
aleksanb 0:449ee9595cf6 8
aleksanb 0:449ee9595cf6 9 enum Direction {
aleksanb 0:449ee9595cf6 10 UP,
aleksanb 0:449ee9595cf6 11 DOWN,
aleksanb 0:449ee9595cf6 12 LEFT,
aleksanb 0:449ee9595cf6 13 RIGHT,
aleksanb 0:449ee9595cf6 14 FRONT,
aleksanb 0:449ee9595cf6 15 BACK,
aleksanb 0:449ee9595cf6 16 UNDEFINED
aleksanb 0:449ee9595cf6 17 };
aleksanb 0:449ee9595cf6 18
aleksanb 0:449ee9595cf6 19 Serial pc(USBTX, USBRX);
aleksanb 0:449ee9595cf6 20
aleksanb 0:449ee9595cf6 21 BLEDevice ble;
aleksanb 0:449ee9595cf6 22
aleksanb 0:449ee9595cf6 23 const static int16_t ACCELERATION_EXITATION_THRESHOLD = 15000;
aleksanb 0:449ee9595cf6 24 const static uint8_t beaconPayload[] = {
aleksanb 0:449ee9595cf6 25 0x00, 0x4C, // Company identifier code (0x004C == Apple)
aleksanb 0:449ee9595cf6 26 0x02, // ID
aleksanb 0:449ee9595cf6 27 0x15, // length of the remaining payload
aleksanb 0:449ee9595cf6 28 0xE2, 0x0A, 0x39, 0xF4, 0x73, 0xF5, 0x4B, 0xC4, // UUID
aleksanb 0:449ee9595cf6 29 0xA1, 0x2F, 0x17, 0xD1, 0xAD, 0x07, 0xA9, 0x61,
aleksanb 0:449ee9595cf6 30 0x13, 0x37, // the major value to differenciate a location
aleksanb 2:b9b42ff80e9a 31 0xC0, 0xBE, // the minor value to differenciate a location
aleksanb 0:449ee9595cf6 32 0xC8 // 2's complement of the Tx power (-56dB)
aleksanb 0:449ee9595cf6 33 };
aleksanb 0:449ee9595cf6 34
aleksanb 0:449ee9595cf6 35 extern GattService cube_service;
aleksanb 0:449ee9595cf6 36 extern GattCharacteristic directionCharacteristic;
aleksanb 0:449ee9595cf6 37 extern uint8_t direction_data[1];
aleksanb 0:449ee9595cf6 38
aleksanb 0:449ee9595cf6 39 MPU6050 mpu;
aleksanb 0:449ee9595cf6 40
aleksanb 0:449ee9595cf6 41 int16_t ax, ay, az;
aleksanb 0:449ee9595cf6 42 int16_t gx, gy, gz;
aleksanb 0:449ee9595cf6 43
aleksanb 0:449ee9595cf6 44 Direction direction = UNDEFINED;
aleksanb 0:449ee9595cf6 45
aleksanb 0:449ee9595cf6 46 void log_direction(void)
aleksanb 0:449ee9595cf6 47 {
aleksanb 2:b9b42ff80e9a 48 switch(direction) {
aleksanb 0:449ee9595cf6 49 case UP:
aleksanb 0:449ee9595cf6 50 pc.printf("Direction UP\n");
aleksanb 0:449ee9595cf6 51 break;
aleksanb 2:b9b42ff80e9a 52
aleksanb 0:449ee9595cf6 53 case DOWN:
aleksanb 0:449ee9595cf6 54 pc.printf("Direction DOWN\n");
aleksanb 0:449ee9595cf6 55 break;
aleksanb 2:b9b42ff80e9a 56
aleksanb 0:449ee9595cf6 57 case LEFT:
aleksanb 0:449ee9595cf6 58 pc.printf("Direction LEFT\n");
aleksanb 0:449ee9595cf6 59 break;
aleksanb 2:b9b42ff80e9a 60
aleksanb 0:449ee9595cf6 61 case RIGHT:
aleksanb 0:449ee9595cf6 62 pc.printf("Direction RIGHT\n");
aleksanb 0:449ee9595cf6 63 break;
aleksanb 2:b9b42ff80e9a 64
aleksanb 0:449ee9595cf6 65 case BACK:
aleksanb 0:449ee9595cf6 66 pc.printf("Direction BACK\n");
aleksanb 0:449ee9595cf6 67 break;
aleksanb 2:b9b42ff80e9a 68
aleksanb 0:449ee9595cf6 69 case FRONT:
aleksanb 0:449ee9595cf6 70 pc.printf("Direction FRONT\n");
aleksanb 0:449ee9595cf6 71 break;
aleksanb 2:b9b42ff80e9a 72
aleksanb 0:449ee9595cf6 73 default:
aleksanb 0:449ee9595cf6 74 pc.printf("Direction UNSET\n");
aleksanb 0:449ee9595cf6 75 break;
aleksanb 0:449ee9595cf6 76 }
aleksanb 0:449ee9595cf6 77 }
aleksanb 0:449ee9595cf6 78
aleksanb 2:b9b42ff80e9a 79 int16_t direction_if_exited(int16_t acceleration)
aleksanb 2:b9b42ff80e9a 80 {
aleksanb 0:449ee9595cf6 81 if (acceleration > ACCELERATION_EXITATION_THRESHOLD) {
aleksanb 0:449ee9595cf6 82 return 1;
aleksanb 0:449ee9595cf6 83 } else if (acceleration < -ACCELERATION_EXITATION_THRESHOLD) {
aleksanb 0:449ee9595cf6 84 return -1;
aleksanb 0:449ee9595cf6 85 } else {
aleksanb 0:449ee9595cf6 86 return 0;
aleksanb 0:449ee9595cf6 87 }
aleksanb 0:449ee9595cf6 88 }
aleksanb 0:449ee9595cf6 89
aleksanb 2:b9b42ff80e9a 90 void update_direction_characteristic(void)
aleksanb 2:b9b42ff80e9a 91 {
aleksanb 2:b9b42ff80e9a 92 direction_data[0] = direction;
aleksanb 2:b9b42ff80e9a 93 ble.updateCharacteristicValue(directionCharacteristic.getHandle(),
aleksanb 2:b9b42ff80e9a 94 direction_data,
aleksanb 2:b9b42ff80e9a 95 sizeof(direction_data));
aleksanb 2:b9b42ff80e9a 96 #if DEBUG
aleksanb 2:b9b42ff80e9a 97 //pc.printf("Updated gatt characteristic\n");
aleksanb 2:b9b42ff80e9a 98 #endif
aleksanb 2:b9b42ff80e9a 99 }
aleksanb 2:b9b42ff80e9a 100
aleksanb 0:449ee9595cf6 101 void update_cube_direction(void)
aleksanb 0:449ee9595cf6 102 {
aleksanb 0:449ee9595cf6 103 mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
aleksanb 2:b9b42ff80e9a 104
aleksanb 0:449ee9595cf6 105 int16_t x = direction_if_exited(ax);
aleksanb 0:449ee9595cf6 106 int16_t y = direction_if_exited(ay);
aleksanb 0:449ee9595cf6 107 int16_t z = direction_if_exited(az);
aleksanb 2:b9b42ff80e9a 108
aleksanb 0:449ee9595cf6 109 int16_t sum = abs(x) + abs(y) + abs(z);
aleksanb 2:b9b42ff80e9a 110 if (sum != 1) {
aleksanb 0:449ee9595cf6 111 return;
aleksanb 0:449ee9595cf6 112 }
aleksanb 2:b9b42ff80e9a 113
aleksanb 2:b9b42ff80e9a 114 Direction new_direction;
aleksanb 0:449ee9595cf6 115 if (z == 1) {
aleksanb 2:b9b42ff80e9a 116 new_direction = UP;
aleksanb 0:449ee9595cf6 117 } else if (z == -1) {
aleksanb 2:b9b42ff80e9a 118 new_direction = DOWN;
aleksanb 0:449ee9595cf6 119 } else if (y == 1) {
aleksanb 2:b9b42ff80e9a 120 new_direction = LEFT;
aleksanb 0:449ee9595cf6 121 } else if (y == -1) {
aleksanb 2:b9b42ff80e9a 122 new_direction = RIGHT;
aleksanb 0:449ee9595cf6 123 } else if (x == 1) {
aleksanb 2:b9b42ff80e9a 124 new_direction = BACK;
aleksanb 0:449ee9595cf6 125 } else if (x == -1) {
aleksanb 2:b9b42ff80e9a 126 new_direction = FRONT;
aleksanb 0:449ee9595cf6 127 }
aleksanb 2:b9b42ff80e9a 128
aleksanb 2:b9b42ff80e9a 129 if (direction == new_direction) {
aleksanb 2:b9b42ff80e9a 130 return;
aleksanb 2:b9b42ff80e9a 131 }
aleksanb 2:b9b42ff80e9a 132
aleksanb 2:b9b42ff80e9a 133 direction = new_direction;
aleksanb 2:b9b42ff80e9a 134
aleksanb 0:449ee9595cf6 135 #if DEBUG
aleksanb 0:449ee9595cf6 136 log_direction();
aleksanb 0:449ee9595cf6 137 #endif
aleksanb 2:b9b42ff80e9a 138 update_direction_characteristic();
aleksanb 0:449ee9595cf6 139 }
aleksanb 0:449ee9595cf6 140
aleksanb 0:449ee9595cf6 141 void disconnectionCallback(void)
aleksanb 0:449ee9595cf6 142 {
aleksanb 0:449ee9595cf6 143 pc.printf("Disconnected!\n");
aleksanb 0:449ee9595cf6 144 pc.printf("Restarting the advertising process\n");
aleksanb 0:449ee9595cf6 145 ble.startAdvertising();
aleksanb 0:449ee9595cf6 146 }
aleksanb 0:449ee9595cf6 147
aleksanb 2:b9b42ff80e9a 148 void periodicCallback(void)
aleksanb 2:b9b42ff80e9a 149 {
aleksanb 2:b9b42ff80e9a 150 update_cube_direction();
aleksanb 2:b9b42ff80e9a 151 }
aleksanb 2:b9b42ff80e9a 152
aleksanb 0:449ee9595cf6 153 void setup_ble(void)
aleksanb 0:449ee9595cf6 154 {
aleksanb 0:449ee9595cf6 155 ble.init();
aleksanb 0:449ee9595cf6 156 ble.onDisconnection(disconnectionCallback);
aleksanb 0:449ee9595cf6 157
aleksanb 0:449ee9595cf6 158 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
aleksanb 0:449ee9595cf6 159 ble.accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA,
aleksanb 2:b9b42ff80e9a 160 beaconPayload, sizeof(beaconPayload));
aleksanb 2:b9b42ff80e9a 161
aleksanb 0:449ee9595cf6 162 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
aleksanb 0:449ee9595cf6 163 ble.setAdvertisingInterval(160);
aleksanb 0:449ee9595cf6 164
aleksanb 0:449ee9595cf6 165 ble.startAdvertising();
aleksanb 2:b9b42ff80e9a 166
aleksanb 0:449ee9595cf6 167 ble.addService(cube_service);
aleksanb 2:b9b42ff80e9a 168
aleksanb 0:449ee9595cf6 169 pc.printf("BLE set up and running\n");
aleksanb 0:449ee9595cf6 170 }
aleksanb 0:449ee9595cf6 171
aleksanb 0:449ee9595cf6 172 int main()
aleksanb 0:449ee9595cf6 173 {
aleksanb 0:449ee9595cf6 174 setup_ble();
aleksanb 2:b9b42ff80e9a 175
aleksanb 2:b9b42ff80e9a 176 Ticker ticker;
aleksanb 2:b9b42ff80e9a 177 ticker.attach(periodicCallback, 1);
aleksanb 2:b9b42ff80e9a 178
aleksanb 0:449ee9595cf6 179 pc.printf("MPU6050 test startup:\n");
aleksanb 0:449ee9595cf6 180
aleksanb 0:449ee9595cf6 181 mpu.initialize();
aleksanb 0:449ee9595cf6 182 pc.printf("TestConnection\n");
aleksanb 2:b9b42ff80e9a 183
aleksanb 2:b9b42ff80e9a 184 if (mpu.testConnection()) {
aleksanb 0:449ee9595cf6 185 pc.printf("MPU success\n");
aleksanb 2:b9b42ff80e9a 186 } else {
aleksanb 0:449ee9595cf6 187 pc.printf("MPU error\n");
aleksanb 0:449ee9595cf6 188 }
aleksanb 0:449ee9595cf6 189
aleksanb 2:b9b42ff80e9a 190 while(1) {
aleksanb 0:449ee9595cf6 191 ble.waitForEvent();
aleksanb 0:449ee9595cf6 192 }
aleksanb 0:449ee9595cf6 193 }