Jeff
Published © CC BY-NC-SA

Scoreboard with ESP32 and TM1638 with BLE Android app

Scoreboard setup for American Football but can be used for almost any sport, etc.

BeginnerProtip5,428
Scoreboard with ESP32 and TM1638 with BLE Android app

Things used in this project

Hardware components

Generic ESP32 development board
I used the DOIT ESP32 DEVKIT V1 board
×1
M1638 Chip Key Display Module 8 Bits Digital LED Tube For AVR Arduino
×1
Android device
Android device
Will require MIT App Inventor installed for testing.
×1
LED (generic)
LED (generic)
Used to show when a Bluetooth device is connected to the ESP32 I used a Blue LED
×1
Resistor 10k ohm
Resistor 10k ohm
Required to wire 2 buttons for manually resetting scores for Home and/or Visitor teams.
×2
Pushbutton switch 12mm
SparkFun Pushbutton switch 12mm
Can use any generic/size Pushbutton switches.
×2

Software apps and online services

Arduino IDE
Arduino IDE
MIT App Inventor
MIT App Inventor

Story

Read more

Schematics

ESP32-Devkit-Pinout

I found this great Pin Out drawing that someone made credit they put in the attached PDF.

Wiring Guide

The ESP in the diagram is not exact and has less pins compared to the board I used but it still works to show how to wiring the curcuit.

Code

Ardiuno sketch for ESP32

Arduino
// ESP32 Dev board - DOIT ESP32 DEVKIT V1
// TM1638 7 Segment Display with buttons
// 10K resistor (x2)
// PushButton (x2)
// Blue LED

/* Wiring Notes as per code below:
Blue LED -
Negative (short LED pin) -> GND
Positive (long LED pin) -> D21 (GPIO pin)

Home & Vistor push buttons - 
Button pin -> D22 (home)GPIO pin / D23 (visitor) GPIO pin
Button pin -> 10K resistor -> GND
Other side button pin -> 3V3 pin

TM1638 7 Segment Display with buttons - 
VCC > 3V3
GND > GND
STB > D4 (GPIO pin)
CLK > RX2 (16 GPIO pin)
DIO > TX2 (17 GPIO pin)
*/

// To Do: Fix diplays when plugged in

#include "wiring_shift_mod.h"

#define CLOCK_TYPE CLOCK_INVERT
#define CLOCK_DELAY_US 1

// Bluetooth
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

BLEServer *pServer = NULL;
BLECharacteristic * pTxCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;

// See the following for generating UUIDs: https://www.uuidgenerator.net/
#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_ScoreTX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"


// ESP32 pins used for Segment display
uint8_t strobe_pin =  4;
uint8_t clock_pin  = 16;            // pin RX2
uint8_t data_pin   = 17;            // pin TX2

//Variables
uint8_t hScore = 0;  // 1st digit in Home Score
uint8_t hScore2 = 0;  // 2nd digit in Home Score
uint8_t vScore = 0;  // 1st digit in Vistor Score
uint8_t vScore2 = 0;  // 2nd digit in Vistor Score

uint8_t hTScore = 0; //Total Home score for Bluetooth Android app
uint8_t vTScore = 0; //Total Home score for Bluetooth Android app

uint8_t currentHomePoints = hTScore; //Used to compare scores for loop to prevent consent BT packets been sent to Client
uint8_t currentVisitorPoints = vTScore; //Used to compare scores for loop to prevent consent BT packets been sent to Client

//Reset Buttons
const uint8_t resetHomePin = 22; 
const uint8_t resetVisitorPin = 23; 
// variables will change:
uint8_t resetbuttonStateH = 0;         // variable for reading the pushbutton status
uint8_t resetbuttonStateV = 0;

// Displays numbers in order of array Hex values(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) ex. NUMBERS[5] displays the number 5.
const uint8_t NUMBERS[] = {
  0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F
};

// Display Segment that is used left to right in order of (array Hex values 0-7 on 8 segment display) ex. SSD[0] uses first 7 Segment display
const uint8_t SSD[] = {
  0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce
};

uint8_t readButtons(void)
{
  uint8_t buttons = 0;
  digitalWrite(strobe_pin, LOW);
  shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, 0x42);

  pinMode(data_pin, INPUT);

  for (uint8_t i = 0; i < 4; i++)
  {
    uint8_t v = shiftInMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US) << i; buttons |= v;
  }

  pinMode(data_pin, OUTPUT);
  digitalWrite(strobe_pin, HIGH);
  return buttons;
}

