Deokgyu Yang | 2c7e86b | 2020-04-28 10:56:11 +0900 | [diff] [blame] | 1 | /* |
| 2 | * ladder.c: |
| 3 | * |
| 4 | * Gordon Henderson, June 2012 |
| 5 | *********************************************************************** |
| 6 | */ |
| 7 | |
| 8 | #include <stdio.h> |
| 9 | #include <stdlib.h> |
| 10 | #include <unistd.h> |
| 11 | #include <math.h> |
| 12 | |
| 13 | #include <wiringPi.h> |
| 14 | #include <piFace.h> |
| 15 | |
| 16 | #ifndef TRUE |
| 17 | # define TRUE (1==1) |
| 18 | # define FALSE (1==2) |
| 19 | #endif |
| 20 | |
| 21 | #undef DEBUG |
| 22 | |
| 23 | #define NUM_LEDS 8 |
| 24 | |
| 25 | |
| 26 | // Map the LEDs to the hardware pins |
| 27 | // using PiFace pin numbers here |
| 28 | |
| 29 | #define PIFACE 200 |
| 30 | |
| 31 | const int ledMap [NUM_LEDS] = |
| 32 | { |
| 33 | // 0, 1, 2, 3, 4, 5, 6, 7, 8 |
| 34 | 200, 201, 202, 203, 204, 205, 206, 207 |
| 35 | } ; |
| 36 | |
| 37 | |
| 38 | // Some constants for our circuit simulation |
| 39 | |
| 40 | const double vBatt = 9.0 ; // Volts (ie. a PP3) |
| 41 | const double capacitor = 0.001 ; // 1000uF |
| 42 | const double rCharge = 2200.0 ; // ohms |
| 43 | const double rDischarge = 68000.0 ; // ohms |
| 44 | const double timeInc = 0.01 ; // Seconds |
| 45 | |
| 46 | double vCharge, vCap, vCapLast ; |
| 47 | |
| 48 | |
| 49 | |
| 50 | /* |
| 51 | * setup: |
| 52 | * Program the GPIO correctly and initialise the lamps |
| 53 | *********************************************************************** |
| 54 | */ |
| 55 | |
| 56 | void setup (void) |
| 57 | { |
| 58 | int i ; |
| 59 | |
| 60 | wiringPiSetupSys () ; |
| 61 | |
| 62 | if (piFaceSetup (200) == -1) |
| 63 | exit (1) ; |
| 64 | |
| 65 | // Enable internal pull-ups |
| 66 | |
| 67 | for (i = 0 ; i < 8 ; ++i) |
| 68 | pullUpDnControl (PIFACE + i, PUD_UP) ; |
| 69 | |
| 70 | // Calculate the actual charging voltage - standard calculation of |
| 71 | // vCharge = r2 / (r1 + r2) * vBatt |
| 72 | // |
| 73 | // |
| 74 | // -----+--- vBatt |
| 75 | // | |
| 76 | // R1 |
| 77 | // | |
| 78 | // +---+---- vCharge |
| 79 | // | | |
| 80 | // R2 C |
| 81 | // | | |
| 82 | // -----+---+----- |
| 83 | |
| 84 | vCharge = rDischarge / (rCharge + rDischarge) * vBatt ; |
| 85 | |
| 86 | // Start with no charge |
| 87 | |
| 88 | vCap = vCapLast = 0.0 ; |
| 89 | } |
| 90 | |
| 91 | |
| 92 | /* |
| 93 | * introLeds |
| 94 | * Put a little pattern on the LEDs to start with |
| 95 | ********************************************************************************* |
| 96 | */ |
| 97 | |
| 98 | void introLeds (void) |
| 99 | { |
| 100 | int i, j ; |
| 101 | |
| 102 | |
| 103 | printf ("Pi Ladder\n") ; |
| 104 | printf ("=========\n\n") ; |
| 105 | printf (" vBatt: %6.2f volts\n", vBatt) ; |
| 106 | printf (" rCharge: %6.0f ohms\n", rCharge) ; |
| 107 | printf (" rDischarge: %6.0f ohms\n", rDischarge) ; |
| 108 | printf (" vCharge: %6.2f volts\n", vCharge) ; |
| 109 | printf (" capacitor: %6.0f uF\n", capacitor * 1000.0) ; |
| 110 | |
| 111 | // Flash 3 times: |
| 112 | |
| 113 | for (j = 0 ; j < 3 ; ++j) |
| 114 | { |
| 115 | for (i = 0 ; i < NUM_LEDS ; ++i) |
| 116 | digitalWrite (ledMap [i], 1) ; |
| 117 | delay (500) ; |
| 118 | for (i = 0 ; i < NUM_LEDS ; ++i) |
| 119 | digitalWrite (ledMap [i], 0) ; |
| 120 | delay (100) ; |
| 121 | } |
| 122 | |
| 123 | // All On |
| 124 | |
| 125 | for (i = 0 ; i < NUM_LEDS ; ++i) |
| 126 | digitalWrite (ledMap [i], 1) ; |
| 127 | delay (500) ; |
| 128 | |
| 129 | // Countdown... |
| 130 | |
| 131 | for (i = NUM_LEDS - 1 ; i >= 0 ; --i) |
| 132 | { |
| 133 | digitalWrite (ledMap [i], 0) ; |
| 134 | delay (100) ; |
| 135 | } |
| 136 | delay (500) ; |
| 137 | } |
| 138 | |
| 139 | |
| 140 | /* |
| 141 | * winningLeds |
| 142 | * Put a little pattern on the LEDs to start with |
| 143 | ********************************************************************************* |
| 144 | */ |
| 145 | |
| 146 | void winningLeds (void) |
| 147 | { |
| 148 | int i, j ; |
| 149 | |
| 150 | // Flash 3 times: |
| 151 | |
| 152 | for (j = 0 ; j < 3 ; ++j) |
| 153 | { |
| 154 | for (i = 0 ; i < NUM_LEDS ; ++i) |
| 155 | digitalWrite (ledMap [i], 1) ; |
| 156 | delay (500) ; |
| 157 | for (i = 0 ; i < NUM_LEDS ; ++i) |
| 158 | digitalWrite (ledMap [i], 0) ; |
| 159 | delay (100) ; |
| 160 | } |
| 161 | |
| 162 | // All On |
| 163 | |
| 164 | for (i = 0 ; i < NUM_LEDS ; ++i) |
| 165 | digitalWrite (ledMap [i], 1) ; |
| 166 | delay (500) ; |
| 167 | |
| 168 | // Countup... |
| 169 | |
| 170 | for (i = 0 ; i < NUM_LEDS ; ++i) |
| 171 | { |
| 172 | digitalWrite (ledMap [i], 0) ; |
| 173 | delay (100) ; |
| 174 | } |
| 175 | delay (500) ; |
| 176 | } |
| 177 | |
| 178 | |
| 179 | /* |
| 180 | * chargeCapacitor: dischargeCapacitor: |
| 181 | * Add or remove charge to the capacitor. |
| 182 | * Standard capacitor formulae. |
| 183 | ********************************************************************************* |
| 184 | */ |
| 185 | |
| 186 | void chargeCapacitor (void) |
| 187 | { |
| 188 | vCap = (vCapLast - vCharge) * |
| 189 | exp (- timeInc / (rCharge * capacitor)) + vCharge ; |
| 190 | |
| 191 | #ifdef DEBUG |
| 192 | printf ("+vCap: %7.4f\n", vCap) ; |
| 193 | #endif |
| 194 | |
| 195 | vCapLast = vCap ; |
| 196 | } |
| 197 | |
| 198 | void dischargeCapacitor (void) |
| 199 | { |
| 200 | vCap = vCapLast * |
| 201 | exp (- timeInc / (rDischarge * capacitor)) ; |
| 202 | |
| 203 | #ifdef DEBUG |
| 204 | printf ("-vCap: %7.4f\n", vCap) ; |
| 205 | #endif |
| 206 | |
| 207 | vCapLast = vCap ; |
| 208 | } |
| 209 | |
| 210 | |
| 211 | /* |
| 212 | * ledBargraph: |
| 213 | * Output the supplied number as a bargraph on the LEDs |
| 214 | ********************************************************************************* |
| 215 | */ |
| 216 | |
| 217 | void ledBargraph (double value, int topLedOn) |
| 218 | { |
| 219 | int topLed = (int)floor (value / vCharge * (double)NUM_LEDS) + 1 ; |
| 220 | int i ; |
| 221 | |
| 222 | if (topLed > NUM_LEDS) |
| 223 | topLed = NUM_LEDS ; |
| 224 | |
| 225 | if (!topLedOn) |
| 226 | --topLed ; |
| 227 | |
| 228 | for (i = 0 ; i < topLed ; ++i) |
| 229 | digitalWrite (ledMap [i], 1) ; |
| 230 | |
| 231 | for (i = topLed ; i < NUM_LEDS ; ++i) |
| 232 | digitalWrite (ledMap [i], 0) ; |
| 233 | } |
| 234 | |
| 235 | |
| 236 | /* |
| 237 | * ledOnAction: |
| 238 | * Make sure the leading LED is on and check the button |
| 239 | ********************************************************************************* |
| 240 | */ |
| 241 | |
| 242 | void ledOnAction (void) |
| 243 | { |
| 244 | if (digitalRead (PIFACE) == LOW) |
| 245 | { |
| 246 | chargeCapacitor () ; |
| 247 | ledBargraph (vCap, TRUE) ; |
| 248 | } |
| 249 | } |
| 250 | |
| 251 | |
| 252 | /* |
| 253 | * ledOffAction: |
| 254 | * Make sure the leading LED is off and check the button |
| 255 | ********************************************************************************* |
| 256 | */ |
| 257 | |
| 258 | void ledOffAction (void) |
| 259 | { |
| 260 | dischargeCapacitor () ; |
| 261 | |
| 262 | // Are we still pushing the button? |
| 263 | |
| 264 | if (digitalRead (PIFACE) == LOW) |
| 265 | { |
| 266 | vCap = vCapLast = 0.0 ; |
| 267 | ledBargraph (vCap, FALSE) ; |
| 268 | |
| 269 | // Wait until we release the button |
| 270 | |
| 271 | while (digitalRead (PIFACE) == LOW) |
| 272 | delay (10) ; |
| 273 | } |
| 274 | } |
| 275 | |
| 276 | |
| 277 | /* |
| 278 | *********************************************************************** |
| 279 | * The main program |
| 280 | *********************************************************************** |
| 281 | */ |
| 282 | |
| 283 | int main (void) |
| 284 | { |
| 285 | unsigned int then, ledOnTime, ledOffTime ; |
| 286 | unsigned int ourDelay = (int)(1000.0 * timeInc) ; |
| 287 | |
| 288 | setup () ; |
| 289 | introLeds () ; |
| 290 | |
| 291 | // Setup the LED times - TODO reduce the ON time as the game progresses |
| 292 | |
| 293 | ledOnTime = 1000 ; |
| 294 | ledOffTime = 1000 ; |
| 295 | |
| 296 | // This is our Gate/Squarewave loop |
| 297 | |
| 298 | for (;;) |
| 299 | { |
| 300 | |
| 301 | // LED ON: |
| 302 | |
| 303 | (void)ledBargraph (vCap, TRUE) ; |
| 304 | then = millis () + ledOnTime ; |
| 305 | while (millis () < then) |
| 306 | { |
| 307 | ledOnAction () ; |
| 308 | delay (ourDelay) ; |
| 309 | } |
| 310 | |
| 311 | // Have we won yet? |
| 312 | // We need vCap to be in the top NUM_LEDS of the vCharge |
| 313 | |
| 314 | if (vCap > ((double)(NUM_LEDS - 1) / (double)NUM_LEDS * vCharge)) // Woo hoo! |
| 315 | { |
| 316 | winningLeds () ; |
| 317 | while (digitalRead (PIFACE) == HIGH) |
| 318 | delay (10) ; |
| 319 | while (digitalRead (PIFACE) == LOW) |
| 320 | delay (10) ; |
| 321 | vCap = vCapLast = 0.0 ; |
| 322 | } |
| 323 | |
| 324 | // LED OFF: |
| 325 | |
| 326 | (void)ledBargraph (vCap, FALSE) ; |
| 327 | then = millis () + ledOffTime ; |
| 328 | while (millis () < then) |
| 329 | { |
| 330 | ledOffAction () ; |
| 331 | delay (ourDelay) ; |
| 332 | } |
| 333 | |
| 334 | } |
| 335 | |
| 336 | return 0 ; |
| 337 | } |