Gordons Projects

--> Projects Top-Level GIT

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