Using the MBED BLE library and Nordic Puck library this is a simple scoring application using Bluetooth LE. It monitors three analog inputs and triggers on reception of a pulse on any one recording data for a short period on all three. This is then published via BLE characteristics. It's a demonstrator for a new UI dev toolkit that is under development.
Fork of Example_Puck_BLE by
main.cpp@7:dc08df448ddc, 2014-08-23 (annotated)
- Committer:
- Bobty
- Date:
- Sat Aug 23 20:44:36 2014 +0000
- Revision:
- 7:dc08df448ddc
- Parent:
- 6:81494b318e55
- Child:
- 8:87a3708dca9c
Works now with Timeout instead of Ticker. But odd result is that when sample interval is 50ms get 30 puckDrive loops per sec but when reduced to 10ms get 117 loops - the two things should be independent!
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
aleksanb | 0:8d7583961274 | 1 | /** |
Bobty | 1:1a59b4810261 | 2 | Scoring Device - for generic game scoring |
Bobty | 1:1a59b4810261 | 3 | Using Puck BLE MBED library from Nordic |
Bobty | 1:1a59b4810261 | 4 | Copyright (C) Nodule.io 2014 |
Bobty | 1:1a59b4810261 | 5 | |
aleksanb | 0:8d7583961274 | 6 | */ |
aleksanb | 0:8d7583961274 | 7 | |
Bobty | 4:cc164ecf6a36 | 8 | #define LOG_LEVEL_DEBUG |
aleksanb | 0:8d7583961274 | 9 | #include "Puck.h" |
Bobty | 3:a155da1cbde3 | 10 | #include "SampleChannel.h" |
aleksanb | 0:8d7583961274 | 11 | |
aleksanb | 0:8d7583961274 | 12 | Puck* puck = &Puck::getPuck(); |
aleksanb | 0:8d7583961274 | 13 | |
Bobty | 1:1a59b4810261 | 14 | // Gatt characteristic and service UUIDs |
Bobty | 2:e400fd4f501b | 15 | const UUID SCORING_GATT_SERVICE = stringToUUID("nod.score1.serv "); |
Bobty | 2:e400fd4f501b | 16 | const UUID THRESHOLD_GATT_CHARACTERISTIC = stringToUUID("nod.score1.thres"); |
Bobty | 2:e400fd4f501b | 17 | const UUID DIVISOR_GATT_CHARACTERISTIC = stringToUUID("nod.score1.div "); |
Bobty | 2:e400fd4f501b | 18 | const UUID INTERVAL_US_GATT_CHARACTERISTIC = stringToUUID("nod.score1.intus"); |
Bobty | 1:1a59b4810261 | 19 | |
Bobty | 3:a155da1cbde3 | 20 | const int NUM_SAMPLE_CHANNELS = 1; |
Bobty | 2:e400fd4f501b | 21 | |
Bobty | 2:e400fd4f501b | 22 | // Sample interval (uS) |
Bobty | 7:dc08df448ddc | 23 | uint32_t sampleIntervalUs = 10000; |
Bobty | 1:1a59b4810261 | 24 | |
Bobty | 4:cc164ecf6a36 | 25 | // Interrupt driven ticker to do the sampling |
Bobty | 7:dc08df448ddc | 26 | Timeout sampleTimeout; |
Bobty | 4:cc164ecf6a36 | 27 | |
Bobty | 3:a155da1cbde3 | 28 | // Sample Channels |
Bobty | 3:a155da1cbde3 | 29 | SampleChannel sampleChannels[] = |
Bobty | 3:a155da1cbde3 | 30 | { |
Bobty | 3:a155da1cbde3 | 31 | SampleChannel(P0_1, stringToUUID("nod.score1.samp1"), &logger), |
Bobty | 3:a155da1cbde3 | 32 | SampleChannel(P0_2, stringToUUID("nod.score1.samp2"), &logger), |
Bobty | 3:a155da1cbde3 | 33 | SampleChannel(P0_3, stringToUUID("nod.score1.samp3"), &logger) |
Bobty | 3:a155da1cbde3 | 34 | }; |
aleksanb | 0:8d7583961274 | 35 | |
Bobty | 1:1a59b4810261 | 36 | // Timer to avoid repeat sampling |
Bobty | 3:a155da1cbde3 | 37 | Timer intervalTimer; |
Bobty | 3:a155da1cbde3 | 38 | int lastTriggerTime = 0; |
Bobty | 1:1a59b4810261 | 39 | int lastSampleTime = 0; |
Bobty | 1:1a59b4810261 | 40 | const int MIN_MS_BETWEEN_SAMPLES = 2000; |
Bobty | 1:1a59b4810261 | 41 | |
Bobty | 7:dc08df448ddc | 42 | // Function called in interrupt driven timeout to handle sampling |
Bobty | 4:cc164ecf6a36 | 43 | static volatile int serviceCount = 0; |
Bobty | 4:cc164ecf6a36 | 44 | void SampleService() |
Bobty | 4:cc164ecf6a36 | 45 | { |
Bobty | 4:cc164ecf6a36 | 46 | serviceCount++; |
Bobty | 4:cc164ecf6a36 | 47 | |
Bobty | 7:dc08df448ddc | 48 | sampleTimeout.attach_us(&SampleService, sampleIntervalUs); |
Bobty | 7:dc08df448ddc | 49 | |
Bobty | 4:cc164ecf6a36 | 50 | return; |
Bobty | 4:cc164ecf6a36 | 51 | |
Bobty | 4:cc164ecf6a36 | 52 | // service all channel's state machines |
Bobty | 4:cc164ecf6a36 | 53 | bool isAnyChannelSampling = false; |
Bobty | 4:cc164ecf6a36 | 54 | for (int chanIdx = 0; chanIdx < NUM_SAMPLE_CHANNELS; chanIdx++) |
Bobty | 4:cc164ecf6a36 | 55 | { |
Bobty | 4:cc164ecf6a36 | 56 | sampleChannels[chanIdx].Service(); |
Bobty | 4:cc164ecf6a36 | 57 | if (sampleChannels[chanIdx].IsSampling()) |
Bobty | 4:cc164ecf6a36 | 58 | isAnyChannelSampling = true; |
Bobty | 4:cc164ecf6a36 | 59 | } |
Bobty | 4:cc164ecf6a36 | 60 | |
Bobty | 4:cc164ecf6a36 | 61 | if (!isAnyChannelSampling) |
Bobty | 4:cc164ecf6a36 | 62 | { |
Bobty | 4:cc164ecf6a36 | 63 | int curTimerVal = intervalTimer.read_ms(); |
Bobty | 4:cc164ecf6a36 | 64 | if ((lastTriggerTime < curTimerVal) || (curTimerVal - lastTriggerTime > MIN_MS_BETWEEN_SAMPLES)) |
Bobty | 4:cc164ecf6a36 | 65 | { |
Bobty | 4:cc164ecf6a36 | 66 | |
Bobty | 4:cc164ecf6a36 | 67 | // check each channel to see if it's been triggered |
Bobty | 4:cc164ecf6a36 | 68 | bool anythingTriggered = false; |
Bobty | 4:cc164ecf6a36 | 69 | for (int chanIdx = 0; chanIdx < NUM_SAMPLE_CHANNELS; chanIdx++) |
Bobty | 4:cc164ecf6a36 | 70 | { |
Bobty | 4:cc164ecf6a36 | 71 | if (sampleChannels[chanIdx].CheckTrigger()) |
Bobty | 4:cc164ecf6a36 | 72 | { |
Bobty | 4:cc164ecf6a36 | 73 | anythingTriggered = true; |
Bobty | 4:cc164ecf6a36 | 74 | LOG_INFO("Triggered\n"); |
Bobty | 4:cc164ecf6a36 | 75 | break; |
Bobty | 4:cc164ecf6a36 | 76 | } |
Bobty | 4:cc164ecf6a36 | 77 | } |
Bobty | 4:cc164ecf6a36 | 78 | if(anythingTriggered) |
Bobty | 4:cc164ecf6a36 | 79 | { |
Bobty | 4:cc164ecf6a36 | 80 | for (int chanIdx = 0; chanIdx < NUM_SAMPLE_CHANNELS; chanIdx++) |
Bobty | 4:cc164ecf6a36 | 81 | { |
Bobty | 4:cc164ecf6a36 | 82 | sampleChannels[chanIdx].StartSampling(); |
Bobty | 4:cc164ecf6a36 | 83 | } |
Bobty | 4:cc164ecf6a36 | 84 | // Set timer to disallow repeated readings |
Bobty | 4:cc164ecf6a36 | 85 | lastTriggerTime = curTimerVal; |
Bobty | 4:cc164ecf6a36 | 86 | } |
Bobty | 4:cc164ecf6a36 | 87 | } |
Bobty | 4:cc164ecf6a36 | 88 | } |
Bobty | 4:cc164ecf6a36 | 89 | } |
Bobty | 4:cc164ecf6a36 | 90 | |
Bobty | 2:e400fd4f501b | 91 | void onThresholdSet(uint8_t* value) |
Bobty | 2:e400fd4f501b | 92 | { |
Bobty | 2:e400fd4f501b | 93 | uint16_t threshold = value[0] * 256 + value[1]; |
Bobty | 2:e400fd4f501b | 94 | LOG_INFO("Threshold=%d\n", threshold); |
Bobty | 3:a155da1cbde3 | 95 | for (int chanIdx = 0; chanIdx < NUM_SAMPLE_CHANNELS; chanIdx++) |
Bobty | 3:a155da1cbde3 | 96 | sampleChannels[chanIdx].SetThreshold(threshold); |
Bobty | 2:e400fd4f501b | 97 | } |
Bobty | 2:e400fd4f501b | 98 | |
Bobty | 2:e400fd4f501b | 99 | void onDivisorSet(uint8_t* value) |
Bobty | 2:e400fd4f501b | 100 | { |
Bobty | 2:e400fd4f501b | 101 | uint16_t divisor = value[0] * 256 + value[1]; |
Bobty | 2:e400fd4f501b | 102 | LOG_INFO("Divisor=%d\n", divisor); |
Bobty | 3:a155da1cbde3 | 103 | for (int chanIdx = 0; chanIdx < NUM_SAMPLE_CHANNELS; chanIdx++) |
Bobty | 3:a155da1cbde3 | 104 | sampleChannels[chanIdx].SetDivisor(divisor); |
Bobty | 2:e400fd4f501b | 105 | } |
Bobty | 2:e400fd4f501b | 106 | |
Bobty | 2:e400fd4f501b | 107 | void onIntervalSet(uint8_t* value) |
Bobty | 2:e400fd4f501b | 108 | { |
Bobty | 2:e400fd4f501b | 109 | uint32_t intervalUs = (value[0] << 24) + (value[1] << 16) + (value[2] << 8) + value[3]; |
Bobty | 2:e400fd4f501b | 110 | LOG_INFO("SampleInterval(uS)=%d\n", intervalUs); |
Bobty | 3:a155da1cbde3 | 111 | if (intervalUs <= 1000000) |
Bobty | 4:cc164ecf6a36 | 112 | { |
Bobty | 3:a155da1cbde3 | 113 | sampleIntervalUs = intervalUs; |
Bobty | 4:cc164ecf6a36 | 114 | // sampleTicker.detach(); |
Bobty | 4:cc164ecf6a36 | 115 | // sampleTicker.attach_us(&SampleService, sampleIntervalUs); |
Bobty | 4:cc164ecf6a36 | 116 | } |
Bobty | 2:e400fd4f501b | 117 | } |
Bobty | 2:e400fd4f501b | 118 | |
Bobty | 1:1a59b4810261 | 119 | int main(void) |
Bobty | 1:1a59b4810261 | 120 | { |
Bobty | 1:1a59b4810261 | 121 | |
Bobty | 1:1a59b4810261 | 122 | // Set baud rate |
Bobty | 1:1a59b4810261 | 123 | logger.baud(115200); |
Bobty | 1:1a59b4810261 | 124 | |
Bobty | 1:1a59b4810261 | 125 | // Add the Gatt characteristic for samples |
Bobty | 3:a155da1cbde3 | 126 | for (int chanIdx = 0; chanIdx < NUM_SAMPLE_CHANNELS; chanIdx++) |
Bobty | 3:a155da1cbde3 | 127 | { |
Bobty | 3:a155da1cbde3 | 128 | puck->addCharacteristic( |
Bobty | 1:1a59b4810261 | 129 | SCORING_GATT_SERVICE, |
Bobty | 3:a155da1cbde3 | 130 | sampleChannels[chanIdx].GetUUID(), |
Bobty | 3:a155da1cbde3 | 131 | sampleChannels[chanIdx].GetSamplesLen(), |
aleksanb | 0:8d7583961274 | 132 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY); |
Bobty | 3:a155da1cbde3 | 133 | } |
aleksanb | 0:8d7583961274 | 134 | |
Bobty | 2:e400fd4f501b | 135 | // Add the Gatt characteristic for threshold |
Bobty | 2:e400fd4f501b | 136 | puck->addCharacteristic( |
Bobty | 2:e400fd4f501b | 137 | SCORING_GATT_SERVICE, |
Bobty | 2:e400fd4f501b | 138 | THRESHOLD_GATT_CHARACTERISTIC, |
Bobty | 3:a155da1cbde3 | 139 | sizeof(uint16_t), |
Bobty | 2:e400fd4f501b | 140 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE); |
Bobty | 2:e400fd4f501b | 141 | puck->onCharacteristicWrite(&THRESHOLD_GATT_CHARACTERISTIC, onThresholdSet); |
Bobty | 2:e400fd4f501b | 142 | |
Bobty | 2:e400fd4f501b | 143 | // Add the Gatt characteristic for sample divisor |
Bobty | 2:e400fd4f501b | 144 | puck->addCharacteristic( |
Bobty | 2:e400fd4f501b | 145 | SCORING_GATT_SERVICE, |
Bobty | 2:e400fd4f501b | 146 | DIVISOR_GATT_CHARACTERISTIC, |
Bobty | 3:a155da1cbde3 | 147 | sizeof(uint16_t), |
Bobty | 2:e400fd4f501b | 148 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE); |
Bobty | 2:e400fd4f501b | 149 | puck->onCharacteristicWrite(&DIVISOR_GATT_CHARACTERISTIC, onDivisorSet); |
Bobty | 2:e400fd4f501b | 150 | |
Bobty | 2:e400fd4f501b | 151 | // Add the Gatt characteristic for sample interval (us) |
Bobty | 2:e400fd4f501b | 152 | puck->addCharacteristic( |
Bobty | 2:e400fd4f501b | 153 | SCORING_GATT_SERVICE, |
Bobty | 2:e400fd4f501b | 154 | INTERVAL_US_GATT_CHARACTERISTIC, |
Bobty | 2:e400fd4f501b | 155 | sizeof(sampleIntervalUs), |
Bobty | 2:e400fd4f501b | 156 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE); |
Bobty | 2:e400fd4f501b | 157 | puck->onCharacteristicWrite(&INTERVAL_US_GATT_CHARACTERISTIC, onIntervalSet); |
Bobty | 2:e400fd4f501b | 158 | |
aleksanb | 0:8d7583961274 | 159 | // Initialize the puck |
Bobty | 1:1a59b4810261 | 160 | puck->init(0xCD01); |
Bobty | 1:1a59b4810261 | 161 | |
Bobty | 1:1a59b4810261 | 162 | // Start timer |
Bobty | 3:a155da1cbde3 | 163 | intervalTimer.start(); |
Bobty | 4:cc164ecf6a36 | 164 | |
Bobty | 7:dc08df448ddc | 165 | // Start timeout to service the sampling |
Bobty | 7:dc08df448ddc | 166 | sampleTimeout.attach_us(&SampleService, sampleIntervalUs); |
aleksanb | 0:8d7583961274 | 167 | |
Bobty | 1:1a59b4810261 | 168 | // Wait for something to be found |
Bobty | 4:cc164ecf6a36 | 169 | unsigned int lastPuckDriveTime = 0; |
Bobty | 5:ed9a4f932fcf | 170 | unsigned int driveLoops = 0; |
Bobty | 7:dc08df448ddc | 171 | unsigned int lastDriveLoops = 0; |
Bobty | 7:dc08df448ddc | 172 | unsigned int lastServiceCount = 0; |
Bobty | 3:a155da1cbde3 | 173 | while(true) |
Bobty | 1:1a59b4810261 | 174 | { |
Bobty | 4:cc164ecf6a36 | 175 | // Service the puck |
Bobty | 5:ed9a4f932fcf | 176 | puck->drive(); |
Bobty | 5:ed9a4f932fcf | 177 | driveLoops++; |
Bobty | 5:ed9a4f932fcf | 178 | |
Bobty | 5:ed9a4f932fcf | 179 | // Handle 1 second updates |
Bobty | 7:dc08df448ddc | 180 | unsigned int nowTime = intervalTimer.read_ms(); |
Bobty | 7:dc08df448ddc | 181 | if ((nowTime - lastPuckDriveTime >= 1000) || (nowTime < lastPuckDriveTime)) |
Bobty | 4:cc164ecf6a36 | 182 | { |
Bobty | 7:dc08df448ddc | 183 | unsigned int elapsed = nowTime - lastPuckDriveTime; |
Bobty | 7:dc08df448ddc | 184 | LOG_INFO("%u E%u C%u DC%u TC%u DTC%u L%u DL%u\n", nowTime, elapsed, serviceCount, serviceCount-lastServiceCount, nowTime/serviceCount, elapsed/(serviceCount-lastServiceCount), driveLoops, driveLoops-lastDriveLoops); |
Bobty | 4:cc164ecf6a36 | 185 | lastPuckDriveTime = intervalTimer.read_ms(); |
Bobty | 7:dc08df448ddc | 186 | lastDriveLoops = driveLoops; |
Bobty | 7:dc08df448ddc | 187 | lastServiceCount = serviceCount; |
Bobty | 4:cc164ecf6a36 | 188 | } |
Bobty | 4:cc164ecf6a36 | 189 | |
Bobty | 4:cc164ecf6a36 | 190 | continue; |
Bobty | 4:cc164ecf6a36 | 191 | |
Bobty | 4:cc164ecf6a36 | 192 | // Check for data ready |
Bobty | 3:a155da1cbde3 | 193 | for (int chanIdx = 0; chanIdx < NUM_SAMPLE_CHANNELS; chanIdx++) |
Bobty | 1:1a59b4810261 | 194 | { |
Bobty | 3:a155da1cbde3 | 195 | if (sampleChannels[chanIdx].AreSamplesReady()) |
Bobty | 1:1a59b4810261 | 196 | { |
Bobty | 3:a155da1cbde3 | 197 | // Set the value of the characteristic |
Bobty | 4:cc164ecf6a36 | 198 | //puck->updateCharacteristicValue(sampleChannels[chanIdx].GetUUID(), sampleChannels[chanIdx].GetSamples(), sampleChannels[chanIdx].GetSamplesLen()); |
Bobty | 3:a155da1cbde3 | 199 | sampleChannels[chanIdx].StopSampling(); |
Bobty | 3:a155da1cbde3 | 200 | LOG_INFO("StopSampling\n"); |
Bobty | 3:a155da1cbde3 | 201 | } |
Bobty | 3:a155da1cbde3 | 202 | } |
Bobty | 1:1a59b4810261 | 203 | } |
Bobty | 1:1a59b4810261 | 204 | } |