Advertisement
Frash

Arduino based alcoholic roulette game

Nov 4th, 2013
186
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.63 KB | None | 0 0
  1. /********************************************************************
  2. *    |RRR    /OOO  |U   U |L     |EEEEE |TTTTT |TTTTT |EEEEE        *
  3. *    |R  R  |O   O |U   U |L     |E       |T     |T   |E            *
  4. *    |RRR   |O   O |U   U |L     |EE      |T     |T   |EE           *
  5. *    |R  R  |O   O |U   U |L     |E       |T     |T   |E            *
  6. *    |R   R  \OOO   \UUU  |LLLLL |EEEEE   |T     |T   |EEEEE        *
  7. *                                                                   *
  8. *          ARDUINO   BASED   ALCOHOLIC   ROULETTE   GAME            *
  9. *                                                                   *
  10. *          ~ b y   F r a s h   P i k a s s ,   2 0 1 3 ~            *
  11. ********************************************************************/
  12.  
  13. /******************************
  14. *         PLAYING THE         *
  15. *            GAME             *
  16. *******************************
  17.  
  18. Have a special tray in which each led is under a shotglass.
  19. Fill each shotglass with a different drink.
  20. Place the tray at the center of the table and sit around it
  21. with your friends.
  22. Decide an order for drinking; each drinker has to click
  23. the REROLL pushbutton once to get a randomly picked drink!
  24.  
  25. When a game is finished, have another round!
  26.  
  27. /******************************
  28. *         SCHEMATICS          *
  29. *******************************
  30.  
  31.       ARDUINO
  32.        PINS           REROLL
  33.                     PUSHBUTTON
  34.         D2 ─────────────/ ──────┐
  35.                                 │
  36.             LEDS                │
  37.         D3 ──►|──┐              │
  38.                  │              │
  39.         D4 ──►|──┤   Resistor   │
  40.                  ├─────\/\/\────┤
  41.         D5 ──►|──┤              │
  42.                  │              │
  43.         D6 ──►|──┘              │
  44.                                 ┴
  45.     A0 ──                  GND
  46.    
  47. Leave A0 unplugged.
  48.  
  49. You can put as many leds as you want on pins from D3 to D13
  50. and from A1 (which can be used as digital pin D15 in the code)
  51. to A5 (which can be used as digital pin D19 in the code), for
  52. a maximum total of 16 leds.
  53.  
  54. Remember to change the code accordingly, by placing the led pins
  55. you've chosen for your project in the constant array "pins" with
  56. their correct order and the number of LEDs plugged in the constant
  57. "NUMBER_OF_PINS".
  58.  
  59. Choose the resistor according to how much current you need to
  60. power up all your leds together at the same time.
  61.  
  62. I suggest you to try different values with a potentiometer while
  63. prototyping.
  64.  
  65. */
  66.  
  67. /******************************
  68. *          CONSTANTS          *
  69. ******************************/
  70.  
  71. //The number of pins installed
  72. #define NUMBER_OF_PINS 4
  73. //The minimum number of cycles Arduino must do when rolling
  74. #define MIN_NUMBER_OF_ROLLING_CYCLES 5
  75.  
  76. //The minimum time between blinks in a roll
  77. #define MIN_ROLLING_TIME_STEP 10
  78.  
  79. //The maximum time between blinks in a roll
  80. #define MAX_ROLLING_TIME_STEP 550
  81.  
  82. //The default delay time for blinks
  83. #define DEFAULT_DELAY 200
  84.  
  85. /*
  86. The pins array contains all the pins with leds attached
  87. in the order you want them to turn on while cycling.
  88. */
  89. const int pins[NUMBER_OF_PINS] = {3, 4, 5, 6};
  90.  
  91. /*
  92. This is an input pin connected to the reroll pushbutton.
  93. The reroll pushbutton short circuits the input on pin 2
  94. to GND, and the reroll pin is read with the internal pullup
  95. resistors of the arduino.
  96. */
  97. const int rerollPin = 2;
  98.  
  99. /*
  100. This constant holds the pin number of the analog pin with
  101. NOTHING ATTACHED the value of which is used as a seed to
  102. generate random numbers throughout the code.
  103. */
  104. const int analogSeedPin = 0;
  105.  
  106.  
  107. /******************************
  108. *            GLOBAL           *
  109. *          VARIABLES          *
  110. ******************************/
  111.  
  112. /*
  113. This is a parallel array to the constant array pins.
  114. The availablePins array contains for each led its status of
  115. availability. If a pin is available its status is 1, if it's
  116. unavailable its status is 0.
  117. It's initialized to ones at the beginning of each loop.
  118. The status is updated to 0 every time the roulette stops.
  119. */
  120. int availablePins[NUMBER_OF_PINS];
  121.  
  122. /*
  123. The numberOfAvailablePins variable keeps track of how many pins are
  124. still available. It's inizialized in the initAvailablePins() function
  125. to NUMBER_OF_PINS and it's decreased by 1 every time the roulette
  126. stops.
  127. */
  128. int numberOfAvailablePins=NUMBER_OF_PINS;
  129.  
  130. /*
  131. The currentPin variable contains the index of the current pin in the
  132. cycle.
  133. */
  134. int currentPin;
  135.  
  136.  
  137. /******************************
  138. *           UTILITY           *
  139. *          FUNCTIONS          *
  140. ******************************/
  141.  
  142. /*
  143. Blinks once on the specific pin for a given time
  144. */
  145. void blink(int pin, int time)
  146. {
  147.   digitalWrite(pin, HIGH);
  148.   delay(time);
  149.   digitalWrite(pin, LOW);
  150.   delay(time);
  151.   return;
  152. }
  153.  
  154. /*
  155. Turns on the specific pin.
  156. */
  157. void turnOn(int pin)
  158. {
  159.   digitalWrite(pin, HIGH);
  160.   return;
  161. }
  162.  
  163. /*
  164. Turns off the specific pin.
  165. */
  166. void turnOff(int pin)
  167. {
  168.   digitalWrite(pin, LOW);
  169.   return;
  170. }
  171.  
  172. /*
  173. Turns on all the pins for a given time (in millis)
  174. */
  175. void allOn(long millisOn)
  176. {
  177.   int i;
  178.   long prevTime=millis();
  179.  
  180.   while((millis()-prevTime)<millisOn)
  181.   {
  182.     for(i=0; i<NUMBER_OF_PINS; i++)
  183.     {
  184.       digitalWrite(pins[i], HIGH);
  185.       digitalWrite(pins[i], LOW);
  186.     }
  187.   }
  188.  
  189.   return;
  190. }
  191.  
  192. /*
  193. Turns all the led pins on.
  194. Overloads the previous function but uses no arguments
  195. */
  196. void allOn()
  197. {
  198.   for(int i=0; i<NUMBER_OF_PINS; i++)
  199.   {
  200.     digitalWrite(pins[i], HIGH);
  201.   }
  202.  
  203.   return;
  204. }
  205.  
  206. /*
  207. Turns off all the pins.
  208. */
  209. void allOff()
  210. {
  211.   int i;
  212.  
  213.   for(i=0; i<NUMBER_OF_PINS; i++)
  214.     digitalWrite(pins[i], LOW);
  215.   return;
  216. }
  217.  
  218.  
  219. /*
  220. Blinks all lights a number of times with a default delay.
  221. */
  222. /*
  223. *I'm not too happy with this variant, but it should work
  224. *more efficiently when done properly.
  225.  
  226. void blinkAll(int times, long delay_)
  227. {
  228.   for(int i=0; i<times; i++)
  229.   {
  230.     allOn(delay_);
  231.     allOff();
  232.     delay(delay_);
  233.   }
  234.   return;  
  235. }
  236. */
  237. void blinkAll(int times, long delay_)
  238. {
  239.   for(int i=0; i<times; i++)
  240.   {
  241.     allOn();
  242.     delay(delay_);
  243.     allOff();
  244.     delay(delay_);
  245.   }
  246.   return;
  247. }
  248.  
  249. /*
  250. Initializes to 1 the array of pin availability status and resets
  251. the variable numberOfAvailablePins.
  252. */
  253. void initAvailablePins()
  254. {
  255.   numberOfAvailablePins = NUMBER_OF_PINS;
  256.  
  257.   int i;
  258.   for(i=0; i<NUMBER_OF_PINS; i++)
  259.     availablePins[i] = 1;
  260.   return;
  261. }
  262.  
  263. /*
  264. Returns the index of an available pin after pinIndex
  265. */
  266. int getNextAvailablePin(int pinIndex)
  267. {
  268.   int p = (pinIndex+1)%NUMBER_OF_PINS;
  269.  
  270.   if(numberOfAvailablePins==0)    //If there are no pins available
  271.     return -1;                    //return -1
  272.  
  273.   else if(availablePins[p]==1)    //Else, if the pin p is available
  274.     return p;                     //return p
  275.  
  276.   else                            //Otherwise, run recursively until
  277.     return getNextAvailablePin(p);//you find an available pin
  278. }
  279.  
  280. /*
  281. Returns the index of a random available pin
  282. */
  283. int getRandomAvailablePin()
  284. {
  285.   int randomPin;
  286.   if(numberOfAvailablePins==0)  //If there are no pins available
  287.     return -1;                  //return -1
  288.   else
  289.   {
  290.     //Seeds the random number generator
  291.     randomSeed(analogRead(analogSeedPin));
  292.  
  293.     //Gets a random pin index number
  294.     randomPin = random(0, NUMBER_OF_PINS);
  295.     return getNextAvailablePin(randomPin);
  296.   }
  297. }
  298.  
  299. /*
  300. Rolls the roulette in a fancy way!
  301. Returns the random available pin extracted.
  302. */
  303. int roll(int firstPinId)
  304. {
  305.   allOff();
  306.   //Seeds the random number generator
  307.   randomSeed(analogRead(analogSeedPin));
  308.  
  309.   //Setup a random unbalancer
  310.   int unbalancer=random(0, numberOfAvailablePins);
  311.  
  312.   //Setup an index for the cycle and one for the pins
  313.   int i, p=firstPinId;
  314.  
  315.   //Setup how many rolling steps we must cycle through
  316.   int rollingSteps = MIN_NUMBER_OF_ROLLING_CYCLES*numberOfAvailablePins+unbalancer;
  317.   for(i=0; i<rollingSteps; i++)
  318.   {
  319.     //Blink for a time directly proportional to the position of i in the range
  320.     //[0,rollingSteps]
  321.     blink(pins[p], map(i, 0, rollingSteps, MIN_ROLLING_TIME_STEP, MAX_ROLLING_TIME_STEP));
  322.     p=getNextAvailablePin(p);
  323.   }
  324.   return p;
  325. }
  326.  
  327. /*
  328. Wait until reroll pushbutton is pushed and released.
  329. The function is written considering the rerollPin is
  330. configured as INPUT_PULLUP, meaning that LOW means
  331. "button pushed" and HIGH means "button released".
  332. */
  333. void waitForReroll()
  334. {
  335.   while(true)
  336.     {
  337.       if(digitalRead(rerollPin)==LOW){
  338.         while(true){
  339.           if(digitalRead(rerollPin)==HIGH);
  340.           break;
  341.         }
  342.         break;
  343.       }
  344.     }
  345.   return;
  346. }
  347.  
  348. /*
  349. Sets the selected pin as unavailable for future rolls.
  350. */
  351. void setUnavailable(int pinIndex)
  352. {
  353.   if(pinIndex>=0 && pinIndex<NUMBER_OF_PINS)
  354.   {
  355.     availablePins[pinIndex] = 0;
  356.     numberOfAvailablePins--;
  357.   }
  358.   return;
  359. }
  360.  
  361. /*
  362. Test leds for malfunctions
  363. */
  364. void testLeds()
  365. {
  366.   allOff();
  367.   for(int i = 0; i < NUMBER_OF_PINS; i++)
  368.   {
  369.     turnOn(pins[i]);
  370.     delay(500);
  371.   }
  372.  
  373.   for(int i = 0; i < NUMBER_OF_PINS; i++)
  374.   {
  375.     turnOff(pins[i]);
  376.     delay(500);
  377.   }
  378. }
  379.  
  380. /******************************
  381. *         MAIN PROGRAM        *
  382. ******************************/
  383.  
  384. /*
  385. RUNS ONCE AT THE BEGINNING
  386. */
  387. void setup()
  388. {
  389.   int i;  //Cycle index
  390.  
  391.   //Initializes the led pins in the pins array as output
  392.   for(i=0; i<NUMBER_OF_PINS; i++)
  393.     pinMode(pins[i], OUTPUT);
  394.  
  395.   //Initializes the reroll pin as input pullup
  396.   //meaning that the open button will read as HIGH
  397.   //while the closed button will read as LOW.
  398.   //To close the button on rerollPin, you need to short it
  399.   //to GND!!!
  400.   pinMode(rerollPin, INPUT_PULLUP);
  401. }
  402.  
  403. /*
  404. LOOPS INDEFINITELY
  405. */
  406. void loop()
  407. {
  408.   //Initialize all
  409.   initAvailablePins();
  410.   currentPin = getRandomAvailablePin();
  411.  
  412.   testLeds();
  413.   allOn();
  414.  
  415.   //Wait for reroll input...
  416.   waitForReroll();
  417.  
  418.   for(int i = numberOfAvailablePins;i>0;i--)
  419.   {
  420.     //Let's roll!
  421.     if(i>1)
  422.       currentPin = roll(currentPin);
  423.     else
  424.     {
  425.       allOff();
  426.       currentPin = getNextAvailablePin(currentPin);
  427.     }
  428.    
  429.     //If a valid pin was extracted
  430.     if(currentPin != -1)
  431.     {
  432.       turnOn(pins[currentPin]);
  433.       delay(DEFAULT_DELAY);      //Wait for reroll input...
  434.       waitForReroll();
  435.       //Set the current pin as unavailable for future rolls
  436.       setUnavailable(currentPin);
  437.     }
  438.     else //If no valid pin was extracted (e.g. in case of a severe hardware error)
  439.     {
  440.       testLeds();
  441.       testLeds();
  442.       allOn();
  443.       waitForReroll();
  444.       break;
  445.     }
  446.   }
  447.  
  448.   //If one game has finished,
  449.   //Blink all lights three times
  450.   blinkAll(3, DEFAULT_DELAY);
  451.  
  452.   //Loop from the start!
  453. }
  454.  
  455. /******************************
  456. *         CONTACTS &          *
  457. *      COPYRIGHT NOTICE       *
  458. ******************************/
  459. /*
  460. * Code written by Frash Pikass (spamfrash@gmail.com)
  461. * in November 2013.
  462. *
  463. * This piece of software is released under a Creative Commons
  464. * Licence.
  465. * You can:
  466. *   - Share and enjoy it with friends freely
  467. *   - Make derivative works out of it (but giving some credits to
  468. *     the author)
  469. *  You can not:
  470. *   - Sell derivative works (at least without the author's consent)
  471. *   - Sell this code.
  472. *
  473. * Drink responsibly and don't break the law in your country
  474. * (UNLESS THE LAW IS UNJUST)
  475. *
  476. * "One has not only a legal but a moral responsibility to obey
  477. *  just laws. Conversely, one has a moral responsibility to
  478. *  disobey unjust laws."
  479. *                                      ~Martin Luther King Jr.
  480. *           (from "Letter from a Birmingham Jail")
  481. *
  482. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement