/* * ladder.c: * * Gordon Henderson, June 2012 *********************************************************************** */ #include #include #include #include #include #include #ifndef TRUE # define TRUE (1==1) # define FALSE (1==2) #endif #undef DEBUG #define NUM_LEDS 8 // Map the LEDs to the hardware pins // using PiFace pin numbers here #define PIFACE 200 const int ledMap [NUM_LEDS] = { // 0, 1, 2, 3, 4, 5, 6, 7, 8 200, 201, 202, 203, 204, 205, 206, 207 } ; // Some constants for our circuit simulation const double vBatt = 9.0 ; // Volts (ie. a PP3) const double capacitor = 0.001 ; // 1000uF const double rCharge = 2200.0 ; // ohms const double rDischarge = 68000.0 ; // ohms const double timeInc = 0.01 ; // Seconds double vCharge, vCap, vCapLast ; /* * setup: * Program the GPIO correctly and initialise the lamps *********************************************************************** */ void setup (void) { int i ; wiringPiSetupSys () ; if (piFaceSetup (200) == -1) exit (1) ; // Enable internal pull-ups for (i = 0 ; i < 8 ; ++i) pullUpDnControl (PIFACE + i, PUD_UP) ; // Calculate the actual charging voltage - standard calculation of // vCharge = r2 / (r1 + r2) * vBatt // // // -----+--- vBatt // | // R1 // | // +---+---- vCharge // | | // R2 C // | | // -----+---+----- vCharge = rDischarge / (rCharge + rDischarge) * vBatt ; // Start with no charge vCap = vCapLast = 0.0 ; } /* * introLeds * Put a little pattern on the LEDs to start with ********************************************************************************* */ void introLeds (void) { int i, j ; printf ("Pi Ladder\n") ; printf ("=========\n\n") ; printf (" vBatt: %6.2f volts\n", vBatt) ; printf (" rCharge: %6.0f ohms\n", rCharge) ; printf (" rDischarge: %6.0f ohms\n", rDischarge) ; printf (" vCharge: %6.2f volts\n", vCharge) ; printf (" capacitor: %6.0f uF\n", capacitor * 1000.0) ; // Flash 3 times: for (j = 0 ; j < 3 ; ++j) { for (i = 0 ; i < NUM_LEDS ; ++i) digitalWrite (ledMap [i], 1) ; delay (500) ; for (i = 0 ; i < NUM_LEDS ; ++i) digitalWrite (ledMap [i], 0) ; delay (100) ; } // All On for (i = 0 ; i < NUM_LEDS ; ++i) digitalWrite (ledMap [i], 1) ; delay (500) ; // Countdown... for (i = NUM_LEDS - 1 ; i >= 0 ; --i) { digitalWrite (ledMap [i], 0) ; delay (100) ; } delay (500) ; } /* * winningLeds * Put a little pattern on the LEDs to start with ********************************************************************************* */ void winningLeds (void) { int i, j ; // Flash 3 times: for (j = 0 ; j < 3 ; ++j) { for (i = 0 ; i < NUM_LEDS ; ++i) digitalWrite (ledMap [i], 1) ; delay (500) ; for (i = 0 ; i < NUM_LEDS ; ++i) digitalWrite (ledMap [i], 0) ; delay (100) ; } // All On for (i = 0 ; i < NUM_LEDS ; ++i) digitalWrite (ledMap [i], 1) ; delay (500) ; // Countup... for (i = 0 ; i < NUM_LEDS ; ++i) { digitalWrite (ledMap [i], 0) ; delay (100) ; } delay (500) ; } /* * chargeCapacitor: dischargeCapacitor: * Add or remove charge to the capacitor. * Standard capacitor formulae. ********************************************************************************* */ void chargeCapacitor (void) { vCap = (vCapLast - vCharge) * exp (- timeInc / (rCharge * capacitor)) + vCharge ; #ifdef DEBUG printf ("+vCap: %7.4f\n", vCap) ; #endif vCapLast = vCap ; } void dischargeCapacitor (void) { vCap = vCapLast * exp (- timeInc / (rDischarge * capacitor)) ; #ifdef DEBUG printf ("-vCap: %7.4f\n", vCap) ; #endif vCapLast = vCap ; } /* * ledBargraph: * Output the supplied number as a bargraph on the LEDs ********************************************************************************* */ void ledBargraph (double value, int topLedOn) { int topLed = (int)floor (value / vCharge * (double)NUM_LEDS) + 1 ; int i ; if (topLed > NUM_LEDS) topLed = NUM_LEDS ; if (!topLedOn) --topLed ; for (i = 0 ; i < topLed ; ++i) digitalWrite (ledMap [i], 1) ; for (i = topLed ; i < NUM_LEDS ; ++i) digitalWrite (ledMap [i], 0) ; } /* * ledOnAction: * Make sure the leading LED is on and check the button ********************************************************************************* */ void ledOnAction (void) { if (digitalRead (PIFACE) == LOW) { chargeCapacitor () ; ledBargraph (vCap, TRUE) ; } } /* * ledOffAction: * Make sure the leading LED is off and check the button ********************************************************************************* */ void ledOffAction (void) { dischargeCapacitor () ; // Are we still pushing the button? if (digitalRead (PIFACE) == LOW) { vCap = vCapLast = 0.0 ; ledBargraph (vCap, FALSE) ; // Wait until we release the button while (digitalRead (PIFACE) == LOW) delay (10) ; } } /* *********************************************************************** * The main program *********************************************************************** */ int main (void) { unsigned int then, ledOnTime, ledOffTime ; unsigned int ourDelay = (int)(1000.0 * timeInc) ; setup () ; introLeds () ; // Setup the LED times - TODO reduce the ON time as the game progresses ledOnTime = 1000 ; ledOffTime = 1000 ; // This is our Gate/Squarewave loop for (;;) { // LED ON: (void)ledBargraph (vCap, TRUE) ; then = millis () + ledOnTime ; while (millis () < then) { ledOnAction () ; delay (ourDelay) ; } // Have we won yet? // We need vCap to be in the top NUM_LEDS of the vCharge if (vCap > ((double)(NUM_LEDS - 1) / (double)NUM_LEDS * vCharge)) // Woo hoo! { winningLeds () ; while (digitalRead (PIFACE) == HIGH) delay (10) ; while (digitalRead (PIFACE) == LOW) delay (10) ; vCap = vCapLast = 0.0 ; } // LED OFF: (void)ledBargraph (vCap, FALSE) ; then = millis () + ledOffTime ; while (millis () < then) { ledOffAction () ; delay (ourDelay) ; } } return 0 ; }