///////////////////////////////////////////////////////////

class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
    }
};

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string rxValue = pCharacteristic->getValue();

      uint8_t buttons = readButtons();
       
       // Print out in Serial Monitor buttons pressed
       //if (rxValue.length() > 0) {
       //Serial.println("*********");
       //Serial.print("Received Value: ");
       // for (int i = 0; i < rxValue.length(); i++)
       //   Serial.print(rxValue[i]);

       if (rxValue.find("update") != -1) {
          updateBTapp();
        }
        
        if (rxValue.find("rHome") != -1) {
          resetHome();
        }
        
        if (rxValue.find("rVisitor") != -1) {
          resetVisitor();
        }

        if (rxValue.find("h1") != -1) {
          addHome1Point();
        }

        if (rxValue.find("h2") != -1) {
          addHome2Points();
        }

        if (rxValue.find("h3") != -1) {
          addHome3Points();
        }

        if (rxValue.find("h6") != -1) {
          addHome6Points();
        }

        if (rxValue.find("v1") != -1) {
          addVisitor1Point();
        }

        if (rxValue.find("v2") != -1) {
          addVisitor2Points();
        }

        if (rxValue.find("v3") != -1) {
          addVisitor3Points();
        }

        if (rxValue.find("v6") != -1) {
          addVisitor6Points();
        }
       
       // Serial.println();
       //Serial.println("*********");
    }
};

/////////////////////////////////////////////////////////

void sendCommand(uint8_t value)
{
  digitalWrite(strobe_pin, LOW);
  shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, value);
  digitalWrite(strobe_pin, HIGH);
}
//////////////////////////////////////////////////////////////
void reset(){
  digitalWrite(strobe_pin, LOW);
      for (uint8_t i = 0; i < 8; i++){
      shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[i]);
      shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, 0x00);
  }
  digitalWrite(strobe_pin, HIGH);

  hScore = 0;  // Reset value of 1st digit in Home Score
  hScore2 = 0;  // Reset value of 2nd digit in Home Score
  vScore = 0;  // Reset value of 1st digit in Vistor Score
  vScore2 = 0;  // Reset value of 2nd digit in Vistor Score
  hTScore = 0; //Reset Home score for Bluetooth Android app
  vTScore = 0; //Reset Home score for Bluetooth Android app
  currentHomePoints = 0;
  currentVisitorPoints = 0;
}

//////////////////////////////////////////////////////////////
void resetHome() {
  digitalWrite(strobe_pin, LOW);
   for (uint8_t i = 0; i < 4; i++){
   shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[i]);
   shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, 0x00);    // Clears Vistor Segments
   }
    
  digitalWrite(strobe_pin, HIGH);
    hScore = 0;  // Reset value of 1st digit in Home Score
    hScore2 = 0;  // Reset value of 2nd digit in Home Score
    hTScore = 0; //Reset Home score for Bluetooth Android app 
   }  
 

/////////////////////////////////////////////////////////////
void resetVisitor() {
   digitalWrite(strobe_pin, LOW);
   for (uint8_t i = 4; i < 8; i++){
   shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[i]);
   shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, 0x00);    // Clears Vistor Segments
   }

  digitalWrite(strobe_pin, HIGH);
    vScore = 0;  // Reset value of 1st digit in Vistor Score
    vScore2 = 0;  // Reset value of 2nd digit in Vistor Score
    vTScore = 0; //Reset Home score for Bluetooth Android app
   }
 
////////////////////////////////////////////////////////////

