Introduction: Arduino Basketball Pop-a-Shot: Upgrayedd

Picture of Arduino Basketball Pop-a-Shot: Upgrayedd

I saw the Instructable Arduino Home Basketball Hoop Score Detection System a.k.a. Scorekeeper by ohoilett (thank you for your contribution and inspiration) and really liked what he had going on, but wanted a cleaner version to use as a prize for a pop-a-shot tournament at an event for work. Thus came the upgrayedd, chock full of electrolytes. If you haven't seen the movie Idiocracy, do yourself a favor and put it on the watch list. It will scare the bejeezus out of you.

Step 1: Parts List

Picture of Parts List

SKLZ Pro Mini Hoop (Any indoor hoop will work.)

Arduino Micro

Digital Distance Sensor

Quad Alphanumeric Display

Perma-Proto Half-Sized Breadboard

Enercell Micro USB Charger (Any 5v USB power stick/charger made for a smartphone will work. Make sure the amperage is congruent with your project's draw.)

3-Pin Female to Female Servo Extension (I found one at Microcenter. This one is too short - should be closer to 6")

1/4" & 1/8" thick Acrylic (at any Lowes or Home Depot)

Step 2: Prototyping

Picture of Prototyping

Taking ohoilette's concept, I identified that I wanted a basketball hoop that had a visible score displayed, controlled by an Arduino and triggered by a distance sensor focused on the net.

Scaling down the individually mapped LED segments to a quad alphanumeric display with an IC2 backpack from Adafruit made the coding easier and looked sharper than anything I would make from scratch. I really wanted to use a Trinket instead of the Micro, but I couldn't get my sketch small enough to fit on the Trinket. Regardless, downsizing to the Micro made the possibility of fitting it all into a half-sized breadboard a reality. I almost went with the ultrasonic distance sensor until I saw the Sharp digital sensor listed in my parts list. It's much smaller and gets the basic job of motion detection done efficiently.

I created the breadboard schematic above with Fritzing, but here are the connections I used:

  • Arduino
    • 5v > 5v rail
    • GND > GND rail
    • A0 > distance sensor (out)
    • 2/SDA > alpha SDA
    • 3/SCL > alpha SCL
  • Display Sensor
    • OUT > adruino A0
    • VIN > 5v rail
    • GND > GND rail
  • Alphanumeric Display
    • Vi2C > 5v rail
    • VCC > 5v rail
    • GND >GND rail
    • SDA > adrunio 2/SDA
    • SCL > adruino 3/SCL

Code-wise, I created an integer called Score that is always displayed on the alpha display. Every time the distance sensor is tripped, 1 is added to the integer count, thereby updating the score on the display. Here is the sketch:

//include libraries
#include #include "Adafruit_LEDBackpack.h" #include "Adafruit_GFX.h"

//create Adafruit Alphanumeric Display object Adafruit_AlphaNum4 alpha4 = Adafruit_AlphaNum4();

//define integer int score = 0;

void setup() { //set sensor pin to INPUT pinMode(A0, INPUT); //set BAUD rate Serial.begin(9600); //start display alpha4.begin(0x70); //write zeros to all positions alpha4.writeDigitAscii(0, '0'); alpha4.writeDigitAscii(1, '0'); alpha4.writeDigitAscii(2, '0'); alpha4.writeDigitAscii(3, '0'); //display newly written values alpha4.writeDisplay();
}

void loop() {

//add 1 to the score if sensor voltage is LOW if (analogRead(A0) < 200) { score++; //write score to display data alpha4.writeDigitAscii(3, (score%10) + '0'); alpha4.writeDigitAscii(2, (score%100/10) + '0'); alpha4.writeDigitAscii(1, (score%1000/100) + '0'); alpha4.writeDigitAscii(0, (score/1000) + '0'); //push display data to display alpha4.writeDisplay(); //wait 1.5 sec to eliminate phantom reads delay(1500); }
}

After all that tested properly, I soldered the components to a half-sized breadboard for mounting to the backboard.

Step 3: Case Construction

Picture of Case Construction

I wanted to enclose the unit in plexiglass to help guard from damage and dust. We purchased a sheet of 1/4" and 1/8" thick acrylic. The 1/4" pieces were used to create the walls and the 1/8" piece for the front of the case. Pieces were cut to size with a table saw, then the edges finished with a propane torch.

We couldn't find any acrylic glue, so we went with small screws to connect the walls and lid of the case, as well to secure the full box to the backboard. Using helicoils would have been ideal here, but the pilot holes were small enough to allow for good grip for the screws.

Small notches were put in each side wall with a router to allow access for the distance sensor and Arduino power cables.

Step 4: Mounting

Picture of Mounting

Double-sided Loctite tape was used on the back of the proto board to secure it to the backboard. The acrylic case was laid on top of that and holes were drilled with a drill press to allow connection with screws from behind the backboard.

The battery pack was affixed to the back of the backboard, directly behind the proto board with the same Loctite tape.

We took a small piece of acrylic and put a groove in it with the table saw, which was then super glued to the rim. Another piece of Loctite tape was used on the back of the distance sensor to secure it to the new tab. It was important to make sure the sensor sat low enough to look though a hole in the net, opposed to directly at the rope.

Step 5: Final Testing

This worked on the first test, which was pretty awesome! I was concerned about the net movement giving false readings to the sensor, but I wasn't able to create an erroneous score even with rim shots and air balls. I give credit to the sensor placement in relation to the holes in the net.

The unit is powered on and off by plugging the usb cable into the Arduino (or from the battery pack side.) That pack runs off of 2 AA batteries, and I let it go with a constant count running for around 3 hours without it dying. I'm not sure of the total life, but it ran long enough for me to be comfortable with that power solution. A rechargeable usb power stick would be more efficient.

Overall a fun project and I am happy with the final product. Hopefully it is appreciated by whomever wins it!

Comments

Afitz105 made it! (author)2015-03-23

I added a buzzer that plays a three tone start, an IR sensor so I can use a remote to restart the game, 2 segments countdown from 60 seconds, 2 segments keep track of score, and at the end of the game it displays "Your", "Scor", then the score and then it displays "High", "Scor", then the high score. Also my LEDs are blue. I'm going to add more functionality with the remote such as being able to enter 3 digit initials for the high score. Thanks so much for posting this project.

maadams7712 (author)Afitz1052016-10-26

This is awesome! Did you ever finish the advanced upgrade version your describing above? If so is it available for purchase or do you mind sharing your designs?

ohoilett (author)2016-06-25

Wow, just saw this. Glad I could be of some inspiration!
And incredibly sleek design. I love it.

phrazelle (author)2015-03-24

Awesome! I'd love to see your sketch on all of that. I have a few other projects slowly coming together, but I put a more "gamified" concept of this together that I hope to do later in the year.

netrix (author)phrazelle2015-09-04

Did you ever had any time to work on this version? I ordered some parts and might try to do something like that in the next couple of months.

Afitz105 (author)phrazelle2015-03-30

I've also 3d printed a case for the sensor and the arduino. I just need to redesign my case so it holds a 9v battery and has a barrel plug to plug into the wall. I'm currently working a frame and get some netting and canvas together to make it pop. I'm probably going to separate the time and score and add a second hoop. I'll keep you posted on the progress and hopefully it will be done by the end of May.

Afitz105 (author)phrazelle2015-03-30

//Remote

#include <IRremote.h>

//Include libraries

//Sound

#include <toneAC.h>

#include "pitches.h"

//start music

int melody[] = {NOTE_A3, NOTE_A3, NOTE_E6};

int noteDurations[] = { 2, 2, 2};

//Display

#include <Wire.h>

#include "Adafruit_LEDBackpack.h"

#include "Adafruit_GFX.h"

//Remote

int RECV_PIN = 5;

IRrecv irrecv(RECV_PIN);

decode_results results;

//create Adafruit Alphanumeric Display object

Adafruit_AlphaNum4 alpha4 = Adafruit_AlphaNum4();

//define integer

int score = 0;

int highscore =0;

int seconds =45;

//define clock check

long cPreviousMillis=0;

long cInterval = 1000;

//distance sensor check

long pPreviousMillis=0;

long pInterval = 500;

bool pointsCheck;

//Displays scrolling text

void displayText(){

char Text[1];

int count = sizeof(Text)/sizeof(Text[0]);

//Display press

for(int j=0; j<=3; j++){

for(int i =0; i<=count/2+1; i++){

alpha4.writeDigitAscii(0, Text[i]);

alpha4.writeDigitAscii(1, Text[i+1]);

alpha4.writeDigitAscii(2, Text[i+2]);

alpha4.writeDigitAscii(3, Text[i+3]);

//display newly written values

alpha4.writeDisplay();

delay(500);

}

}

}

//reset score function

void resetScore(){

bool start = false;

results.value=0;

while(start==false){

//Display press

alpha4.writeDigitAscii(0, 'P');

alpha4.writeDigitAscii(1, 'L');

alpha4.writeDigitAscii(2, 'A');

alpha4.writeDigitAscii(3, 'Y');

//display newly written values

alpha4.writeDisplay();

//Remote press play to reset

if (irrecv.decode(&results))

{

irrecv.resume(); // Receive the next value

}

if (results.value == 16761405) // change zero to your IR remote button number

{

start=true;

alpha4.writeDigitAscii(0, '4');

alpha4.writeDigitAscii(1, '5');

alpha4.writeDigitAscii(2, '0');

alpha4.writeDigitAscii(3, '0');

alpha4.writeDisplay();

delay(100); // keeps the transistion smooth

}

}

//Reset score

score = 0;

seconds=45;

//Intro Beep

for (int thisNote = 0; thisNote < 3; thisNote++) {

int noteDuration = 1000/noteDurations[thisNote];

toneAC(melody[thisNote], 10, noteDuration, true); // Play thisNote at full volume for noteDuration in the background.

delay(noteDuration * 4 / 3); // Wait while the tone plays in the background, plus another 33% delay between notes.

}

}

void setup() {

//start IR receiver

irrecv.enableIRIn(); // Start the receiver

//set sensor pin to INPUT

pinMode(A0, INPUT);

//set BAUD rate

Serial.begin(9600);

//start IR receiver

irrecv.enableIRIn(); // Start the receiver

//start display

alpha4.begin(0x70);

//write zeros to all positions

alpha4.writeDigitAscii(0, '0');

alpha4.writeDigitAscii(1, '0');

alpha4.writeDigitAscii(2, '0');

alpha4.writeDigitAscii(3, '0');

//display newly written values

alpha4.writeDisplay();

}

void loop() {

unsigned long cCurrentMillis = millis(); //time keeping timer

unsigned long pCurrentMillis = millis(); //time keeping points

//Remote press play to reset

if (irrecv.decode(&results))

{

irrecv.resume(); // Receive the next value

}

if (results.value == 16761405) // change zero to your IR remote button number

{

resetScore();

delay(100); // keeps the transistion smooth

}

if (cCurrentMillis - cPreviousMillis > cInterval) {

cPreviousMillis = cCurrentMillis;

alpha4.writeDigitAscii(1,(seconds%10) + '0');

alpha4.writeDigitAscii(0, (seconds%100/10) + '0');

seconds--;

alpha4.writeDisplay();

}

if ((analogRead(A0) < 200) & (pointsCheck==false)){score++; pointsCheck=true;

alpha4.writeDigitAscii(3, (score%10) + '0');

alpha4.writeDigitAscii(2, (score%100/10) + '0');

//push display data to display

alpha4.writeDisplay();

}

if (pCurrentMillis - pPreviousMillis > pInterval) {

pPreviousMillis = pCurrentMillis;

pointsCheck = false;

}

//End of Game

//Display player score

if(seconds == 0){

delay(500);

//Game Over Beep

int noteDuration = 1000/2;

toneAC(NOTE_A3, 10, noteDuration, true); // Play thisNote at full volume for noteDuration in the background.

delay(noteDuration * 4 / 3); // Wait while the tone plays in the background, plus another 33% delay between notes.

for(int i=0; i<=9; i++){

if (i%4==0){

alpha4.writeDigitAscii(0, 'Y');

alpha4.writeDigitAscii(1, 'O');

alpha4.writeDigitAscii(2, 'U');

alpha4.writeDigitAscii(3, 'R');

//push display data to display

alpha4.writeDisplay();

}

if (i%4==1){

alpha4.writeDigitAscii(0, 'S');

alpha4.writeDigitAscii(1, 'C');

alpha4.writeDigitAscii(2, 'O');

alpha4.writeDigitAscii(3, 'R');

//push display data to display

alpha4.writeDisplay();

}

if (i%4==2){

alpha4.writeDigitAscii(0, 'C');

alpha4.writeDigitAscii(3, 'E');

alpha4.writeDigitAscii(2, 'R');

alpha4.writeDigitAscii(1, 'O');

//push display data to display

alpha4.writeDisplay();

}

if (i%4==3){

alpha4.writeDigitAscii(0, '*');

alpha4.writeDigitAscii(3, '*');

alpha4.writeDigitAscii(2, (score%10) + '0');

alpha4.writeDigitAscii(1, (score%100/10) + '0');

//push display data to display

alpha4.writeDisplay();

}

delay(750);

}

//Display High Score

if (score > highscore){highscore = score;}

for(int i=0; i<=9; i++){

if (i%4==0){

alpha4.writeDigitAscii(0, 'H');

alpha4.writeDigitAscii(1, 'I');

alpha4.writeDigitAscii(2, 'G');

alpha4.writeDigitAscii(3, 'H');

//push display data to display

alpha4.writeDisplay();

}

if (i%4==1){

alpha4.writeDigitAscii(0, 'S');

alpha4.writeDigitAscii(1, 'C');

alpha4.writeDigitAscii(2, 'O');

alpha4.writeDigitAscii(3, 'R');

//push display data to display

alpha4.writeDisplay();

}

if (i%4==2){

alpha4.writeDigitAscii(0, 'C');

alpha4.writeDigitAscii(3, 'E');

alpha4.writeDigitAscii(2, 'R');

alpha4.writeDigitAscii(1, 'O');

//push display data to display

alpha4.writeDisplay();

}

if (i%4==3){

alpha4.writeDigitAscii(0, '*');

alpha4.writeDigitAscii(3, '*');

alpha4.writeDigitAscii(2, (highscore%10) + '0');

alpha4.writeDigitAscii(1, (highscore%100/10) + '0');

//push display data to display

alpha4.writeDisplay();

}

delay(750);

}

resetScore();

}

}

parthew (author)2015-08-28

This is awesome! I am currently building this and have run into a weird issue....it doesn't count when the ball passes by the sensor. Literally anything else I throw through the hoop will add to the score but the ball does not. Is there a solution to this or am I doing something wrong?

phrazelle (author)parthew2015-08-31

I would try moving the distance sensor closer to the net and see if that helps. An object is an object and if it is registering for certain things then it is technically working.

phrazelle (author)phrazelle2015-08-31

Or just make sure the sensor isn't obstructed at all. That sensor is a fixed distance of 100mm, I believe...

parthew (author)phrazelle2015-09-03

Yeah, I actually moved the sensor inside the net just to test it (by dropping the ball past the sensor) and it still isn't picking it up. It picks up pretty much anything else I toss through there except for the basketball. Odd.

Curtis R.S (author)2015-05-27

Absolutely thrilled to see this! I'm extremely curios to see that if I pay you can you build me one similar to this except for when the sensor is "tripped" it activates the "ENTER Button" on my keyboard computer....so everytime a basketball goes thru the hoop the "ENTER" key is pressed. Please give me your thought as soon as you get a chance. I'd love to chat.

God Bless,
Curtis

phrazelle (author)2015-03-24

General concept is a more true-to-life pop-a-shot. Scope of the game is 2 players, 3, 30 second rounds, person with the highest total score after all 3 rounds is the winner.

There will be a larger alphanumeric display at the top middle of the board to act as a countdown timer. Under this will be 3 LEDs displaying which round of 3 is currently being played. Each player's score is displayed on each side of the board, along with LEDs showing if it is their turn or not (green on means that player's turn.)

On the side of the board will be a panel that not only holds the micro-controllers, but also provides an interface to power on, change the game mode, turn the sound on and off, and reset the game.

Player turns the board on via the side panel and selects game mode. Free Play activates the Player 1 score count into infinity without a timer - essentially what is built now. 1-On-1 activates the 3 round mode with countdown timer.

To begin a 1-On-1 game, the first player will hit the red Start button next to their score display, triggering a 5 second countdown on the main timer that leads into Player 1's first 30 second round. Shots are counted via the distance sensor and added to current player's score only while the countdown timer is active. During the last 5 seconds of a round, a red LED next to the timer flashes each second and a countdown beep happens up until a buzzer sound at zero. Green player status LED changes to next player at this point. Player 2 hits the red Start button next to their score display and the process repeats.

After the 3rd round is complete, the player with the highest score is the winner and their side blinks, victory sound goes off, etc. Possible shot-for-shot sudden death in the instance of a tie.

KOTSOS5 (author)phrazelle2015-03-27

Hi your project look great, but with the update you intend to do, you are going to next level, I'll be watching you, so I can see when the new project is ready. If you want have a look here :

https://plus.google.com/109652469005118520122/posts/SmmDEMmihpT It's a site from an Italian guy, maybe you can get some ideas cause he provides all kind of information for his project.

About This Instructable

13,319views

24favorites

License:

Bio: I love playing with random things to make random stuff!
More by phrazelle:Reclaimed Pallet Wood Sandwich BoardOrnate Magic MirrorSteampunk Raspberry Pi Laptop
Add instructable to: