blob: 4f08a6f55a57025eaea7280d2a32117578ac5ab5 [file] [log] [blame]
Deokgyu Yang2c7e86b2020-04-28 10:56:11 +09001/*
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
31const 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
40const double vBatt = 9.0 ; // Volts (ie. a PP3)
41const double capacitor = 0.001 ; // 1000uF
42const double rCharge = 2200.0 ; // ohms
43const double rDischarge = 68000.0 ; // ohms
44const double timeInc = 0.01 ; // Seconds
45
46double vCharge, vCap, vCapLast ;
47
48
49
50/*
51 * setup:
52 * Program the GPIO correctly and initialise the lamps
53 ***********************************************************************
54 */
55
56void 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
98void 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
146void 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
186void 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
198void 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
217void 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
242void 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
258void 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
283int 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}