void addHome1Point() {
  if  (hScore2 < 9) {          // Displays 1-9 on Home scoreboard
    hScore2 = hScore2 + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[2]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[hScore2]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    hTScore++;
  }
  else if  (hScore2 == 9) {    // Displays (10,20,30,40,50,60,70,80,90) on Home scoreboard
    hScore = hScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[1]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[hScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[2]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[0]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    hScore2 = 0;
    hTScore++;
  }
}

////////////////////////////////////////////////////////////

void addHome2Points() {
  if  (hScore2 < 8) {          // Displays 1-9 on Home scoreboard
    hScore2 = hScore2 + 2;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[2]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[hScore2]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    hTScore = hTScore+2;
  }
  else if  (hScore2 == 8) {    // Displays (10,20,30,40,50,60,70,80,90) on Home scoreboard
    hScore = hScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[1]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[hScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[2]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[0]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    hScore2 = 0;
    hTScore = hTScore+2;
  }
  else if  (hScore2 == 9) {    // Displays (11,21,31,41,51,61,71,81,91) on Home scoreboard
    hScore = hScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[1]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[hScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[2]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[1]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    hScore2 = 1;
    hTScore = hTScore+2;
  }
}

////////////////////////////////////////////////////////////

void addHome3Points() {
  if  (hScore2 < 7) {          // Displays 1-9 on Home scoreboard
    hScore2 = hScore2 + 3;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[2]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[hScore2]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    hTScore = hTScore+3;
  }
  else if  (hScore2 == 7) {    // Displays (10,20,30,40,50,60,70,80,90) on Home scoreboard
    hScore = hScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[1]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[hScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[2]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[0]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    hScore2 = 0;
    hTScore = hTScore+3;
  }
  else if  (hScore2 == 8) {    // Displays (11,21,31,41,51,61,71,81,91) on Home scoreboard
    hScore = hScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[1]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[hScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[2]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[1]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    hScore2 = 1;
    hTScore = hTScore+3;
  }
  else if  (hScore2 == 9) {    // Displays (12,22,32,42,52,62,72,82,92) on Home scoreboard
    hScore = hScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[1]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[hScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[2]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[2]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    hScore2 = 2;
    hTScore = hTScore+3;
  }
}

////////////////////////////////////////////////////////////

void addHome6Points() {
  if  (hScore2 < 4) {          // Displays 1-9 on Home scoreboard
    hScore2 = hScore2 + 6;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[2]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[hScore2]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    hTScore = hTScore+6;
  }
  else if  (hScore2 == 4) {    // Displays (10,20,30,40,50,60,70,80,90) on Home scoreboard
    hScore = hScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[1]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[hScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[2]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[0]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    hScore2 = 0;
    hTScore = hTScore+6;
  }
  else if  (hScore2 == 5) {    // Displays (11,21,31,41,51,61,71,81,91) on Home scoreboard
    hScore = hScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[1]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[hScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[2]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[1]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    hScore2 = 1;
    hTScore = hTScore+6;
  }
  else if  (hScore2 == 6) {    // Displays (12,22,32,42,52,62,72,82,92) on Home scoreboard
    hScore = hScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[1]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[hScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[2]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[2]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    hScore2 = 2;
    hTScore = hTScore+6;
  }
  else if  (hScore2 == 7) {    // Displays (13,23,33,43,53,63,73,83,93) on Home scoreboard
    hScore = hScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[1]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[hScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[2]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[3]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    hScore2 = 3;
    hTScore = hTScore+6;
  }
  else if  (hScore2 == 8) {    // Displays (14,24,34,44,54,64,74,84,94) on Home scoreboard
    hScore = hScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[1]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[hScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[2]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[4]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    hScore2 = 4;
    hTScore = hTScore+6;
  }
  else if  (hScore2 == 9) {     // Displays (15,25,35,45,55,65,75,85,95) on Home scoreboard
    hScore = hScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[1]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[hScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[2]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[5]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    hScore2 = 5;
    hTScore = hTScore+6;
  }
}

////////////////////////////////////////////////////////////

void addVisitor1Point() {
  if  (vScore2 < 9) {          // Displays 1-9 on Visitor scoreboard
    vScore2 = vScore2 + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[6]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[vScore2]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    vTScore++;
  }
  else if  (vScore2 == 9) {    // Displays (10,20,30,40,50,60,70,80,90) on Visitor scoreboard
    vScore = vScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[5]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[vScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[6]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[0]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    vScore2 = 0;
    vTScore++;
  }
}

////////////////////////////////////////////////////////////

void addVisitor2Points() {
  if  (vScore2 < 8) {          // Displays 1-9 on Visitor scoreboard
    vScore2 = vScore2 + 2;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[6]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[vScore2]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    vTScore = vTScore+2;
  }
  else if  (vScore2 == 8) {    // Displays (10,20,30,40,50,60,70,80,90) on Visitor scoreboard
    vScore = vScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[5]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[vScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[6]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[0]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    vScore2 = 0;
    vTScore = vTScore+2;
  }
  else if  (vScore2 == 9) {    // Displays (11,21,31,41,51,61,71,81,91) on Visitor scoreboard
    vScore = vScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[5]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[vScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[6]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[1]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    vScore2 = 1;
    vTScore = vTScore+2;
  }
}

////////////////////////////////////////////////////////////

void addVisitor3Points() {
  if  (vScore2 < 7) {          // Displays 1-9 on Visitor scoreboard
    vScore2 = vScore2 + 3;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[6]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[vScore2]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    vTScore = vTScore+3;
  }
  else if  (vScore2 == 7) {    // Displays (10,20,30,40,50,60,70,80,90) on Visitor scoreboard
    vScore = vScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[5]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[vScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[6]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[0]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    vScore2 = 0;
    vTScore = vTScore+3;
  }
  else if  (vScore2 == 8) {    // Displays (11,21,31,41,51,61,71,81,91) on Visitor Scoreboard
    vScore = vScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[5]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[vScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[6]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[1]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    vScore2 = 1;
    vTScore = vTScore+3;
  }
  else if  (vScore2 == 9) {    // Displays (12,22,32,42,52,62,72,82,92) on Visitor Scoreboard
    vScore = vScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[5]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[vScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[6]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[2]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    vScore2 = 2;
    vTScore = vTScore+3;
  }
}

////////////////////////////////////////////////////////////

void addVisitor6Points() {
  if  (vScore2 < 4) {          // Displays 1-9 on Visitor scoreboard
    vScore2 = vScore2 + 6;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[6]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[vScore2]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    vTScore = vTScore+6;
  }
  else if  (vScore2 == 4) {    // Displays (10,20,30,40,50,60,70,80,90) on Visitor scoreboard
    vScore = vScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[5]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[vScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[6]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[0]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    vScore2 = 0;
    vTScore = vTScore+6;
  }
  else if  (vScore2 == 5) {    // Displays (11,21,31,41,51,61,71,81,91) on Visitor Scoreboard
    vScore = vScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[5]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[vScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[6]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[1]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    vScore2 = 1;
    vTScore = vTScore+6;
  }
  else if  (vScore2 == 6) {    // Displays (12,22,32,42,52,62,72,82,92) on Visitor Scoreboard
    vScore = vScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[5]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[vScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[6]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[2]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    vScore2 = 2;
    vTScore = vTScore+6;
  }
  else if  (vScore2 == 7) {    // Displays (13,23,33,43,53,63,73,83,93) on Visitor Scoreboard
    vScore = vScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[5]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[vScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[6]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[3]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    vScore2 = 3;
    vTScore = vTScore+6;
  }
  else if  (vScore2 == 8) {    // Displays (14,24,34,44,54,64,74,84,94) on Visitor Scoreboard
    vScore = vScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[5]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[vScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[6]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[4]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    vScore2 = 4;
    vTScore = vTScore+6;
  }
  else if  (vScore2 == 9) {     // Displays (15,25,35,45,55,65,75,85,95) on Visitor Scoreboard
    vScore = vScore + 1;
    digitalWrite(strobe_pin, LOW);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[5]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[vScore]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, SSD[6]);
    shiftOutMod(data_pin, clock_pin, LSBFIRST, CLOCK_TYPE, CLOCK_DELAY_US, NUMBERS[5]);
    digitalWrite(strobe_pin, HIGH);
    delay(250);
    vScore2 = 5;
    vTScore = vTScore+6;
  }
}

////////////////////////////////////////////////////////////

// Buttons to add points to Scoreboard

void addPoints() {

  uint8_t buttons = readButtons(); //Reads what button was pushed

  // Add Points to Home Score (left side)
  // Button to add 1 point to Home Scoreboard
  if (buttons == 1) {
    addHome1Point();
  }

  // Button to add 2 points to Home Scoreboard
  if (buttons == 2) {
    addHome2Points();
  }

  // Button to add 3 points to Home Scoreboard
  if (buttons == 4) {
    addHome3Points();
  }

  // Button to add 6 points to Home Scoreboard
  if (buttons == 8) {
    addHome6Points();
  }

  //////////////////

  // Add Points to Visitor Score (right side)
  // Button to add 1 point to Visitor Scoreboard
  if (buttons == 16) {
    addVisitor1Point();
  }

  // Button to add 2 points to Visitor Scoreboard
  if (buttons == 32) {
    addVisitor2Points();
  }

  // Button to add 3 points to Visitor Scoreboard
  if (buttons == 64) {
    addVisitor3Points();
  }

  // Button to add 6 points to Visitor Scoreboard
  if (buttons == 128) {
    addVisitor6Points();
  }
}
//////////////////////////////////////////////////////////////
void points2BTapp() {

  if (hTScore != currentHomePoints) {
   
    //For Displaying Home Team score to Bluetooth app
    //Convert the value to a char array:  
    char hTString[8];          //the ASCII of the integer will be stored in this char array
    itoa(hTScore,hTString,10);  //(integer, yourBuffer, base)for integer variable convert to string for BT app
    char sHome[] = "h";
    char sHomeBT [] = {0};

    // Merge Char arrays to have "h" appear before the score for BT app control
    strcat(sHomeBT, sHome);
    strcat(sHomeBT, hTString);
      
    pTxCharacteristic->setValue(sHomeBT);
    pTxCharacteristic->notify(); // Send the value to the app!
    
    Serial.print("*** Home: ");
    Serial.print(sHomeBT);
    Serial.println(" ***");
    currentHomePoints = hTScore;
  }

   if (vTScore != currentVisitorPoints) {
   
    //For Displaying Home Team score to Bluetooth app
    //Convert the value to a char array:  
    char vTString[8];          //the ASCII of the integer will be stored in this char array
    itoa(vTScore,vTString,10);  //(integer, yourBuffer, base)for integer variable convert to string for BT app
    char sVisitor[] = "v";
    char sVisitorBT [] = {0};

    // Merge Char arrays to have "v" appear before the score for BT app control
    strcat(sVisitorBT, sVisitor);
    strcat(sVisitorBT, vTString);
       
    pTxCharacteristic->setValue(sVisitorBT);
    pTxCharacteristic->notify(); // Send the value to the app!
    
    Serial.print("*** Visitors: ");
    Serial.print(sVisitorBT);
    Serial.println(" ***");
    currentVisitorPoints = vTScore;
  }
}
////////////////////////////////////////////////////////////
void updateBTapp() {               // reset scores on BT Android app 

    char hTString[8];          //the ASCII of the integer will be stored in this char array
    itoa(hTScore,hTString,10);  //(integer, yourBuffer, base)for integer variable convert to string for BT app
    char sHome[] = "h";
    char sHomeBT [] = {0};

    // Merge Char arrays to have "h" appear before the score for BT app control
    strcat(sHomeBT, sHome);
    strcat(sHomeBT, hTString);
      
    pTxCharacteristic->setValue(sHomeBT);
    pTxCharacteristic->notify(); // Send the value to the app!
    currentHomePoints = hTScore;
  
    //For Displaying Home Team score to Bluetooth app
    //Convert the value to a char array:  
    char vTString[8];          //the ASCII of the integer will be stored in this char array
    itoa(vTScore,vTString,10);  //(integer, yourBuffer, base)for integer variable convert to string for BT app
    char sVisitor[] = "v";
    char sVisitorBT [] = {0};

    // Merge Char arrays to have "v" appear before the score for BT app control
    strcat(sVisitorBT, sVisitor);
    strcat(sVisitorBT, vTString);
       
    pTxCharacteristic->setValue(sVisitorBT);
    pTxCharacteristic->notify(); // Send the value to the app!
    currentVisitorPoints = vTScore;
  }

////////////////////////////////////////////////////////////

void setup() {
  Serial.begin(115200);
  pinMode(strobe_pin, OUTPUT);
  pinMode(clock_pin, OUTPUT);
  pinMode(data_pin, OUTPUT);

  pinMode(2, OUTPUT);                        //initialize Internal LED pin
  pinMode(21, OUTPUT);                        //initialize LED pin using for showing Bluetooth device connected
  
  pinMode(resetHomePin, INPUT);                // initialize the pushbutton pins as an input:
  pinMode(resetVisitorPin, INPUT); 
  
  sendCommand(0x8f);              // activate at max brightness
  reset();                         // initialize screen
  
  // Create the BLE Device
  BLEDevice::init("ScoreBoard");  //Set Name of ESP device

  // Create the BLE Server
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Create the BLE Service
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // Create a BLE Characteristic
  pTxCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_ScoreTX, BLECharacteristic::PROPERTY_NOTIFY);
  pTxCharacteristic->addDescriptor(new BLE2902());

  BLECharacteristic * pRxCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE);
  pRxCharacteristic->setCallbacks(new MyCallbacks());

  // Start the service
  pService->start();

  // Start advertising
  pServer->getAdvertising()->start();
  Serial.println("Waiting a client connection to notify...");
}

///////////////////////////////////////////////////////////

void loop()
{
  //sendCommand(0x44);  // set single

  if (deviceConnected) {     
    points2BTapp();
    delay(100); // bluetooth stack will go into congestion, if too many packets are sent -> adjust delay for better response times from Android app
   digitalWrite(21, HIGH);  
   }

  // disconnecting
  if (!deviceConnected && oldDeviceConnected) {
    delay(500); // give the bluetooth stack the chance to get things ready
    pServer->startAdvertising(); // restart advertising
    Serial.println("start advertising");
    oldDeviceConnected = deviceConnected;
    digitalWrite(21, LOW);
  }
  // connecting
  if (deviceConnected && !oldDeviceConnected) {
    // do stuff here on connecting
    oldDeviceConnected = deviceConnected;
    
  }
  addPoints();
  
  resetbuttonStateH = digitalRead(resetHomePin);            // read the state of the pushbutton values
        if (resetbuttonStateH == HIGH) {                    // check if the pushbutton is pressed 
        resetHome();
        }

  resetbuttonStateV = digitalRead(resetVisitorPin);                   // read the state of the pushbutton values
      if (resetbuttonStateV == HIGH) {                                // check if the pushbutton is pressed      
      resetVisitor();
      }
 }

wiring_shift_mod.cpp

C/C++
For the ESP32 to work with the TM1638 7 Segment Display with buttons. Need to be saved in the same directory as the Arduino Sketch.
/*
  wiring_shift_mod.c - clocked shift functions

  Based on Arduino's wiring_shift.c

  Original work Copyright 2005-2006 David A. Mellis
  Modified work Copyright 2017 Martin F. Falatic

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General
  Public License along with this library; if not, write to the
  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  Boston, MA  02111-1307  USA
*/

#include "wiring_private.h"
#include "wiring_shift_mod.h"

uint8_t shiftInMod(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t clock_type, uint16_t clock_delay_us) {
	uint8_t value = 0;
	uint8_t i;

  
	for (i = 0; i < 8; ++i) {
		digitalWrite(clockPin, (clock_type ? LOW : HIGH));
    delayMicroseconds(clock_delay_us);
		if (bitOrder == LSBFIRST)
			value |= digitalRead(dataPin) << i;
		else
			value |= digitalRead(dataPin) << (7 - i);
		digitalWrite(clockPin, (clock_type ? HIGH : LOW));
	}
	return value;
}

void shiftOutMod(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t clock_type, uint16_t clock_delay_us, uint8_t val)
{
	uint8_t i;

	for (i = 0; i < 8; i++)  {
		if (bitOrder == LSBFIRST)
			digitalWrite(dataPin, !!(val & (1 << i)));
		else	
			digitalWrite(dataPin, !!(val & (1 << (7 - i))));
			
		digitalWrite(clockPin, (clock_type ? LOW : HIGH));
    delayMicroseconds(clock_delay_us);
		digitalWrite(clockPin, (clock_type ? HIGH : LOW));		
	}
}

wiring_shift_mod.h

C/C++
For the ESP32 to work with the TM1638 7 Segment Display with buttons. Need to be saved in the same directory as the Arduino Sketch.
#ifndef wiring_shift_mod_h
#define wiring_shift_mod_h

#define CLOCK_NORMAL 0
#define CLOCK_INVERT 1

void shiftOutMod(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t clock_type, uint16_t clock_delay_us, uint8_t val);
uint8_t shiftInMod(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t clock_type, uint16_t clock_delay_us);

#endif

Scoreboard_MKII.aia

C/C++
File used to Import into MIT app inventor so you can change the ESP32 MAC address to match the address of your ESP32. It is commented in the Blocks code. Then you can save your final app to APK package to install on you Android device. I made a few adjustments to make the connection via BLE more reliable.
No preview (download only).

Credits

Jeff
4 projects • 8 followers
Contact

Comments

Please log in or sign up to comment.