Marcelo Ávila de Oliveira
Published © GPL3+

Smart Basketball Scoreboard

What if an Arduino/Android solution was added to a regular basketball board to track my basketball training workouts? Let's go for it!

IntermediateFull instructions provided24 hours5,731
Smart Basketball Scoreboard

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
×1
HC-05 Bluetooth Module
HC-05 Bluetooth Module
×1
E18-D80NK Infrared Proximity Sensor
×1
Grove - Vibration Sensor (SW-420)
Seeed Grove - Vibration Sensor (SW-420)
×1
DHT22 Temperature Sensor
DHT22 Temperature Sensor
×1
8mm RGB LED
×1
Resistor 10k ohm
Resistor 10k ohm
×3
Resistor 100 ohm
Resistor 100 ohm
×3
Through Hole Resistor, 47 ohm
Through Hole Resistor, 47 ohm
×1
Resistor 1k ohm
Resistor 1k ohm
×1
Resistor 2.21k ohm
Resistor 2.21k ohm
×1
9V battery (generic)
9V battery (generic)
×1

Software apps and online services

Arduino IDE
Arduino IDE
MIT App Inventor Android IDE

Story

Read more

Schematics

Arduino schematics (1.1.0)

Arduino schematics (2.0.0)

Code

Arduino code (1.1.0)

Arduino
//----------------------------------------------------------------------------//
// Filename    : Scoreboard.ino                                               //
// Description : Smart Basketball Scoreboard                                  //
// Version     : 1.1.0                                                        //
// Author      : Marcelo Avila de Oliveira <marceloavilaoliveira@gmail.com>   //
//----------------------------------------------------------------------------//

//----------------------------------------------------------------------------//
// DEFINITIONS                                                                //
//----------------------------------------------------------------------------//

// TURN ON DEBUG MODE
// #define DEBUG
// #define DEBUG_PROX
// #define DEBUG_VIBR

//----------------------------------------------------------------------------//
// CONSTANTS                                                                  //
//----------------------------------------------------------------------------//

// PINS
const int prox_pin = 2;
const int vibr_pin = 3;
const int led_r_pin = 4;
const int led_g_pin = 5;
const int led_b_pin = 6;

// TIME
const unsigned long wait_interval = 3000;

// MATH
const float percent_to_bright_factor = 100 * log10(2) / log10(255);

//----------------------------------------------------------------------------//
// VARIABLES                                                                  //
//----------------------------------------------------------------------------//

// TIME
unsigned long wait_time;

// STATUS
boolean prox = false;
boolean vibr = false;
boolean wait = false;

//----------------------------------------------------------------------------//
// FUNCTIONS (SETTINGS)                                                       //
//----------------------------------------------------------------------------//

void setup() {
    // INITIATE PINS
    pinMode(prox_pin, INPUT);
    pinMode(vibr_pin, INPUT);
    pinMode(led_r_pin, OUTPUT);
    pinMode(led_g_pin, OUTPUT);
    pinMode(led_b_pin, OUTPUT);

    set_led(5, 100);

    // INITIATE SERIAL COMMUNICATION
    Serial.begin(9600);

    // INITIATE BLUETOOTH COMMUNICATION
    setup_bluetooth();

    set_led(4, 100);

    #ifdef DEBUG
        Serial.println("Board is alive");
        Serial.println();
    #endif
}

void setup_bluetooth() {
    #ifdef DEBUG
        Serial.println("Setting Bluetooth");
        Serial.println();
    #endif

    Serial1.begin(38400);                   // Set baud rate
    Serial1.print("\r\n+STWMOD=0\r\n");     // Set to work in slave mode
    Serial1.print("\r\n+STNA=Arduino\r\n"); // Set name
    Serial1.print("\r\n+STOAUT=1\r\n");     // Permit Paired device to connect me
    Serial1.print("\r\n+STAUTO=0\r\n");     // Auto-connection should be forbidden here
    delay(2000);                            // This delay is required.
    Serial1.print("\r\n+INQ=1\r\n");        // Make the slave inquirable 
    delay(2000);                            // This delay is required.
    while (Serial1.available()) {           // Clear data
        delay(50);
        Serial1.read();
    }
}

