wiringPi/examples/PiFace/ladder.c

338 lines
6.2 KiB
C

/*
* ladder.c:
*
* Gordon Henderson, June 2012
***********************************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <wiringPi.h>
#include <piFace.h>
#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 ;
}