Demo code for Life Detector - attempting to share publically so someone else can tweak and reflash
main.cpp@0:d9a2b95dc9d8, 2016-06-01 (annotated)
- Committer:
- cefn
- Date:
- Wed Jun 01 17:44:46 2016 +0000
- Revision:
- 0:d9a2b95dc9d8
Attempting to publish a tree
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
cefn | 0:d9a2b95dc9d8 | 1 | #include "MicroBit.h" |
cefn | 0:d9a2b95dc9d8 | 2 | |
cefn | 0:d9a2b95dc9d8 | 3 | /* Raygun pin mapping - listed in Kitronik breakout order |
cefn | 0:d9a2b95dc9d8 | 4 | * 0 : MO Motor low-side-switch NPN pin |
cefn | 0:d9a2b95dc9d8 | 5 | * 5 : TS Trigger Switch (configured as ButtonA) |
cefn | 0:d9a2b95dc9d8 | 6 | * 1 : L1 Light 1 high-side-switch NPN Base |
cefn | 0:d9a2b95dc9d8 | 7 | * 8 : L2 Light 2 high-side-switch NPN Base |
cefn | 0:d9a2b95dc9d8 | 8 | * 11 : RS Red button switch (configured as ButtonB) |
cefn | 0:d9a2b95dc9d8 | 9 | * 12 : BL Blue LED |
cefn | 0:d9a2b95dc9d8 | 10 | * 2 : PZ Piezo speaker |
cefn | 0:d9a2b95dc9d8 | 11 | * 14 : TX 3.3V Serial Transmit Pin |
cefn | 0:d9a2b95dc9d8 | 12 | * 15 : TX 3.3V Serial Receive Pin |
cefn | 0:d9a2b95dc9d8 | 13 | * 16 : GS Green Switch (unpowered side) |
cefn | 0:d9a2b95dc9d8 | 14 | * 3V : 3.3V reference |
cefn | 0:d9a2b95dc9d8 | 15 | * 0V : Piezo ground, common ground wire from circuit board |
cefn | 0:d9a2b95dc9d8 | 16 | */ |
cefn | 0:d9a2b95dc9d8 | 17 | |
cefn | 0:d9a2b95dc9d8 | 18 | MicroBit uBit; |
cefn | 0:d9a2b95dc9d8 | 19 | |
cefn | 0:d9a2b95dc9d8 | 20 | MicroBitPin motor = uBit.io.P0; |
cefn | 0:d9a2b95dc9d8 | 21 | MicroBitPin speaker = uBit.io.P2; |
cefn | 0:d9a2b95dc9d8 | 22 | |
cefn | 0:d9a2b95dc9d8 | 23 | MicroBitPin frontLight = uBit.io.P1; |
cefn | 0:d9a2b95dc9d8 | 24 | MicroBitPin centerLight = uBit.io.P8; |
cefn | 0:d9a2b95dc9d8 | 25 | MicroBitPin backLight = uBit.io.P12; |
cefn | 0:d9a2b95dc9d8 | 26 | |
cefn | 0:d9a2b95dc9d8 | 27 | //somehow non-functional |
cefn | 0:d9a2b95dc9d8 | 28 | //MicroBitButton triggerButton = uBit.buttonA; |
cefn | 0:d9a2b95dc9d8 | 29 | //MicroBitButton topButton = uBit.buttonB; |
cefn | 0:d9a2b95dc9d8 | 30 | |
cefn | 0:d9a2b95dc9d8 | 31 | MicroBitPin powerSwitch = uBit.io.P16; |
cefn | 0:d9a2b95dc9d8 | 32 | |
cefn | 0:d9a2b95dc9d8 | 33 | char commandbytes[] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; |
cefn | 0:d9a2b95dc9d8 | 34 | char respondbytes[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; |
cefn | 0:d9a2b95dc9d8 | 35 | |
cefn | 0:d9a2b95dc9d8 | 36 | bool triggerSwitched = false; |
cefn | 0:d9a2b95dc9d8 | 37 | bool powerSwitched = false; |
cefn | 0:d9a2b95dc9d8 | 38 | bool topSwitched = false; |
cefn | 0:d9a2b95dc9d8 | 39 | bool lifeDetected = false; |
cefn | 0:d9a2b95dc9d8 | 40 | |
cefn | 0:d9a2b95dc9d8 | 41 | int gas = 0; |
cefn | 0:d9a2b95dc9d8 | 42 | int backgroundGas = 1600; |
cefn | 0:d9a2b95dc9d8 | 43 | int diffGas = 200; |
cefn | 0:d9a2b95dc9d8 | 44 | |
cefn | 0:d9a2b95dc9d8 | 45 | int pitch; |
cefn | 0:d9a2b95dc9d8 | 46 | unsigned long pitchedTime; |
cefn | 0:d9a2b95dc9d8 | 47 | |
cefn | 0:d9a2b95dc9d8 | 48 | int minPitch = 1000; |
cefn | 0:d9a2b95dc9d8 | 49 | int maxPitch = 2000; |
cefn | 0:d9a2b95dc9d8 | 50 | int pitchCycle = 500; |
cefn | 0:d9a2b95dc9d8 | 51 | |
cefn | 0:d9a2b95dc9d8 | 52 | bool isAlive(int gas){ |
cefn | 0:d9a2b95dc9d8 | 53 | return gas > backgroundGas + diffGas; |
cefn | 0:d9a2b95dc9d8 | 54 | } |
cefn | 0:d9a2b95dc9d8 | 55 | |
cefn | 0:d9a2b95dc9d8 | 56 | void showGas(){ |
cefn | 0:d9a2b95dc9d8 | 57 | if(gas == 0){ |
cefn | 0:d9a2b95dc9d8 | 58 | uBit.display.scrollAsync("?"); |
cefn | 0:d9a2b95dc9d8 | 59 | } |
cefn | 0:d9a2b95dc9d8 | 60 | else if(gas == 400){ |
cefn | 0:d9a2b95dc9d8 | 61 | uBit.display.scrollAsync("..."); |
cefn | 0:d9a2b95dc9d8 | 62 | } |
cefn | 0:d9a2b95dc9d8 | 63 | else if(isAlive(gas)){ |
cefn | 0:d9a2b95dc9d8 | 64 | uBit.display.scrollAsync("+++"); |
cefn | 0:d9a2b95dc9d8 | 65 | } |
cefn | 0:d9a2b95dc9d8 | 66 | else { |
cefn | 0:d9a2b95dc9d8 | 67 | uBit.display.scrollAsync(gas); |
cefn | 0:d9a2b95dc9d8 | 68 | } |
cefn | 0:d9a2b95dc9d8 | 69 | } |
cefn | 0:d9a2b95dc9d8 | 70 | |
cefn | 0:d9a2b95dc9d8 | 71 | void soundAlarm(){ |
cefn | 0:d9a2b95dc9d8 | 72 | speaker.setAnalogValue(512); |
cefn | 0:d9a2b95dc9d8 | 73 | } |
cefn | 0:d9a2b95dc9d8 | 74 | |
cefn | 0:d9a2b95dc9d8 | 75 | void silenceAlarm(){ |
cefn | 0:d9a2b95dc9d8 | 76 | speaker.setAnalogValue(0); |
cefn | 0:d9a2b95dc9d8 | 77 | } |
cefn | 0:d9a2b95dc9d8 | 78 | |
cefn | 0:d9a2b95dc9d8 | 79 | void setPitch(int futurePitch){ |
cefn | 0:d9a2b95dc9d8 | 80 | pitchedTime = uBit.systemTime(); |
cefn | 0:d9a2b95dc9d8 | 81 | pitch = futurePitch; |
cefn | 0:d9a2b95dc9d8 | 82 | speaker.setAnalogPeriodUs(1000000 / futurePitch); |
cefn | 0:d9a2b95dc9d8 | 83 | } |
cefn | 0:d9a2b95dc9d8 | 84 | |
cefn | 0:d9a2b95dc9d8 | 85 | void displayComplete(MicroBitEvent e){ |
cefn | 0:d9a2b95dc9d8 | 86 | showGas(); |
cefn | 0:d9a2b95dc9d8 | 87 | } |
cefn | 0:d9a2b95dc9d8 | 88 | |
cefn | 0:d9a2b95dc9d8 | 89 | int getSample(){ |
cefn | 0:d9a2b95dc9d8 | 90 | uBit.serial.send((uint8_t *)commandbytes, 9); |
cefn | 0:d9a2b95dc9d8 | 91 | |
cefn | 0:d9a2b95dc9d8 | 92 | uBit.serial.read((uint8_t *)respondbytes, 9); |
cefn | 0:d9a2b95dc9d8 | 93 | |
cefn | 0:d9a2b95dc9d8 | 94 | char header = respondbytes[1]; |
cefn | 0:d9a2b95dc9d8 | 95 | char highppm = respondbytes[2]; |
cefn | 0:d9a2b95dc9d8 | 96 | char lowppm = respondbytes[3]; |
cefn | 0:d9a2b95dc9d8 | 97 | |
cefn | 0:d9a2b95dc9d8 | 98 | if(header==0x86){ |
cefn | 0:d9a2b95dc9d8 | 99 | return ((int)highppm) * 256 + lowppm; |
cefn | 0:d9a2b95dc9d8 | 100 | } |
cefn | 0:d9a2b95dc9d8 | 101 | else{ |
cefn | 0:d9a2b95dc9d8 | 102 | return -1; |
cefn | 0:d9a2b95dc9d8 | 103 | } |
cefn | 0:d9a2b95dc9d8 | 104 | } |
cefn | 0:d9a2b95dc9d8 | 105 | |
cefn | 0:d9a2b95dc9d8 | 106 | void diagnostic(){ |
cefn | 0:d9a2b95dc9d8 | 107 | //Run diagnostic sequence |
cefn | 0:d9a2b95dc9d8 | 108 | uBit.display.printChar('M', 0); |
cefn | 0:d9a2b95dc9d8 | 109 | motor.setDigitalValue(true); |
cefn | 0:d9a2b95dc9d8 | 110 | uBit.sleep(1000); |
cefn | 0:d9a2b95dc9d8 | 111 | |
cefn | 0:d9a2b95dc9d8 | 112 | uBit.display.printChar('F', 0); |
cefn | 0:d9a2b95dc9d8 | 113 | frontLight.setDigitalValue(true); |
cefn | 0:d9a2b95dc9d8 | 114 | uBit.sleep(1000); |
cefn | 0:d9a2b95dc9d8 | 115 | frontLight.setDigitalValue(false); |
cefn | 0:d9a2b95dc9d8 | 116 | |
cefn | 0:d9a2b95dc9d8 | 117 | uBit.display.printChar('C', 0); |
cefn | 0:d9a2b95dc9d8 | 118 | centerLight.setDigitalValue(true); |
cefn | 0:d9a2b95dc9d8 | 119 | uBit.sleep(1000); |
cefn | 0:d9a2b95dc9d8 | 120 | centerLight.setDigitalValue(false); |
cefn | 0:d9a2b95dc9d8 | 121 | |
cefn | 0:d9a2b95dc9d8 | 122 | motor.setDigitalValue(false); |
cefn | 0:d9a2b95dc9d8 | 123 | |
cefn | 0:d9a2b95dc9d8 | 124 | uBit.display.printChar('B', 0); |
cefn | 0:d9a2b95dc9d8 | 125 | backLight.setDigitalValue(true); |
cefn | 0:d9a2b95dc9d8 | 126 | uBit.sleep(1000); |
cefn | 0:d9a2b95dc9d8 | 127 | backLight.setDigitalValue(false); |
cefn | 0:d9a2b95dc9d8 | 128 | |
cefn | 0:d9a2b95dc9d8 | 129 | speaker.setAnalogPeriod(1000.0/500.0); |
cefn | 0:d9a2b95dc9d8 | 130 | speaker.setAnalogValue(512); |
cefn | 0:d9a2b95dc9d8 | 131 | uBit.sleep(1000); |
cefn | 0:d9a2b95dc9d8 | 132 | speaker.setAnalogValue(0); |
cefn | 0:d9a2b95dc9d8 | 133 | } |
cefn | 0:d9a2b95dc9d8 | 134 | |
cefn | 0:d9a2b95dc9d8 | 135 | |
cefn | 0:d9a2b95dc9d8 | 136 | int main() |
cefn | 0:d9a2b95dc9d8 | 137 | { |
cefn | 0:d9a2b95dc9d8 | 138 | uBit.init(); |
cefn | 0:d9a2b95dc9d8 | 139 | uBit.serial.baud(9600); |
cefn | 0:d9a2b95dc9d8 | 140 | uBit.serial.redirect(MICROBIT_PIN_P14, MICROBIT_PIN_P15); |
cefn | 0:d9a2b95dc9d8 | 141 | |
cefn | 0:d9a2b95dc9d8 | 142 | //begin with all outputs off |
cefn | 0:d9a2b95dc9d8 | 143 | motor.setDigitalValue(false); |
cefn | 0:d9a2b95dc9d8 | 144 | frontLight.setDigitalValue(false); |
cefn | 0:d9a2b95dc9d8 | 145 | centerLight.setDigitalValue(false); |
cefn | 0:d9a2b95dc9d8 | 146 | backLight.setDigitalValue(false); |
cefn | 0:d9a2b95dc9d8 | 147 | |
cefn | 0:d9a2b95dc9d8 | 148 | //force the speaker to be analog |
cefn | 0:d9a2b95dc9d8 | 149 | speaker.setAnalogValue(0); |
cefn | 0:d9a2b95dc9d8 | 150 | |
cefn | 0:d9a2b95dc9d8 | 151 | //force switch to a pull-down implied by reading it |
cefn | 0:d9a2b95dc9d8 | 152 | powerSwitch.getDigitalValue(); |
cefn | 0:d9a2b95dc9d8 | 153 | |
cefn | 0:d9a2b95dc9d8 | 154 | while(powerSwitch.getDigitalValue()==false){ |
cefn | 0:d9a2b95dc9d8 | 155 | uBit.display.scrollAsync("After powering gun, reset micro:bit"); |
cefn | 0:d9a2b95dc9d8 | 156 | } |
cefn | 0:d9a2b95dc9d8 | 157 | |
cefn | 0:d9a2b95dc9d8 | 158 | |
cefn | 0:d9a2b95dc9d8 | 159 | //create implicit 'loop' showing gas, and trigger it |
cefn | 0:d9a2b95dc9d8 | 160 | uBit.messageBus.listen( MICROBIT_ID_DISPLAY, MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE, displayComplete); |
cefn | 0:d9a2b95dc9d8 | 161 | showGas(); |
cefn | 0:d9a2b95dc9d8 | 162 | |
cefn | 0:d9a2b95dc9d8 | 163 | while(1) |
cefn | 0:d9a2b95dc9d8 | 164 | { |
cefn | 0:d9a2b95dc9d8 | 165 | if(triggerSwitched != uBit.buttonA.isPressed()){ |
cefn | 0:d9a2b95dc9d8 | 166 | triggerSwitched = !triggerSwitched; |
cefn | 0:d9a2b95dc9d8 | 167 | } |
cefn | 0:d9a2b95dc9d8 | 168 | |
cefn | 0:d9a2b95dc9d8 | 169 | if(topSwitched != uBit.buttonB.isPressed()){ |
cefn | 0:d9a2b95dc9d8 | 170 | topSwitched = !topSwitched; |
cefn | 0:d9a2b95dc9d8 | 171 | |
cefn | 0:d9a2b95dc9d8 | 172 | if(topSwitched){ //calibration button pushed - acknowledge with new value |
cefn | 0:d9a2b95dc9d8 | 173 | backgroundGas = getSample(); |
cefn | 0:d9a2b95dc9d8 | 174 | ManagedString prefix("C:"); |
cefn | 0:d9a2b95dc9d8 | 175 | ManagedString suffix(backgroundGas); |
cefn | 0:d9a2b95dc9d8 | 176 | uBit.display.scroll(prefix+suffix); |
cefn | 0:d9a2b95dc9d8 | 177 | } |
cefn | 0:d9a2b95dc9d8 | 178 | |
cefn | 0:d9a2b95dc9d8 | 179 | } |
cefn | 0:d9a2b95dc9d8 | 180 | |
cefn | 0:d9a2b95dc9d8 | 181 | if(powerSwitched != powerSwitch.getDigitalValue()){ //note, totally different logic than buttons (and different pull) |
cefn | 0:d9a2b95dc9d8 | 182 | powerSwitched = powerSwitch.getDigitalValue(); |
cefn | 0:d9a2b95dc9d8 | 183 | } |
cefn | 0:d9a2b95dc9d8 | 184 | |
cefn | 0:d9a2b95dc9d8 | 185 | gas = getSample(); |
cefn | 0:d9a2b95dc9d8 | 186 | |
cefn | 0:d9a2b95dc9d8 | 187 | if(powerSwitched){ |
cefn | 0:d9a2b95dc9d8 | 188 | backLight.setDigitalValue(true); |
cefn | 0:d9a2b95dc9d8 | 189 | } |
cefn | 0:d9a2b95dc9d8 | 190 | else{ |
cefn | 0:d9a2b95dc9d8 | 191 | backLight.setDigitalValue(false); |
cefn | 0:d9a2b95dc9d8 | 192 | } |
cefn | 0:d9a2b95dc9d8 | 193 | |
cefn | 0:d9a2b95dc9d8 | 194 | if(lifeDetected != isAlive(gas)){ |
cefn | 0:d9a2b95dc9d8 | 195 | lifeDetected = !lifeDetected; |
cefn | 0:d9a2b95dc9d8 | 196 | setPitch(1000); |
cefn | 0:d9a2b95dc9d8 | 197 | } |
cefn | 0:d9a2b95dc9d8 | 198 | |
cefn | 0:d9a2b95dc9d8 | 199 | if(triggerSwitched){ |
cefn | 0:d9a2b95dc9d8 | 200 | motor.setDigitalValue(true); |
cefn | 0:d9a2b95dc9d8 | 201 | frontLight.setDigitalValue(true); |
cefn | 0:d9a2b95dc9d8 | 202 | if(lifeDetected){ |
cefn | 0:d9a2b95dc9d8 | 203 | centerLight.setDigitalValue(true); |
cefn | 0:d9a2b95dc9d8 | 204 | soundAlarm(); |
cefn | 0:d9a2b95dc9d8 | 205 | if(uBit.systemTime() - pitchedTime > 10){ |
cefn | 0:d9a2b95dc9d8 | 206 | if(pitch < maxPitch){ |
cefn | 0:d9a2b95dc9d8 | 207 | setPitch(pitch + (100 * (maxPitch - minPitch)/pitchCycle)); |
cefn | 0:d9a2b95dc9d8 | 208 | } |
cefn | 0:d9a2b95dc9d8 | 209 | else{ |
cefn | 0:d9a2b95dc9d8 | 210 | setPitch(minPitch); |
cefn | 0:d9a2b95dc9d8 | 211 | } |
cefn | 0:d9a2b95dc9d8 | 212 | } |
cefn | 0:d9a2b95dc9d8 | 213 | } |
cefn | 0:d9a2b95dc9d8 | 214 | } |
cefn | 0:d9a2b95dc9d8 | 215 | else{ |
cefn | 0:d9a2b95dc9d8 | 216 | motor.setDigitalValue(false); |
cefn | 0:d9a2b95dc9d8 | 217 | frontLight.setDigitalValue(false); |
cefn | 0:d9a2b95dc9d8 | 218 | centerLight.setDigitalValue(false); |
cefn | 0:d9a2b95dc9d8 | 219 | silenceAlarm(); |
cefn | 0:d9a2b95dc9d8 | 220 | } |
cefn | 0:d9a2b95dc9d8 | 221 | |
cefn | 0:d9a2b95dc9d8 | 222 | } |
cefn | 0:d9a2b95dc9d8 | 223 | } |