//----------------------------------------------------------------------------//
// FUNCTIONS (LIGHT)                                                          //
//----------------------------------------------------------------------------//

int percent_to_bright(int percent) {
    // PERCENT:
    // 0..100
    // RETURN BRIGHT
    // 255..0

    return 256 - pow(2, percent / percent_to_bright_factor);
}

void set_led(int color, int bright) {
    // COLOR:
    // 0 = GREEN
    // 1 = YELLOW  
    // 2 = RED
    // 3 = CYAN
    // 4 = BLUE
    // 5 = MAGENTA
    // 6 = WHITE
    //
    // BRIGHT:
    // 0 = OFF
    // ..
    // 100 = MAX

    #ifdef DEBUG
        Serial.println("Setting LED");
        Serial.println();
    #endif

    if (color < 0 || color > 6 || bright < 0 || bright > 100) {
        return;
    }

    int led_r_bright = 255;
    int led_g_bright = 255;
    int led_b_bright = 255;
    int bright_aux = percent_to_bright(bright);

    switch (color) {
        case 0:
            // GREEN
            led_g_bright = bright_aux;
            break;
        case 1:
            // YELLOW
            led_r_bright = bright_aux;
            led_g_bright = bright_aux;
            break;
        case 2:
            // RED
            led_r_bright = bright_aux;
            break;
        case 3:
            // CYAN
            led_g_bright = bright_aux;
            led_b_bright = bright_aux;
            break;
        case 4:
            // BLUE
            led_b_bright = bright_aux;
            break;
        case 5:
            // MAGENTA
            led_r_bright = bright_aux;
            led_b_bright = bright_aux;
            break;
        case 6:
            // WHITE
            led_r_bright = bright_aux;
            led_g_bright = bright_aux;
            led_b_bright = bright_aux;
            break;
    }

    analogWrite(led_r_pin, led_r_bright);
    analogWrite(led_g_pin, led_g_bright);
    analogWrite(led_b_pin, led_b_bright);

    return;
}

//----------------------------------------------------------------------------//
// FUNCTIONS (CHECK)                                                          //
//----------------------------------------------------------------------------//

void check_prox() {
    if (!prox) {
        if(digitalRead(prox_pin) == LOW) {
            #ifdef DEBUG_PROX
                Serial.println("Proximity detected");
                Serial.println();
            #endif

            prox = true;
            if (!vibr) {
                wait = true;
                wait_time = millis() + wait_interval;
            }
            set_shot(1);
        }
    }
}

void check_vibr() {
    if (!prox && !vibr) {
        if(digitalRead(vibr_pin) == HIGH) {
            #ifdef DEBUG_PROX
                Serial.println("Vibration detected");
                Serial.println();
            #endif

            vibr = true;
            wait = true;
            wait_time = millis() + wait_interval;
            set_led(1, 100);
        }
    }
}

void check_wait() {
    if (wait && millis() > wait_time) {
        if (!prox) {
            set_shot(0);
        }

        reset();
    }
}

//----------------------------------------------------------------------------//
// FUNCTIONS (MIS)                                                            //
//----------------------------------------------------------------------------//

void set_shot(int mode) {
    // MODE:
    // 0 = WRONG SHOT (MISS)
    // 1 = RIGHT SHOT (SCORE)

    if (mode == 0) {
        set_led(2, 100);
    } else {
        set_led(0, 100);
    }

    Serial1.print(mode);
    delay(1000);
}

void reset() {
    vibr = false;
    prox = false;
    wait = false;
    set_led(4, 100);
}

//----------------------------------------------------------------------------//
// MAIN                                                                       //
//----------------------------------------------------------------------------//

void loop() {
    check_prox();
    check_vibr();
    check_wait();
}

Android code (1.1.0)

