Components and supplies
Rotary Encoder with Push-Button
Stepper Motor, Mini Step
Limit Switch, 5 A
Arduino Nano R3
OLED Display, Blue on Black
Apps and platforms
Arduino IDE
Project description
Code
Code for Automated Beer Pong Game
c_cpp
This is for the game, some adjustments might have to be made if using a different motor driver (TB6600) or motor with different degrees of steps.
1/* 2 * Code by Ty Palowski for Automated Beerpong Game 3 * https://youtube.com/c/typalowski 4 */ 5 6 7#include <Adafruit_GFX.h> 8#include <Adafruit_SSD1306.h> 9#include <ClickEncoder.h> 10#include <TimerOne.h> 11 12#define SCREEN_WIDTH 128 // OLED display width, in pixels 13#define SCREEN_HEIGHT 32 // OLED display height, in pixels 14 15// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) 16#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin) 17 18Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); 19 20// defines pins numbers 21const int dirPin = 2; 22const int stepPin = 4; 23const int enPin = 5; 24 25int menuitem = 1; 26int frame = 1; 27int page = 1; 28int lastMenuItem = 1; 29 30String menuItem1 = "Motor: OFF"; 31String menuItem2 = "Difficulty"; 32String menuItem3 = "Mode"; 33String menuItem4 = "Reset"; 34 35boolean motor = true; 36int stepdelay; 37 38int maxDelay = 240; 39int diffDelta = 22; 40 41String difficulty[10] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" }; 42int selectedDifficulty = 0; 43 44String mode[2] = { "EASY", "HARD"}; 45int selectedMode = 1; 46 47boolean up = false; 48boolean down = false; 49boolean middle = false; 50 51ClickEncoder *encoder; 52int16_t last, value; 53 54// '85062033-beer-pong-or-beirut-drinking-game-with-cups-with-ball-line-art-vector-icon-for-apps-and-websites-', 128x32px 55const unsigned char myBitmap [] PROGMEM = { 56 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 64 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 66 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x83, 0x83, 0x83, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 67 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 68 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 69 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x98, 0x38, 0x38, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xff, 0xff, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0xc3, 0xc3, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x83, 0x83, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0xff, 0xff, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x98, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x9c, 0x71, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x9f, 0xf1, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x90, 0x13, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x98, 0x13, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc8, 0x23, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 80 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 81 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 84 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 88}; 89 90#define home_switch 9 // Pin 9 connected to Home Switch (MicroSwitch) 91 92int direction; // Variable to set Rotation (CW-CCW) of the motor 93int steps; // Used to set HOME position after Homing is completed 94 95int fullDist = 32766; 96int halfDist = fullDist/2; 97 98 99void setup() { 100 Serial.begin(9600); 101 102 103 // Sets the two pins as Outputs 104 pinMode(stepPin,OUTPUT); 105 pinMode(dirPin,OUTPUT); 106 107 pinMode(enPin,OUTPUT); 108 digitalWrite(enPin,LOW); 109 110 111 pinMode(7,OUTPUT); 112 113 114 encoder = new ClickEncoder(A1, A0, A2); 115 encoder->setAccelerationEnabled(false); 116 117 display.begin(); 118 display.clearDisplay(); 119 120 Timer1.initialize(1000); 121 Timer1.attachInterrupt(timerIsr); 122 123 last = encoder->getValue(); 124 125 display.setRotation (2); 126 127 display.drawBitmap(0, 0, myBitmap, 128, 64, WHITE); // display.drawBitmap(x position, y position, bitmap data, bitmap width, bitmap height, color) 128 129 // Show the display buffer on the screen. 130 display.display(); 131 132 133// Start Homing procedure of Stepper Motor at startup 134Serial.println("Homing..."); 135 while (digitalRead(home_switch)) { // Do this until the switch is activated 136 digitalWrite(dirPin, HIGH); // (HIGH = anti-clockwise / LOW = clockwise) 137 digitalWrite(stepPin, HIGH); 138 delayMicroseconds(75); // Delay to slow down speed of Stepper 139 digitalWrite(stepPin, LOW); 140 delayMicroseconds(75); 141} 142 143 while (!digitalRead(home_switch)) { // Do this until the switch is not activated 144 digitalWrite(dirPin, LOW); 145 digitalWrite(stepPin, HIGH); 146 delay(5); // More delay to slow even more while moving away from switch 147 digitalWrite(stepPin, LOW); 148 delay(5); 149 } 150 151 steps=0; // Reset position variable to zero 152 153 digitalWrite(dirPin,LOW); // Enables the motor to move in a particular direction 154 // Makes 200 pulses for making one full cycle rotation 155 for(int x = 0; x < halfDist+400; x++) { 156 digitalWrite(stepPin,HIGH); 157 delayMicroseconds(50); 158 digitalWrite(stepPin,LOW); 159 delayMicroseconds(50); 160 } 161 Serial.println("Ready!"); 162 delay(1000); 163 164} 165 166void loop() { 167 168stepdelay = maxDelay - selectedDifficulty*diffDelta; 169 170 if (motor == true) 171 { 172 turnMotorOff(); 173 } 174 else 175 { 176 turnMotorOn(); 177 } 178 179 drawMenu(); 180 181 readRotaryEncoder(); 182 183 ClickEncoder::Button b = encoder->getButton(); 184 if (b != ClickEncoder::Open) { 185 switch (b) { 186 case ClickEncoder::Clicked: 187 middle=true; 188 break; 189 } 190 } 191 192 if (up && page == 1 ) //We have turned the Rotary Encoder CounterClockwise 193 { 194 up = false; 195 if(menuitem==1 && frame ==2) 196 { 197 frame--; 198 } 199 if(menuitem==2 && frame ==3) 200 { 201 frame--; 202 } 203 if(menuitem==3 && frame ==4) 204 { 205 frame--; 206 } 207 208 lastMenuItem = menuitem; 209 menuitem--; 210 if (menuitem==0) 211 { 212 menuitem=1; 213 } 214 } 215 else if (up && page == 2 && menuitem==2 ) 216 { 217 up = false; 218 selectedDifficulty--; 219 if(selectedDifficulty == -1) 220 { 221 selectedDifficulty = 9; 222 } 223 } 224 else if (up && page == 2 && menuitem==4 ) { 225 up = false; 226 } 227 else if (up && page == 2 && menuitem==3 ) { 228 up = false; 229 selectedMode--; 230 if(selectedMode == -1) 231 { 232 selectedMode = 1; 233 } 234 } 235 236 if (down && page == 1) //We have turned the Rotary Encoder Clockwise 237 { 238 239 down = false; 240 if(menuitem==2 && lastMenuItem == 1) 241 { 242 frame ++; 243 } 244 else if(menuitem==3 && lastMenuItem == 2) 245 { 246 frame ++; 247 } 248 else if(menuitem==4 && lastMenuItem == 3 && frame!=3) 249 { 250 frame ++; 251 } 252 lastMenuItem = menuitem; 253 menuitem++; 254 if (menuitem==5) 255 { 256 menuitem--; 257 } 258 } 259 else if (down && page == 2 && menuitem==2 ) { 260 down = false; 261 selectedDifficulty++; 262 if(selectedDifficulty == 10) 263 { 264 selectedDifficulty = 0; 265 } 266 } 267 else if (down && page == 2 && menuitem==3 ) { 268 down = false; 269 selectedMode++; 270 if(selectedMode == 2) 271 { 272 selectedMode = 0; 273 } 274 } 275 276 if (middle) //Middle Button is Pressed 277 { 278 middle = false; 279 280 if (page == 1 && menuitem==1) // Motor Control 281 { 282 if (motor) 283 { 284 menuItem1 = "Motor: ON"; 285 motor = false; 286 turnMotorOff(); 287 //Left to Center 288 digitalWrite(dirPin,LOW); // Enables the motor to move in a particular direction 289 for(int x = 0; x < halfDist; x++) { 290 digitalWrite(stepPin,HIGH); 291 delayMicroseconds(stepdelay); 292 digitalWrite(stepPin,LOW); 293 delayMicroseconds(stepdelay); 294 } 295 } 296 else 297 { 298 menuItem1 = "Motor: OFF"; 299 motor = true; 300 turnMotorOn(); 301 //Center to Right 302 digitalWrite(dirPin,HIGH); // Enables the motor to move in a particular direction 303 for(int x = 0; x < halfDist; x++) { 304 digitalWrite(stepPin,HIGH); 305 delayMicroseconds(stepdelay); 306 digitalWrite(stepPin,LOW); 307 delayMicroseconds(stepdelay); 308 } 309 } 310 } 311 312 if(page == 1 && menuitem ==4)// Reset 313 { 314 resetDefaults(); 315 } 316 else if (page == 1 && menuitem==2) { 317 page=2; 318 } 319 else if (page == 1 && menuitem==3) { 320 page=2; 321 } 322 else if (page == 2) 323 { 324 page=1; 325 } 326 } 327 } 328 329 void drawMenu() 330 { 331 332 if (page==1) 333 { 334 display.setTextSize(1); 335 display.clearDisplay(); 336 display.setTextColor(WHITE, BLACK); 337 display.setCursor(15, 0); 338 display.print("MAIN MENU"); 339 display.drawFastHLine(0,10,128,WHITE); 340 341 if(menuitem==1 && frame ==1) 342 { 343 displayMenuItem(menuItem1, 15,true); //FRAME 1 344 displayMenuItem(menuItem2, 25,false); 345 } 346 else if(menuitem == 2 && frame == 1) 347 { 348 displayMenuItem(menuItem1, 15,false); 349 displayMenuItem(menuItem2, 25,true); 350 } 351 else if(menuitem == 3 && frame == 2) 352 { 353 displayMenuItem(menuItem2, 15,false); //FRAME 2 354 displayMenuItem(menuItem3, 25,true); 355 } 356 357 else if(menuitem == 2 && frame == 2) 358 { 359 displayMenuItem(menuItem2, 15,true); 360 displayMenuItem(menuItem3, 25,false); 361 } 362 else if(menuitem == 4 && frame == 3) 363 { 364 displayMenuItem(menuItem3, 15,false); //FRAME 3 365 displayMenuItem(menuItem4, 25,true); 366 } 367 368 else if(menuitem == 3 && frame == 3) 369 { 370 displayMenuItem(menuItem3, 15,true); 371 displayMenuItem(menuItem4, 25,false); 372 } 373 else if(menuitem == 2 && frame == 3) 374 { 375 displayMenuItem(menuItem2, 15,true); //FRAME 2 376 displayMenuItem(menuItem3, 25,false); 377 } 378 else if(menuitem == 1 && frame == 2) 379 { 380 displayMenuItem(menuItem1, 15,true); //FRAME 1 381 displayMenuItem(menuItem2, 25,false); 382 } 383 display.display(); 384 } 385 else if (page==2 && menuitem == 2) 386 { 387 displayStringMenuPage(menuItem2, difficulty[selectedDifficulty]); 388 } 389 else if (page==2 && menuitem == 3) 390 { 391 displayStringMenuPage(menuItem3, mode[selectedMode]); 392 } 393 } 394 395 396 void resetDefaults() 397 { 398 selectedDifficulty = 0; 399 selectedMode = 0; 400 motor = true; 401 menuItem1 = "Motor: OFF";// Start Homing procedure of Stepper Motor at startup 402 403 while (digitalRead(home_switch)) { // Do this until the switch is activated 404 digitalWrite(dirPin, HIGH); // (HIGH = anti-clockwise / LOW = clockwise) 405 digitalWrite(stepPin, HIGH); 406 delayMicroseconds(75); // Delay to slow down speed of Stepper 407 digitalWrite(stepPin, LOW); 408 delayMicroseconds(75); 409} 410 411 while (!digitalRead(home_switch)) { // Do this until the switch is not activated 412 digitalWrite(dirPin, LOW); 413 digitalWrite(stepPin, HIGH); 414 delay(5); // More delay to slow even more while moving away from switch 415 digitalWrite(stepPin, LOW); 416 delay(5); 417 } 418 419 steps=0; // Reset position variable to zero 420 421 digitalWrite(dirPin,LOW); // Enables the motor to move in a particular direction 422 for(int x = 0; x < halfDist+400; x++) { 423 digitalWrite(stepPin,HIGH); 424 delayMicroseconds(50); 425 digitalWrite(stepPin,LOW); 426 delayMicroseconds(50); 427 } 428 } 429 430 void setstepdelay() 431 { 432 // display.setContrast(contrast); 433 display.display(); 434 } 435 436 void turnMotorOn() 437 { 438//Left limit to Right Limit 439 digitalWrite(dirPin,HIGH); 440 for(int x = 0; x < fullDist; x++) { 441 digitalWrite(stepPin,HIGH); 442 delayMicroseconds(stepdelay); 443 digitalWrite(stepPin,LOW); 444 delayMicroseconds(stepdelay); 445 } 446//Right limit to Left 447 digitalWrite(dirPin,LOW); 448 for(int x = 0; x < fullDist; x++) { 449 digitalWrite(stepPin,HIGH); 450 delayMicroseconds(stepdelay); 451 digitalWrite(stepPin,LOW); 452 delayMicroseconds(stepdelay); 453 } 454 } 455 456 void turnMotorOff() 457 { 458 digitalWrite(7,HIGH); 459 } 460 461 void timerIsr() { 462 encoder->service(); 463} 464 465void displayIntMenuPage(String menuItem, int value) 466{ 467 display.setTextSize(1); 468 display.clearDisplay(); 469 display.setTextColor(WHITE, BLACK); 470 display.setCursor(10, 0); 471 display.print(menuItem); 472 display.drawFastHLine(0,10,80,WHITE); 473 display.setCursor(5, 15); 474 display.print("Value"); 475 display.setTextSize(2); 476 display.setCursor(80, 10); 477 display.print(value); 478 display.setTextSize(2); 479 display.display(); 480} 481 482void displayStringMenuPage(String menuItem, String value) 483{ 484 display.setTextSize(2); 485 display.clearDisplay(); 486 display.setTextColor(WHITE, BLACK); 487 display.setCursor(0, 0); 488 display.print(menuItem); 489 display.setCursor(50, 15); 490 display.print(value); 491 display.setTextSize(2); 492 display.display(); 493} 494 495void displayMenuItem(String item, int position, boolean selected) 496{ 497 if(selected) 498 { 499 display.setTextColor(BLACK, WHITE); 500 }else 501 { 502 display.setTextColor(WHITE, BLACK); 503 } 504 display.setCursor(0, position); 505 display.print(">"+item); 506} 507 508void readRotaryEncoder() 509{ 510 value += encoder->getValue(); 511 512 if (value/2 > last) { 513 last = value/2; 514 down = true; 515 delay(150); 516 }else if (value/2 < last) { 517 last = value/2; 518 up = true; 519 delay(150); 520 } 521}
Downloadable files
Wiring Schedule for Components
Works with Arduino Uno and Nano. Needs 12V supply and 5V to power motor driver and Arduino, respectively.
Wiring Schedule for Components
Wiring Schedule for Components
Works with Arduino Uno and Nano. Needs 12V supply and 5V to power motor driver and Arduino, respectively.
Wiring Schedule for Components
Documentation
Magnet Shuttle
Magnet shuttle which fits ontop of AL202 Slider
Magnet Shuttle
Stepper Motor Holder
Holds stepper motor and AL2020 rail.
Stepper Motor Holder
Magnet Shuttle
Magnet shuttle which fits ontop of AL202 Slider
Magnet Shuttle
Stepper Motor Holder
Holds stepper motor and AL2020 rail.
Stepper Motor Holder
Limit Switch Holder
Holds limit switch and AL2020 Rail
Limit Switch Holder
Limit Switch Holder
Holds limit switch and AL2020 Rail
Limit Switch Holder
Comments
Only logged in users can leave comments