Electronic Beer Pong
Authors:
Yaoyao Wolansky - yaoyaowolansky@gmail.com
RJ Robak - richard.j.robak.iii@gmail.com
Noah McNair - nmcnair3013@csum.edu
(For more questions contact us at our emails above)
Here is a video of our working project: https://youtu.be/RARWashAqwE
Here is a video of the presentation we made: https://youtu.be/cpGaHxqV3LI
Acknowledgments:
Patrick Mullen (3D Printing)
Erin Cole (MakerSpace)
Ben Bashor (ET370 Tutor)
California Maritime Academy (Marine Engineering Technology)
Professor Chang-Siu and Professor Clyatt (ET370 Electronics)
The Idea:
The idea for this project was to turn a college favorite drinking game, into something more innovative and fun to play with. We created a 10 cup triangle that has proximity infrared sensors to detect if the cup is on or off the triangle platform that we created. Based on the sensor reading, the neopixels would turn different colors accordingly. Additionally, we created a "re-rack" button that would allow the player to adjust the placement of the cups into a new formation. Lastly, this game is made to be portable so that you may take it to any party you go to.
Green LED - Cup is still on the triangle
Red LED - Cup has been removed
Re-rack Button Function - Button that counts cups taken away and gives a rerack pattern based on how many cups are left in the game. Also allows for the player to reset the game, if they so choose.
LED Light Show - a light show will appear once all the cups have been removed from the platform
Here is the link to our animated electronic beer pong game for a better understanding of how the game is made: https://youtu.be/lAGh_5KQJfI
Supplies
Below is a list of supplies we used to create this project. All supplies may be purchased from Amazon. WE HIGHLY RECOMMEND BUYING EXTRA ELECTRICAL COMPONENTS. YOU MAY END UP FRYING SOME OF THESE PARTS, JUST LIKE US
Electrical Components:
1. Neopixel Strips: 3 neopixels were used per cup, 30 total. The color of the neopixel was changed based off whether or not the cup is there, to create the light-show and for the re-rack function. The neopixels will all be in series
2. 10 Proximity Infrared Sensors: This will detect whether or not a cup is there and change the color of the neopixels accordingly. You will need 10. 1 for each cup.
3. 1 Nano Arduino: This is used to store the code for the game. Usually comes with a USB cable to upload the code
4. 2 Re-chargable batteries: In order to keep the game portable, you will need 2 re-chargable batteries. These batteries will also be the power supply to the buck converter
5. 1 Buck Converter: To step down the voltage to 5V, this way you will have enough voltage going through the electrical system
6. 1 Toggle Switch: This turns the game on/off so that the game may be portable.
7. 1 10k Pulldown Resistor: This is connected to the ground of the re-rack button
8. 1 470 Pullup Resistor: This is connected to the digital-input of the first neopixel in series
9. 1 Capacitor: To smooth out the colors in the neopixels
10. 1 Button: To serve as the "re-rack button"
Non-Electrical Components:
11. Soldering Kit: To solder every electrical component together.
12. 3D printer and filament: This will be used to print our hexagon shaped pods that will hold the cups
13. Acrylic Plexiglass: This will be used on top of the 3D hexagon shaped pod prints, so that no liquid can get inside the pod. This will also hold the cups
14. Gorilla Glue (Gel): This will be used to glue the 3D hexagon shaped pods together
15. Red Solo Cups: For obvious reasons
16. Ping Pong Balls: Also for obvious reasons
17. Hot Glue Gun: This is used to glue the PIRs in place, inside the 3D hexagon shaped pods
18. Electrical Tape (Optional): To tape electrical wires together
20. Perf boards: To solder the electrical wires to
21. Electrical Heat Shrink: To protect exposed wire from shorting, especially if you solder two wires together
22. Heat Gum: To shrink the heat shrink
23. Base Board: We used a wood base board, but you may use any base board you'd like to hold the 3D hexagon prints and all of the electrical components together
24. Blue Tape: Served for various purposes, but to mainly tape components down
25. Wire strippers: To cut and strip wires
26. 22 Gage Wire: Or any gage wire of your choosing, whether it be solid core or braided. Buy extra as well
27. Multimeter: Super helpful with testing conductivity and voltages
3D CAD Drawings
Description:
Here are the 3D CAD drawings we created. The lip that you see in the CAD drawings is where the plexiglass will sit. Inside the hexagon housing will be the IR sensors and neopixels. Outside of the housing will be the cups that sit on top of the plexiglass.
Here is a video of the 3D printing process: https://youtu.be/tPCRVMqumZM
Circuit Diagram
Description: You may also search me on TinkerCad to view the code we used for the project @yaoyaowolansky or by searching "Electronic Beer Pong Code"
- The 2 parallel re-chargable batteries feeds the input of the buck converter and the nano arduino.
- From the output of the buck converter connects the ground and power of the buck converter to the ground and power of the neopixels. Additionally, the capacitor is placed in series as well, connecting the power and ground to the power and ground of the buck converter and neopixels
- The digital inputs of the IR sensor will be connected to the digital pins of the nano arduino.
- The power and ground of each IR sensor will be soldered to a perf board on the negative and positive side
State Machine Diagram
Here is the state machine diagram that explains the logic of the game. The begins in state 1 with all neopixels red or green based on IR sensor reading. Once there are 6, 4, 3, 2, and 0 cups left in the game, you may choose to "re-rack" the game in which you will be allowed to re-arrange the placements of your cups. For example, if there are 6 cups left in the game (green arrow) you will be sent to State 2, in which you must satisfy the new re-rack orientation in order to be sent back to state 1. I highly recommend that you watch the beer pong animation if you have not done so already. The video can be found under "The Idea".
Arduino Code
We first start off the code by defining our variables above the void setup:
#include <Adafruit_NeoPixel.h> #define PIN 12 // On Trinket or Gemma, suggest changing this to 1 #define NUMPIXELS 30 // Popular NeoPixel ring size Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); #define DELAYVAL 500 // Time (in milliseconds) to pause between pixels int SwitchPin1 = 13; int SwitchPin1State = 0; int SwitchPin1StatePrev = 0; int SwitchPin2 = 2; int SwitchPin2State = 0; int SwitchPin2StatePrev = 0; int SwitchPin3 = 3; int SwitchPin3State = 0; int SwitchPin3StatePrev = 0; int SwitchPin4 = 4; int SwitchPin4State = 0; int SwitchPin4StatePrev = 0; int SwitchPin5 = 5; int SwitchPin5State = 0; int SwitchPin5StatePrev = 0; int SwitchPin6 = 6; int SwitchPin6State = 0; int SwitchPin6StatePrev = 0; int SwitchPin7 = 7; int SwitchPin7State = 0; int SwitchPin7StatePrev = 0; int SwitchPin8 = 8; int SwitchPin8State = 0; int SwitchPin8StatePrev = 0; int SwitchPin9 = 9; int SwitchPin9State = 0; int SwitchPin9StatePrev = 0; int SwitchPin10 = 10; int SwitchPin10State = 0; int SwitchPin10StatePrev = 0; int SwitchPinCount = 0; const int buttonPin = 11; int buttonStatePrev = 0; int state = 1; int buttonState = 0; unsigned long changeTime; unsigned long intervalTime = 5000; //light show int RbArrayR[] = {148, 75, 0, 0, 255, 255, 255}; int RbArrayG[] = {0, 0, 0, 255, 255, 127, 0}; int RbArrayB[] = {211, 130, 255, 0, 0, 0, 0}; int pixelIndex = 0; int colorIndex = 0; int factor = 0;<br>
In the void setup we have:
void setup() { Serial.begin(9600); pinMode(12, OUTPUT);// initialize neopixel pin as output pinMode(buttonPin, INPUT);// initialize pushbutton pin as input pinMode(SwitchPin1, INPUT); pinMode(SwitchPin2, INPUT); pinMode(SwitchPin3, INPUT); pinMode(SwitchPin4, INPUT); pinMode(SwitchPin5, INPUT); pinMode(SwitchPin6, INPUT); pinMode(SwitchPin7, INPUT); pinMode(SwitchPin8, INPUT); pinMode(SwitchPin9, INPUT); pinMode(SwitchPin10, INPUT); changeTime = millis(); pixels.begin(); // Initialize NeoPixel strip pixels.setBrightness(50); }
In the void loop we must first define the button state and the switch pin states:
void loop() { buttonStatePrev = buttonState; //Store the previous button state buttonState = digitalRead(buttonPin);// read the state of the pushbutton value SwitchPin1StatePrev = SwitchPin1State; SwitchPin1State = digitalRead(SwitchPin1); SwitchPin2StatePrev = SwitchPin2State; SwitchPin2State = digitalRead(SwitchPin2); SwitchPin3StatePrev = SwitchPin3State; SwitchPin3State = digitalRead(SwitchPin3); SwitchPin4StatePrev = SwitchPin4State; SwitchPin4State = digitalRead(SwitchPin4); SwitchPin5StatePrev = SwitchPin5State; SwitchPin5State = digitalRead(SwitchPin5); SwitchPin6StatePrev = SwitchPin6State; SwitchPin6State = digitalRead(SwitchPin6); SwitchPin7StatePrev = SwitchPin7State; SwitchPin7State = digitalRead(SwitchPin7); SwitchPin8StatePrev = SwitchPin8State; SwitchPin8State = digitalRead(SwitchPin8); SwitchPin9StatePrev = SwitchPin9State; SwitchPin9State = digitalRead(SwitchPin9); SwitchPin10StatePrev = SwitchPin10State; SwitchPin10State = digitalRead(SwitchPin10);
Now we may begin defining each switch state: Case 1
This starts off the game by having all of the neopixels light up yellow until an IR sensor has read that an object has been placed on top of it. Once state 1 is satisfied with all 10 cups on the board, the game may continue to case 2
switch (state) { case 1: //game begins with all neopixels yellow, until satisfied with cups if(SwitchPin1State == LOW){ pixels.setPixelColor(0, pixels.Color(0,255,0)); //green, cup detected pixels.setPixelColor(1, pixels.Color(0,255,0)); pixels.setPixelColor(2, pixels.Color(0,255,0)); } else { pixels.setPixelColor(0, pixels.Color(255,255,0));//yellow, no cup detected pixels.setPixelColor(1, pixels.Color(255,255,0)); pixels.setPixelColor(2, pixels.Color(255,255,0)); } if(SwitchPin2State == LOW){ pixels.setPixelColor(3, pixels.Color(0,255,0)); pixels.setPixelColor(4, pixels.Color(0,255,0)); pixels.setPixelColor(5, pixels.Color(0,255,0)); } else { pixels.setPixelColor(3, pixels.Color(255,255,0)); pixels.setPixelColor(4, pixels.Color(255,255,0)); pixels.setPixelColor(5, pixels.Color(255,255,0)); } if(SwitchPin3State == LOW){ pixels.setPixelColor(6, pixels.Color(0,255,0)); pixels.setPixelColor(7, pixels.Color(0,255,0)); pixels.setPixelColor(8, pixels.Color(0,255,0)); } else { pixels.setPixelColor(6, pixels.Color(255,255,0)); pixels.setPixelColor(7, pixels.Color(255,255,0)); pixels.setPixelColor(8, pixels.Color(255,255,0)); } if(SwitchPin4State == LOW){ pixels.setPixelColor(9, pixels.Color(0,255,0)); pixels.setPixelColor(10, pixels.Color(0,255,0)); pixels.setPixelColor(11, pixels.Color(0,255,0)); } else { pixels.setPixelColor(9, pixels.Color(255,255,0)); pixels.setPixelColor(10, pixels.Color(255,255,0)); pixels.setPixelColor(11, pixels.Color(255,255,0)); } if(SwitchPin5State == LOW){ pixels.setPixelColor(12, pixels.Color(0,255,0)); pixels.setPixelColor(13, pixels.Color(0,255,0)); pixels.setPixelColor(14, pixels.Color(0,255,0)); } else { pixels.setPixelColor(12, pixels.Color(255,255,0)); pixels.setPixelColor(13, pixels.Color(255,255,0)); pixels.setPixelColor(14, pixels.Color(255,255,0)); } if(SwitchPin6State == LOW){ pixels.setPixelColor(15, pixels.Color(0,255,0)); pixels.setPixelColor(16, pixels.Color(0,255,0)); pixels.setPixelColor(17, pixels.Color(0,255,0)); } else { pixels.setPixelColor(15, pixels.Color(255,255,0)); pixels.setPixelColor(16, pixels.Color(255,255,0)); pixels.setPixelColor(17, pixels.Color(255,255,0)); } if(SwitchPin7State == LOW){ pixels.setPixelColor(18, pixels.Color(0,255,0)); pixels.setPixelColor(19, pixels.Color(0,255,0)); pixels.setPixelColor(20, pixels.Color(0,255,0)); } else { pixels.setPixelColor(18, pixels.Color(255,255,0)); pixels.setPixelColor(19, pixels.Color(255,255,0)); pixels.setPixelColor(20, pixels.Color(255,255,0)); } if(SwitchPin8State == LOW){ pixels.setPixelColor(21, pixels.Color(0,255,0)); pixels.setPixelColor(22, pixels.Color(0,255,0)); pixels.setPixelColor(23, pixels.Color(0,255,0)); } else { pixels.setPixelColor(21, pixels.Color(255,255,0)); pixels.setPixelColor(22, pixels.Color(255,255,0)); pixels.setPixelColor(23, pixels.Color(255,255,0)); } if(SwitchPin9State == LOW){ pixels.setPixelColor(24, pixels.Color(0,255,0)); pixels.setPixelColor(25, pixels.Color(0,255,0)); pixels.setPixelColor(26, pixels.Color(0,255,0)); } else { pixels.setPixelColor(24, pixels.Color(255,255,0)); pixels.setPixelColor(25, pixels.Color(255,255,0)); pixels.setPixelColor(26, pixels.Color(255,255,0)); } if(SwitchPin10State == LOW){ pixels.setPixelColor(27, pixels.Color(0,255,0)); pixels.setPixelColor(28, pixels.Color(0,255,0)); pixels.setPixelColor(29, pixels.Color(0,255,0)); } else { pixels.setPixelColor(27, pixels.Color(255,255,0)); pixels.setPixelColor(28, pixels.Color(255,255,0)); pixels.setPixelColor(29, pixels.Color(255,255,0)); } pixels.show(); SwitchPinCount = SwitchPin1State + SwitchPin2State + SwitchPin3State + SwitchPin4State + SwitchPin5State + SwitchPin6State + SwitchPin7State + SwitchPin8State + SwitchPin9State + SwitchPin10State; Serial.println(" in State 1 "); if (SwitchPinCount == 0){ Serial.println(" 10 cups detected "); state = 2; break; } break;<br>
Case 2:
case 2: // game begins once the cups are on the board therefore turning green if(SwitchPin1State == LOW){ pixels.setPixelColor(0, pixels.Color(0,255,0)); //green, cup detected pixels.setPixelColor(1, pixels.Color(0,255,0)); pixels.setPixelColor(2, pixels.Color(0,255,0)); } else { pixels.setPixelColor(0, pixels.Color(255,0,0));//red, no cup detected pixels.setPixelColor(1, pixels.Color(255,0,0)); pixels.setPixelColor(2, pixels.Color(255,0,0)); } if(SwitchPin2State == LOW){ pixels.setPixelColor(3, pixels.Color(0,255,0)); pixels.setPixelColor(4, pixels.Color(0,255,0)); pixels.setPixelColor(5, pixels.Color(0,255,0)); } else { pixels.setPixelColor(3, pixels.Color(255,0,0)); pixels.setPixelColor(4, pixels.Color(255,0,0)); pixels.setPixelColor(5, pixels.Color(255,0,0)); } if(SwitchPin3State == LOW){ pixels.setPixelColor(6, pixels.Color(0,255,0)); pixels.setPixelColor(7, pixels.Color(0,255,0)); pixels.setPixelColor(8, pixels.Color(0,255,0)); } else { pixels.setPixelColor(6, pixels.Color(255,0,0)); pixels.setPixelColor(7, pixels.Color(255,0,0)); pixels.setPixelColor(8, pixels.Color(255,0,0)); } if(SwitchPin4State == LOW){ pixels.setPixelColor(9, pixels.Color(0,255,0)); pixels.setPixelColor(10, pixels.Color(0,255,0)); pixels.setPixelColor(11, pixels.Color(0,255,0)); } else { pixels.setPixelColor(9, pixels.Color(255,0,0)); pixels.setPixelColor(10, pixels.Color(255,0,0)); pixels.setPixelColor(11, pixels.Color(255,0,0)); } if(SwitchPin5State == LOW){ pixels.setPixelColor(12, pixels.Color(0,255,0)); pixels.setPixelColor(13, pixels.Color(0,255,0)); pixels.setPixelColor(14, pixels.Color(0,255,0)); } else { pixels.setPixelColor(12, pixels.Color(255,0,0)); pixels.setPixelColor(13, pixels.Color(255,0,0)); pixels.setPixelColor(14, pixels.Color(255,0,0)); } if(SwitchPin6State == LOW){ pixels.setPixelColor(15, pixels.Color(0,255,0)); pixels.setPixelColor(16, pixels.Color(0,255,0)); pixels.setPixelColor(17, pixels.Color(0,255,0)); } else { pixels.setPixelColor(15, pixels.Color(255,0,0)); pixels.setPixelColor(16, pixels.Color(255,0,0)); pixels.setPixelColor(17, pixels.Color(255,0,0)); } if(SwitchPin7State == LOW){ pixels.setPixelColor(18, pixels.Color(0,255,0)); pixels.setPixelColor(19, pixels.Color(0,255,0)); pixels.setPixelColor(20, pixels.Color(0,255,0)); } else { pixels.setPixelColor(18, pixels.Color(255,0,0)); pixels.setPixelColor(19, pixels.Color(255,0,0)); pixels.setPixelColor(20, pixels.Color(255,0,0)); } if(SwitchPin8State == LOW){ pixels.setPixelColor(21, pixels.Color(0,255,0)); pixels.setPixelColor(22, pixels.Color(0,255,0)); pixels.setPixelColor(23, pixels.Color(0,255,0)); } else { pixels.setPixelColor(21, pixels.Color(255,0,0)); pixels.setPixelColor(22, pixels.Color(255,0,0)); pixels.setPixelColor(23, pixels.Color(255,0,0)); } if(SwitchPin9State == LOW){ pixels.setPixelColor(24, pixels.Color(0,255,0)); pixels.setPixelColor(25, pixels.Color(0,255,0)); pixels.setPixelColor(26, pixels.Color(0,255,0)); } else { pixels.setPixelColor(24, pixels.Color(255,0,0)); pixels.setPixelColor(25, pixels.Color(255,0,0)); pixels.setPixelColor(26, pixels.Color(255,0,0)); } if(SwitchPin10State == LOW){ pixels.setPixelColor(27, pixels.Color(0,255,0)); pixels.setPixelColor(28, pixels.Color(0,255,0)); pixels.setPixelColor(29, pixels.Color(0,255,0)); } else { pixels.setPixelColor(27, pixels.Color(255,0,0)); pixels.setPixelColor(28, pixels.Color(255,0,0)); pixels.setPixelColor(29, pixels.Color(255,0,0)); } pixels.show(); SwitchPinCount = SwitchPin1State + SwitchPin2State + SwitchPin3State + SwitchPin4State + SwitchPin5State + SwitchPin6State + SwitchPin7State + SwitchPin8State + SwitchPin9State + SwitchPin10State; Serial.println(" in State 2"); if (SwitchPinCount == 4 && buttonState == HIGH && buttonStatePrev == LOW){ Serial.println(" button press detected "); state = 3; break; } if (SwitchPinCount == 6 && buttonState == HIGH && buttonStatePrev == LOW){ Serial.println(" button press detected "); state = 4; break; } if (SwitchPinCount == 7 && buttonState == HIGH && buttonStatePrev == LOW){ Serial.println(" button press detected "); state = 5; break; } if (SwitchPinCount == 8 && buttonState == HIGH && buttonStatePrev == LOW){ Serial.println(" button press detected "); state = 6; break; } if (SwitchPinCount == 10){ Serial.println(" !WINNER! "); state = 7; break; //this will leave the switch case } break;<br>
Case 3: 6 cup re-rack
case 3: // 6 cup re-rack if(SwitchPin1State == LOW){ pixels.setPixelColor(0, pixels.Color(255,0,0)); //red pixels.setPixelColor(1, pixels.Color(255,0,0)); pixels.setPixelColor(2, pixels.Color(255,0,0)); } else { pixels.setPixelColor(0, pixels.Color(255,0,0)); pixels.setPixelColor(1, pixels.Color(255,0,0)); pixels.setPixelColor(2, pixels.Color(255,0,0)); } if(SwitchPin2State == LOW){ pixels.setPixelColor(3, pixels.Color(0,255,0)); pixels.setPixelColor(4, pixels.Color(0,255,0)); pixels.setPixelColor(5, pixels.Color(0,255,0)); } else { pixels.setPixelColor(3, pixels.Color(255,255,0)); pixels.setPixelColor(4, pixels.Color(255,255,0)); pixels.setPixelColor(5, pixels.Color(255,255,0)); } if(SwitchPin3State == LOW){ pixels.setPixelColor(6, pixels.Color(0,255,0)); pixels.setPixelColor(7, pixels.Color(0,255,0)); pixels.setPixelColor(8, pixels.Color(0,255,0)); } else { pixels.setPixelColor(6, pixels.Color(255,255,0)); pixels.setPixelColor(7, pixels.Color(255,255,0)); pixels.setPixelColor(8, pixels.Color(255,255,0)); } if(SwitchPin4State == LOW){ pixels.setPixelColor(9, pixels.Color(0,255,0)); pixels.setPixelColor(10, pixels.Color(0,255,0)); pixels.setPixelColor(11, pixels.Color(0,255,0)); } else { pixels.setPixelColor(9, pixels.Color(255,255,0)); pixels.setPixelColor(10, pixels.Color(255,255,0)); pixels.setPixelColor(11, pixels.Color(255,255,0)); } if(SwitchPin5State == LOW){ pixels.setPixelColor(12, pixels.Color(0,255,0)); pixels.setPixelColor(13, pixels.Color(0,255,0)); pixels.setPixelColor(14, pixels.Color(0,255,0)); } else { pixels.setPixelColor(12, pixels.Color(255,255,0)); pixels.setPixelColor(13, pixels.Color(255,255,0)); pixels.setPixelColor(14, pixels.Color(255,255,0)); } if(SwitchPin6State == LOW){ pixels.setPixelColor(15, pixels.Color(0,255,0)); pixels.setPixelColor(16, pixels.Color(0,255,0)); pixels.setPixelColor(17, pixels.Color(0,255,0)); } else { pixels.setPixelColor(15, pixels.Color(255,255,0)); pixels.setPixelColor(16, pixels.Color(255,255,0)); pixels.setPixelColor(17, pixels.Color(255,255,0)); } if(SwitchPin7State == LOW){ pixels.setPixelColor(18, pixels.Color(0,255,0)); pixels.setPixelColor(19, pixels.Color(0,255,0)); pixels.setPixelColor(20, pixels.Color(0,255,0)); } else { pixels.setPixelColor(18, pixels.Color(255,255,0)); pixels.setPixelColor(19, pixels.Color(255,255,0)); pixels.setPixelColor(20, pixels.Color(255,255,0)); } if(SwitchPin8State == LOW){ pixels.setPixelColor(21, pixels.Color(255,0,0)); pixels.setPixelColor(22, pixels.Color(255,0,0)); pixels.setPixelColor(23, pixels.Color(255,0,0)); } else { pixels.setPixelColor(21, pixels.Color(255,0,0)); pixels.setPixelColor(22, pixels.Color(255,0,0)); pixels.setPixelColor(24, pixels.Color(255,0,0)); } if(SwitchPin9State == LOW){ pixels.setPixelColor(24, pixels.Color(255,0,0)); //red pixels.setPixelColor(25, pixels.Color(255,0,0)); pixels.setPixelColor(26, pixels.Color(255,0,0)); } else { pixels.setPixelColor(24, pixels.Color(255,0,0)); pixels.setPixelColor(25, pixels.Color(255,0,0)); pixels.setPixelColor(26, pixels.Color(255,0,0)); } if(SwitchPin10State == LOW){ pixels.setPixelColor(27, pixels.Color(255,0,0)); pixels.setPixelColor(28, pixels.Color(255,0,0)); pixels.setPixelColor(29, pixels.Color(255,0,0)); } else { pixels.setPixelColor(27, pixels.Color(255,0,0)); pixels.setPixelColor(28, pixels.Color(255,0,0)); pixels.setPixelColor(29, pixels.Color(255,0,0)); } pixels.show(); SwitchPinCount = SwitchPin1State + SwitchPin10State + SwitchPin9State + SwitchPin8State; Serial.println(" in State 3 "); if (SwitchPinCount == 4){ Serial.println(" 6 cups detected "); state = 2; break; //this will leave the switch case } break;
Case 4: 4 cup re-rack
case 4: // 4 cup re-rack if(SwitchPin1State == LOW){ pixels.setPixelColor(0, pixels.Color(255,0,0)); //red pixels.setPixelColor(1, pixels.Color(255,0,0)); pixels.setPixelColor(2, pixels.Color(255,0,0)); } else { pixels.setPixelColor(0, pixels.Color(255,0,0)); pixels.setPixelColor(1, pixels.Color(255,0,0)); pixels.setPixelColor(2, pixels.Color(255,0,0)); } if(SwitchPin2State == LOW){ pixels.setPixelColor(3, pixels.Color(255,0,0)); pixels.setPixelColor(4, pixels.Color(255,0,0)); pixels.setPixelColor(5, pixels.Color(255,0,0)); } else { pixels.setPixelColor(3, pixels.Color(255,0,0)); pixels.setPixelColor(4, pixels.Color(255,0,0)); pixels.setPixelColor(5, pixels.Color(255,0,0)); } if(SwitchPin3State == LOW){ pixels.setPixelColor(6, pixels.Color(0,255,0)); pixels.setPixelColor(7, pixels.Color(0,255,0)); pixels.setPixelColor(8, pixels.Color(0,255,0)); } else { pixels.setPixelColor(6, pixels.Color(255,255,0));//yellow pixels.setPixelColor(7, pixels.Color(255,255,0)); pixels.setPixelColor(8, pixels.Color(255,255,0)); } if(SwitchPin4State == LOW){ pixels.setPixelColor(9, pixels.Color(0,255,0)); pixels.setPixelColor(10, pixels.Color(0,255,0)); pixels.setPixelColor(11, pixels.Color(0,255,0)); } else { pixels.setPixelColor(9, pixels.Color(255,255,0)); pixels.setPixelColor(10, pixels.Color(255,255,0)); pixels.setPixelColor(11, pixels.Color(255,255,0)); } if(SwitchPin5State == LOW){ pixels.setPixelColor(12, pixels.Color(0,255,0)); pixels.setPixelColor(13, pixels.Color(0,255,0)); pixels.setPixelColor(14, pixels.Color(0,255,0)); } else { pixels.setPixelColor(12, pixels.Color(255,255,0)); pixels.setPixelColor(13, pixels.Color(255,255,0)); pixels.setPixelColor(14, pixels.Color(255,255,0)); } if(SwitchPin6State == LOW){ pixels.setPixelColor(15, pixels.Color(255,0,0)); pixels.setPixelColor(16, pixels.Color(255,0,0)); pixels.setPixelColor(17, pixels.Color(255,0,0)); } else { pixels.setPixelColor(15, pixels.Color(255,0,0));//red pixels.setPixelColor(16, pixels.Color(255,0,0)); pixels.setPixelColor(17, pixels.Color(255,0,0)); } if(SwitchPin7State == LOW){ pixels.setPixelColor(18, pixels.Color(0,255,0)); pixels.setPixelColor(19, pixels.Color(0,255,0)); pixels.setPixelColor(20, pixels.Color(0,255,0)); } else { pixels.setPixelColor(18, pixels.Color(255,255,0));//yellow pixels.setPixelColor(19, pixels.Color(255,255,0)); pixels.setPixelColor(20, pixels.Color(255,255,0)); } if(SwitchPin8State == LOW){ pixels.setPixelColor(21, pixels.Color(255,0,0)); pixels.setPixelColor(22, pixels.Color(255,0,0)); pixels.setPixelColor(23, pixels.Color(255,0,0)); } else { pixels.setPixelColor(21, pixels.Color(255,0,0));//red pixels.setPixelColor(22, pixels.Color(255,0,0)); pixels.setPixelColor(23, pixels.Color(255,0,0)); } if(SwitchPin9State == LOW){ pixels.setPixelColor(24, pixels.Color(255,0,0)); pixels.setPixelColor(25, pixels.Color(255,0,0)); pixels.setPixelColor(26, pixels.Color(255,0,0)); } else { pixels.setPixelColor(24, pixels.Color(255,0,0));//red pixels.setPixelColor(25, pixels.Color(255,0,0)); pixels.setPixelColor(26, pixels.Color(255,0,0)); } if(SwitchPin10State == LOW){ pixels.setPixelColor(27, pixels.Color(255,0,0)); pixels.setPixelColor(28, pixels.Color(255,0,0)); pixels.setPixelColor(29, pixels.Color(255,0,0)); } else { pixels.setPixelColor(27, pixels.Color(255,0,0)); pixels.setPixelColor(28, pixels.Color(255,0,0)); pixels.setPixelColor(29, pixels.Color(255,0,0)); } pixels.show(); SwitchPinCount = SwitchPin1State + SwitchPin2State + SwitchPin6State + SwitchPin8State + SwitchPin9State + SwitchPin10State; Serial.println(" in State 4 "); if (SwitchPinCount == 6){ Serial.println(" 4 cups detected "); state = 2; break; //this will leave the switch case } break;
Case 5: 3 cup re-rack
case 5: // 3 cup re-rack if(SwitchPin1State == LOW){ pixels.setPixelColor(0, pixels.Color(255,0,0)); pixels.setPixelColor(1, pixels.Color(255,0,0)); pixels.setPixelColor(2, pixels.Color(255,0,0)); } else { pixels.setPixelColor(0, pixels.Color(255,0,0));//red, no cup detected pixels.setPixelColor(2, pixels.Color(255,0,0)); pixels.setPixelColor(3, pixels.Color(255,0,0)); } if(SwitchPin2State == LOW){ pixels.setPixelColor(3, pixels.Color(0,255,0)); pixels.setPixelColor(4, pixels.Color(0,255,0)); pixels.setPixelColor(5, pixels.Color(0,255,0)); } else { pixels.setPixelColor(3, pixels.Color(255,0,0)); pixels.setPixelColor(4, pixels.Color(255,0,0)); pixels.setPixelColor(5, pixels.Color(255,0,0)); } if(SwitchPin3State == LOW){ pixels.setPixelColor(6, pixels.Color(0,255,0)); pixels.setPixelColor(7, pixels.Color(0,255,0)); pixels.setPixelColor(8, pixels.Color(0,255,0)); } else { pixels.setPixelColor(6, pixels.Color(255,255,0));//yellow pixels.setPixelColor(7, pixels.Color(255,255,0)); pixels.setPixelColor(8, pixels.Color(255,255,0)); } if(SwitchPin4State == LOW){ pixels.setPixelColor(9, pixels.Color(0,255,0)); pixels.setPixelColor(10, pixels.Color(0,255,0)); pixels.setPixelColor(11, pixels.Color(0,255,0)); } else { pixels.setPixelColor(9, pixels.Color(255,255,0)); pixels.setPixelColor(10, pixels.Color(255,255,0)); pixels.setPixelColor(11, pixels.Color(255,255,0)); } if(SwitchPin5State == LOW){ pixels.setPixelColor(12, pixels.Color(0,255,0)); pixels.setPixelColor(13, pixels.Color(0,255,0)); pixels.setPixelColor(14, pixels.Color(0,255,0)); } else { pixels.setPixelColor(12, pixels.Color(255,255,0)); pixels.setPixelColor(13, pixels.Color(255,255,0)); pixels.setPixelColor(14, pixels.Color(255,255,0)); } if(SwitchPin6State == LOW){ pixels.setPixelColor(15, pixels.Color(255,0,0)); pixels.setPixelColor(16, pixels.Color(255,0,0)); pixels.setPixelColor(17, pixels.Color(255,0,0)); } else { pixels.setPixelColor(15, pixels.Color(255,0,0));//red pixels.setPixelColor(16, pixels.Color(255,0,0)); pixels.setPixelColor(17, pixels.Color(255,0,0)); } if(SwitchPin7State == LOW){ pixels.setPixelColor(18, pixels.Color(255,0,0)); pixels.setPixelColor(19, pixels.Color(255,0,0)); pixels.setPixelColor(20, pixels.Color(255,0,0)); } else { pixels.setPixelColor(18, pixels.Color(255,0,0));//red pixels.setPixelColor(19, pixels.Color(255,0,0)); pixels.setPixelColor(20, pixels.Color(255,0,0)); } if(SwitchPin8State == LOW){ pixels.setPixelColor(21, pixels.Color(255,0,0)); pixels.setPixelColor(22, pixels.Color(255,0,0)); pixels.setPixelColor(23, pixels.Color(255,0,0)); } else { pixels.setPixelColor(21, pixels.Color(255,0,0));//red pixels.setPixelColor(22, pixels.Color(255,0,0)); pixels.setPixelColor(23, pixels.Color(255,0,0)); } if(SwitchPin9State == LOW){ pixels.setPixelColor(24, pixels.Color(255,0,0)); pixels.setPixelColor(25, pixels.Color(255,0,0)); pixels.setPixelColor(26, pixels.Color(255,0,0)); } else { pixels.setPixelColor(24, pixels.Color(255,0,0));//red pixels.setPixelColor(25, pixels.Color(255,0,0)); pixels.setPixelColor(26, pixels.Color(255,0,0)); } if(SwitchPin10State == LOW){ pixels.setPixelColor(27, pixels.Color(255,0,0)); pixels.setPixelColor(28, pixels.Color(255,0,0)); pixels.setPixelColor(29, pixels.Color(255,0,0)); } else { pixels.setPixelColor(27, pixels.Color(255,0,0)); pixels.setPixelColor(28, pixels.Color(255,0,0)); pixels.setPixelColor(29, pixels.Color(255,0,0)); } pixels.show(); SwitchPinCount = SwitchPin1State + SwitchPin2State + SwitchPin6State + SwitchPin7State + SwitchPin8State + SwitchPin9State + SwitchPin10State; Serial.println(" in State 5 "); if (SwitchPinCount == 7){ Serial.println(" 3 cups detected "); state = 2; break; //this will leave the switch case } break;<br>
Case 6: 2 cup re-rack
case 6: // 2 cup re-rack if(SwitchPin1State == LOW){ pixels.setPixelColor(0, pixels.Color(255,0,0)); pixels.setPixelColor(1, pixels.Color(255,0,0)); pixels.setPixelColor(2, pixels.Color(255,0,0)); } else { pixels.setPixelColor(0, pixels.Color(255,0,0));//red, no cup detected pixels.setPixelColor(1, pixels.Color(255,0,0)); pixels.setPixelColor(2, pixels.Color(255,0,0)); } if(SwitchPin2State == LOW){ pixels.setPixelColor(3, pixels.Color(255,0,0)); pixels.setPixelColor(4, pixels.Color(255,0,0)); pixels.setPixelColor(5, pixels.Color(255,0,0)); } else { pixels.setPixelColor(3, pixels.Color(255,0,0)); pixels.setPixelColor(4, pixels.Color(255,0,0)); pixels.setPixelColor(5, pixels.Color(255,0,0)); } if(SwitchPin3State == LOW){ pixels.setPixelColor(6, pixels.Color(255,0,0)); pixels.setPixelColor(7, pixels.Color(255,0,0)); pixels.setPixelColor(8, pixels.Color(255,0,0)); } else { pixels.setPixelColor(6, pixels.Color(255,0,0)); pixels.setPixelColor(7, pixels.Color(255,0,0)); pixels.setPixelColor(8, pixels.Color(255,0,0)); } if(SwitchPin4State == LOW){ pixels.setPixelColor(9, pixels.Color(0,255,0)); pixels.setPixelColor(10, pixels.Color(0,255,0)); pixels.setPixelColor(11, pixels.Color(0,255,0)); } else { pixels.setPixelColor(9, pixels.Color(255,255,0));//yellow pixels.setPixelColor(10, pixels.Color(255,255,0)); pixels.setPixelColor(11, pixels.Color(255,255,0)); } if(SwitchPin5State == LOW){ pixels.setPixelColor(12, pixels.Color(255,0,0)); pixels.setPixelColor(13, pixels.Color(255,0,0)); pixels.setPixelColor(14, pixels.Color(255,0,0)); } else { pixels.setPixelColor(12, pixels.Color(255,0,0)); pixels.setPixelColor(13, pixels.Color(255,0,0)); pixels.setPixelColor(14, pixels.Color(255,0,0)); } if(SwitchPin6State == LOW){ pixels.setPixelColor(15, pixels.Color(255,0,0)); pixels.setPixelColor(16, pixels.Color(255,0,0)); pixels.setPixelColor(17, pixels.Color(255,0,0)); } else { pixels.setPixelColor(15, pixels.Color(255,0,0));//red pixels.setPixelColor(16, pixels.Color(255,0,0)); pixels.setPixelColor(17, pixels.Color(255,0,0)); } if(SwitchPin7State == LOW){ pixels.setPixelColor(18, pixels.Color(0,255,0)); pixels.setPixelColor(19, pixels.Color(0,255,0)); pixels.setPixelColor(20, pixels.Color(0,255,0)); } else { pixels.setPixelColor(18, pixels.Color(255,255,0));//yellow pixels.setPixelColor(19, pixels.Color(255,255,0)); pixels.setPixelColor(20, pixels.Color(255,255,0)); } if(SwitchPin8State == LOW){ pixels.setPixelColor(21, pixels.Color(255,0,0)); pixels.setPixelColor(22, pixels.Color(255,0,0)); pixels.setPixelColor(23, pixels.Color(255,0,0)); } else { pixels.setPixelColor(21, pixels.Color(255,0,0));//red pixels.setPixelColor(22, pixels.Color(255,0,0)); pixels.setPixelColor(23, pixels.Color(255,0,0)); } if(SwitchPin9State == LOW){ pixels.setPixelColor(24, pixels.Color(255,0,0)); pixels.setPixelColor(25, pixels.Color(255,0,0)); pixels.setPixelColor(26, pixels.Color(255,0,0)); } else { pixels.setPixelColor(24, pixels.Color(255,0,0));//red pixels.setPixelColor(25, pixels.Color(255,0,0)); pixels.setPixelColor(26, pixels.Color(255,0,0)); } if(SwitchPin10State == LOW){ pixels.setPixelColor(27, pixels.Color(255,0,0)); pixels.setPixelColor(28, pixels.Color(255,0,0)); pixels.setPixelColor(29, pixels.Color(255,0,0)); } else { pixels.setPixelColor(27, pixels.Color(255,0,0)); pixels.setPixelColor(28, pixels.Color(255,0,0)); pixels.setPixelColor(29, pixels.Color(255,0,0)); } pixels.show(); SwitchPinCount = SwitchPin1State + SwitchPin2State + SwitchPin3State + SwitchPin5State + SwitchPin6State + SwitchPin8State + SwitchPin9State + SwitchPin10State; Serial.println(" in State 6 "); if (SwitchPinCount == 8){ Serial.println(" 2 cups detected "); state = 2; changeTime = millis(); break; //this will leave the switch case } break;<br>
Case 7: Winning State
case 7: // !WINNER! light show for(pixelIndex=0; pixelIndex<NUMPIXELS; pixelIndex++) {//for each pixel... colorIndex = pixelIndex + factor; colorIndex = colorIndex%7; //modulud comman to rollover colorINdex pixels.setPixelColor(pixelIndex, RbArrayR[colorIndex], RbArrayG[colorIndex], RbArrayB[colorIndex]); } factor++; if(factor>= 10) { factor = 0; } pixels.show(); //send the updated pixel colors to the hardware. delay(DELAYVAL); //pause before next pass through loop Serial.println(" in State 7 "); if (millis() - changeTime > 20000) { digitalWrite(12, HIGH); break; } if (buttonState == HIGH && buttonStatePrev == LOW) { Serial.println(" game reset "); state = 1;// this will re-start the game break; //this will leave the switch case } break; } } <br>
Downloads
Initial Testing
Programs such as TinkerCad and Arduino are very useful. Throughout this project we ran tests such as:
- IR Testing: Initial IR testing
- Testing IR with Nano Arduino: https://youtu.be/vMSELmnc1aU
- Soldering neopixels in series testing: Successful soldering of neopixels
We noticed that during this stage we either burned an electrical component or we soldered something incorrectly. This is when having a multimeter came in handy to test voltages and most importantly conductivity to ensure the solder we just did was done well.
To test neopixels we used this code:
#include <Adafruit_NeoPixel.h>
#define PIN 2 // input pin Neopixel is attached to
#define NUMPIXELS 3 // number of neopixels in strip
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
int delayval = 100; // timing delay in milliseconds
int redColor = 0;
int greenColor = 0;
int blueColor = 0;
void setup() {
// Initialize the NeoPixel library.
pixels.begin();
}
void loop() {
setColor();
for (int i=0; i < NUMPIXELS; i++) {
// pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
pixels.setPixelColor(i, pixels.Color(redColor, greenColor, blueColor));
// This sends the updated pixel color to the hardware.
pixels.show();
// Delay for a period of time (in milliseconds).
delay(delayval);
}
}
// setColor()
// picks random values to set for RGB
void setColor(){
redColor = random(0, 255);
greenColor = random(0,255);
blueColor = random(0, 255);
}
To test IRs we used this code:
int IRSensor = 2; // connect ir sensor to arduino pin 2int LED = 13; // conect Led to arduino pin 13void setup(){pinMode (IRSensor, INPUT); // sensor pin INPUTpinMode (LED, OUTPUT); // Led pin OUTPUTSerial.begin(9600);}void loop(){int statusSensor = digitalRead (IRSensor);if (statusSensor == HIGH){digitalWrite(LED, HIGH); // LED HIGHSerial.println("No Cup Detected/LED High");}else{digitalWrite(LED, LOW); // LED LOWSerial.println("Cup Detected/LED LOW");}}
Power Consumption
Here are the calculations we made to ensure that we would not damage any of our electrical components
Assembly
Step 1: Once the 3D printing of all of the hexagon pods have been made, you will want to glue them all together to form a triangle.
Step 2: Hot glue the IR sensors into each hexagon pod ensuring that you are still able to place a plexiglass over the top and that a cup may still be detected. We recommend running tests during this step as well
Step 3: With the base board of your choice, connect the neopixels in series, with 3 neopixels per pod as shown in the photos above.
Step 4: Neatly and carefully place the triangle on top of the base board while also placing the wires of the IR sensors through the holes of the baseboard. Example photos are shown above.
Step 5: Begin working on the power box, that includes the buck converter, re-rack button, toggle switch, nano arduino and perf board. We recommend testing that once power is supplied to the buck converter from the batteries that at the output of the buck, you read 5V and at the input of the buck you read 7-9V. Also test that the toggle switch turns on and off the buck and nano arduino. Do not forget to include the pul down resistor on the ground of the re-rack button
Step 6: On a perf board solder the power and grounds of the IR sensors to the positive and negative side of the perf board. Be careful as to not ground any of your wires and that if there are any exposed wires, use electrical tape or heat shrink to prevent any shorting in the circuit
Step 7: Solder the digital inputs of the IR sensor to the digital in of the IR sensors
Step 8: Solder the digital input of the neopixel to the digital in of the nano arduino. We learned that neopixels can we fragile, so be gentle with them
Conclusions and Improvements
Conclusion
This project, while fun to make, was also a huge learning curve for us as this was the first time we had ever built this. We custom made the 3D prints and designed everything from scratch. We learned that wire management is very important and noticed that at the end of our project, seeing the behind the scenes of the wires was a huge rat's nest and was tough on the eyes. This project was also code heavy and used 900+ lines to create. However, overall we are very happy with the results and the hard work we put into making this project was worth it. All together it took about 2 weeks to make. We also learned the importance of buying extra parts. we definitely learned that the hard way.
Improvements
- A more intricate light show
- Make a full electronic beer pong table