Java
Android MIT App Inventor (http://ai2.appinventor.mit.edu/)
No preview (download only).

Arduino code (2.0.0)

Arduino
//----------------------------------------------------------------------------//
// Filename    : Scoreboard.ino                                               //
// Description : Smart Basketball Scoreboard                                  //
// Version     : 2.0.0                                                        //
// Author      : Marcelo Avila de Oliveira <marceloavilaoliveira@gmail.com>   //
//----------------------------------------------------------------------------//

//----------------------------------------------------------------------------//
// LIBRARIES                                                                  //
//----------------------------------------------------------------------------//

// TEMPERATURE & HUMIDITY LIBRARY
#include "DHT.h"
// MULTI SERIAL LIBRARY
#include "SoftwareSerial.h"

//----------------------------------------------------------------------------//
// DEFINITIONS                                                                //
//----------------------------------------------------------------------------//

// TURN ON DEBUG MODE
// #define DEBUG
// #define DEBUG_BLUE
// #define DEBUG_PROX
// #define DEBUG_VIBR
// #define DEBUG_DHT

// DHT SENSOR
#define DHTPIN 7
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

// BLUETOOTH MODULE (RX, TX)
SoftwareSerial Bluetooth(10, 11);

//----------------------------------------------------------------------------//
// CONSTANTS                                                                  //
//----------------------------------------------------------------------------//

// PINS
const int prox_pin = 2;
const int vibr_pin = 3;
const int led_r_pin = 4;
const int led_g_pin = 5;
const int led_b_pin = 6;

// TIME
const unsigned long wait_interval = 2000;
const unsigned long dht_interval = 10000;

// MATH
const float percent_to_bright_factor = 100 * log10(2) / log10(255);

//----------------------------------------------------------------------------//
// VARIABLES                                                                  //
//----------------------------------------------------------------------------//

// TIME
unsigned long wait_time;
unsigned long dht_time;

// HUMIDITY & TEMPERATURE
float humi, temp, heat;

// STATUS
boolean prox = false;
boolean vibr = false;
boolean wait = false;

//----------------------------------------------------------------------------//
// FUNCTIONS (SETTINGS)                                                       //
//----------------------------------------------------------------------------//

void setup() {
    // INITIATE PINS
    pinMode(prox_pin, INPUT);
    pinMode(vibr_pin, INPUT);
    pinMode(led_r_pin, OUTPUT);
    pinMode(led_g_pin, OUTPUT);
    pinMode(led_b_pin, OUTPUT);

    // SET LED MAGENTA
    set_led(5, 100);

    // INITIATE SERIAL COMMUNICATION
    Serial.begin(9600);

    // INITIATE BLUETOOTH COMMUNICATION
    setup_bluetooth();

    // INITIATE DHT SENSOR
    dht.begin();

    // SET LED BLUE
    set_led(4, 100);

    #ifdef DEBUG
        Serial.println("Board is alive");
        Serial.println();
    #endif
}

void setup_bluetooth() {
    #ifdef DEBUG_BLUE
        Serial.println("Setting Bluetooth");
        Serial.println();
    #endif

    // SET BAUD RATE
    Bluetooth.begin(9600);
    // CLEAR ANY AVAILABLE DATA
    while (Bluetooth.available()) {
        delay(50);
        Bluetooth.read();
    }
}

//----------------------------------------------------------------------------//
// FUNCTIONS (LIGHT)                                                          //
//----------------------------------------------------------------------------//

int percent_to_bright(int percent) {
    // PERCENT:
    // 0..100
    // RETURN BRIGHT
    // 255..0

    return 256 - pow(2, percent / percent_to_bright_factor);
}

void set_led(int color, int bright) {
    // COLOR:
    // 0 = GREEN
    // 1 = YELLOW  
    // 2 = RED
    // 3 = CYAN
    // 4 = BLUE
    // 5 = MAGENTA
    // 6 = WHITE
    //
    // BRIGHT:
    // 0 = OFF
    // ..
    // 100 = MAX

    #ifdef DEBUG
        Serial.println("Setting LED");
        Serial.println();
    #endif

    if (color < 0 || color > 6 || bright < 0 || bright > 100) {
        return;
    }

    int led_r_bright = 255;
    int led_g_bright = 255;
    int led_b_bright = 255;
    int bright_aux = percent_to_bright(bright);

    switch (color) {
        case 0:
            // GREEN
            led_g_bright = bright_aux;
            break;
        case 1:
            // YELLOW
            led_r_bright = bright_aux;
            led_g_bright = bright_aux;
            break;
        case 2:
            // RED
            led_r_bright = bright_aux;
            break;
        case 3:
            // CYAN
            led_g_bright = bright_aux;
            led_b_bright = bright_aux;
            break;
        case 4:
            // BLUE
            led_b_bright = bright_aux;
            break;
        case 5:
            // MAGENTA
            led_r_bright = bright_aux;
            led_b_bright = bright_aux;
            break;
        case 6:
            // WHITE
            led_r_bright = bright_aux;
            led_g_bright = bright_aux;
            led_b_bright = bright_aux;
            break;
    }

    analogWrite(led_r_pin, led_r_bright);
    analogWrite(led_g_pin, led_g_bright);
    analogWrite(led_b_pin, led_b_bright);

    return;
}

//----------------------------------------------------------------------------//
// FUNCTIONS (CHECK)                                                          //
//----------------------------------------------------------------------------//

void check_prox() {
    if (!prox) {
        // CHECK PROXIMITY ONLY IF PROXIMITY WASN'T DETECTED

        if(digitalRead(prox_pin) == LOW) {
            #ifdef DEBUG_PROX
                Serial.println("Proximity detected");
                Serial.println();
            #endif

            // SET LED GREEN
            set_led(0, 100);
            send_data(2);

            prox = true;
            if (!vibr) {
                wait = true;
                wait_time = millis() + wait_interval;
            }
        }
    }
}

void check_vibr() {
    if (!prox && !vibr) {
        // CHECK VIBRATION ONLY IF PROXIMITY AND VIBRATION WEREN'T DETECTED

        if(digitalRead(vibr_pin) == HIGH) {
            #ifdef DEBUG_VIBR
                Serial.println("Vibration detected");
                Serial.println();
            #endif

            // SET LED YELLOW
            set_led(1, 100);

            vibr = true;
            wait = true;
            wait_time = millis() + wait_interval;
        }
    }
}

void check_wait() {
    if (wait && millis() > wait_time) {
        if (!prox) {
            // SET LED RED
            set_led(2, 100);
            send_data(1);
        }

        reset();
    }
}

void check_dht() {
    if (!prox && !vibr) {
        // CHECK DHT ONLY IF VIBRATION WASN'T DETECTED

        if (millis() > dht_time) {
            humi = dht.readHumidity();
            temp = dht.readTemperature();
            heat = dht.computeHeatIndex(temp, humi, false);

            #ifdef DEBUG_DHT
                Serial.print("Humidity   : ");
                Serial.print(humi);
                Serial.println("%");
                Serial.print("Temperature: ");
                Serial.print(temp);
                Serial.println("C");
                Serial.print("Head Index : ");
                Serial.print(heat);
                Serial.println("C");
                Serial.println("");
           #endif

            send_data(0);
            dht_time = millis() + dht_interval;
        }
    }
}

//----------------------------------------------------------------------------//
// FUNCTIONS (MIS)                                                            //
//----------------------------------------------------------------------------//

void send_data(int shot) {
    // SHOT:
    // 0 = NO DATA
    // 1 = WRONG SHOT (MISS)
    // 2 = RIGHT SHOT (SCORE)

    Bluetooth.print(humi);
    Bluetooth.print(temp);
    Bluetooth.print(heat);
    Bluetooth.print(shot);

    #ifdef DEBUG_BLUE
        Serial.println("Bluetooth sent");
        Serial.println();
    #endif
}

void reset() {
    vibr = false;
    prox = false;
    wait = false;

    delay(1000);

    // SET LED BLUE
    set_led(4, 100);
}

//----------------------------------------------------------------------------//
// MAIN                                                                       //
//----------------------------------------------------------------------------//

void loop() {
    check_prox();
    check_vibr();
    check_wait();
    check_dht();
}

Android code (2.0.0)

Java
Android MIT App Inventor (http://ai2.appinventor.mit.edu/)
No preview (download only).

Credits

Marcelo Ávila de Oliveira

Marcelo Ávila de Oliveira

3 projects • 4 followers

Comments