#include "SevSeg.h"
#include <LiquidCrystal_I2C.h>
// --- buzzer ---
void tom (char pino, int frequencia, int duracao);
#define buzzer 8
int modo = 0;
// Encoder
byte CLK = 2; // Botão A do encoder
byte DT = 3; // Botão B do encoder
byte SW = 4; // Pino do botão do encoder
bool escolha;
byte dtvalue;
String modalidade = "";
// Time A
#define btnVerde_A 53
#define btnVermelho_A 52
#define Led_A 9
// Time B
#define btnVerde_B 35
#define btnVermelho_B 37
#define Led_B 10
// Inicializar display LCD
#define I2C_ADDR 0x27
#define LCD_COLUMNS 20
#define LCD_LINES 4
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
// Controlar os displays de 7 segmentos
// Time A
SevSeg P_A;
SevSeg S_A;
// Time B
SevSeg P_B;
SevSeg S_B;
unsigned long scoreA = 0; // Pontuação da equipe A
unsigned long scoreB = 0; // Pontuação da equipe B
int setsA = 0; // Sets vencidos pela equipe A
int setsB = 0; // Sets vencidos pela equipe B
int SetAtual = 1; // Set atual
bool Quadra = true; // Se o jogo é na quadra
bool tiebreak = false; // Se o jogo está na partida de desenpate
// Variaveis de somatória
unsigned long Ntotal = 0;
void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
pinMode(btnVerde_A, INPUT_PULLUP);
pinMode(btnVermelho_A, INPUT_PULLUP);
pinMode(btnVerde_B, INPUT_PULLUP);
pinMode(btnVermelho_B, INPUT_PULLUP);
pinMode(Led_A, OUTPUT);
pinMode(Led_B, OUTPUT);
pinMode(buzzer, OUTPUT);
// Display Padrão
escolheModo();
// Configuração Padrão (Display de 7 Segmentos)
bool zerosNaEsquerda = false; // 'true' pra manter os zeros à esquerda
bool PontoDecimal = true; // 'false' se o ponto decimal existe
byte pinosDesenho[] = {51, 49, 47, 43, 45, 41, 39};
// Display Pontuação A
byte digitos_P_A = 6;
byte pinos_P_A[] = {25, 23, 27, 33, 31, 29};
P_A.begin(COMMON_ANODE, digitos_P_A, pinos_P_A, pinosDesenho, false,
false, zerosNaEsquerda, PontoDecimal);
// Display Sets A
byte digitos_S_A = 1;
byte pinos_S_A[] = {27};
S_A.begin(COMMON_ANODE, digitos_S_A, pinos_S_A, pinosDesenho, false,
false, zerosNaEsquerda, PontoDecimal);
// Display Sets B
byte digitos_S_B = 1;
byte pinos_S_B[] = {33};
S_B.begin(COMMON_ANODE, digitos_S_B, pinos_S_B, pinosDesenho, false,
false, zerosNaEsquerda, PontoDecimal);
}
void loop() {
// Lógica para adicionar e subtrair pontos
pontuacao();
if (digitalRead(SW) == LOW){
reset();
}
// Npa + 10000 --> Somar 1 ponto visual no time A
// Nsa + 1000 --> Somar 1 ponto visual no Set A
// Nsb + 100 --> Somar 1 ponto visual no Set B
// Npb + 1 ou Npb++ --> Somar 1 ponto visual no time B
// Atualizando os displays de 7 segmentos com a pontuação atual
P_A.setNumber(Ntotal, 6); // n = 00-00-00, n + 100000, n + 10000, n + 1000, n + 100, n + 10 e n + 1.
P_A.refreshDisplay();
S_A.setNumber(setsA, 2);
S_A.refreshDisplay();
S_B.setNumber(setsB, 2);
S_B.refreshDisplay();
switch (modo){
//---------------------------------QUADRA---------------------------
case 1:
if ((scoreA >= 25) && (scoreA - scoreB >= 2)) {
setsA++;
delay(500);
Serial.println(setsA);
Ntotal = Ntotal + 1000;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("FIM DO SET");
Ntotal = Ntotal - ((scoreA * 10000) + (scoreB));
delay(2000);
lcd.clear();
if (setsA >= 2 ){
lcd.print("O Time A venceu");
delay(30000);
// Npa + 10000 --> Somar 1 ponto visual no time A
// Nsa + 1000 --> Somar 1 ponto visual no Set A
// Nsb + 100 --> Somar 1 ponto visual no Set B
// Npb + 1 ou Npb++ --> Somar 1 ponto visual no time B
}
else{
lcd.print("Indo para o proximo Set...");
delay(2000);
lcd.clear();
resetScores();
}
}
else if (scoreB >= 25 && scoreB - scoreA >= 2) {
setsB++;
Ntotal = Ntotal + 100;
delay(500);
Serial.println(setsB);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("FIM DO SET");
Ntotal = Ntotal - ((scoreA * 10000) + (scoreB));
delay(30000);
lcd.clear();
if (setsA >= 2 ){
lcd.print("O Time B venceu");
Ntotal + 100;
delay(30000);
// Npa + 10000 --> Somar 1 ponto visual no time A
// Nsa + 1000 --> Somar 1 ponto visual no Set A
// Nsb + 100 --> Somar 1 ponto visual no Set B
// Npb + 1 ou Npb++ --> Somar 1 ponto visual no time B
}
else{
lcd.print("Indo para o proximo Set...");
delay(2000);
lcd.clear();
resetScores();
}
}
// Verificando se terá o tiebreak
else if (setsA == 2 && setsB == 2) {
if ((scoreA == 15 && scoreA - scoreB >= 2) || (scoreB == 15 && scoreB - scoreA >= 2)) {
// Fim do tiebreak
lcd.clear();
lcd.setCursor(0, 0);
Ntotal = 0;
lcd.print("Tiebreak terminou");
lcd.setCursor(0, 1);
if (scoreA == 15 && scoreA - scoreB >= 2) {
lcd.print("O Time A venceu");
}
else if (scoreB == 15 && scoreB - scoreA >= 2) {
lcd.print("O Time B venceu");
}
delay(30000);
reset();
}
else if ((scoreA == 8) || (scoreB == 8)) {
// Troca de lados no tiebreak
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Troca de lados");
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Pontos: " + String(scoreA) + "-" + String(scoreB));
delay(30000);
}
}
pontuacao();
break;
//---------------------------------AREIA---------------------------
case 2:
if (scoreA >= 21 && scoreA - scoreB >= 2) {
setsA++;
Ntotal = Ntotal + 1000;
delay(500);
Serial.println(setsA);
lcd.clear();
lcd.setCursor(0, 0);
Ntotal = Ntotal - ((scoreA * 10000) + (scoreB));
lcd.print("FIM DO SET");
delay(30000);
lcd.clear();
if (setsA >= 2 ){
lcd.print("O Time A venceu");
Ntotal + 1000;
delay(30000);
// Npa + 10000 --> Somar 1 ponto visual no time A
// Nsa + 1000 --> Somar 1 ponto visual no Set A
// Nsb + 100 --> Somar 1 ponto visual no Set B
// Npb + 1 ou Npb++ --> Somar 1 ponto visual no time B
}
else{
lcd.print("Indo para o proximo Set...");
delay(30000);
lcd.clear();
resetScores();
}
}
else if (scoreB >= 21 && scoreB - scoreA >= 2) {
setsB++;
Ntotal = Ntotal + 100;
delay(500);
Serial.println(setsB);
lcd.clear();
lcd.setCursor(0, 0);
Ntotal = Ntotal - ((scoreA * 10000) + (scoreB));
lcd.print("FIM DO SET");
delay(30000);
lcd.clear();
if (setsA >= 2 ){
lcd.print("O Time B venceu");
//Ntotal + 100;
delay(30000);
// Npa + 10000 --> Somar 1 ponto visual no time A
// Nsa + 1000 --> Somar 1 ponto visual no Set A
// Nsb + 100 --> Somar 1 ponto visual no Set B
// Npb + 1 ou Npb++ --> Somar 1 ponto visual no time B
}
else{
lcd.print("Indo para o proximo Set...");
delay(2000);
lcd.clear();
resetScores();
}
}
// Entrando no tiebreak
else if (setsA == 1 && setsB == 1) {
// Fim do tiebreak
if (((scoreA == 15) && (scoreA - scoreB >= 2)) || ((scoreB == 15) && (scoreB - scoreA >= 2))) {
lcd.clear();
lcd.setCursor(0, 0);
Ntotal = 0;
lcd.print("Tiebreak terminou");
lcd.clear();
if (scoreA == 15 && scoreA - scoreB >= 2) {
lcd.print("O Time A venceu");
}
else if (scoreB == 15 && scoreB - scoreA >= 2) {
lcd.print("O Time B venceu");
}
delay(30000);
reset();
}
// Troca de lados no tiebreak
else if (((scoreA % 7 == 0) && (scoreA > 0)) || ((scoreB % 7 == 0) && (scoreB > 0))) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Troca de lados");
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Pontos: " + String(scoreA) + "-" + String(scoreB));
delay(30000);
}
}
pontuacao();
}
}
void pontuacao() {
if (digitalRead(btnVerde_A) == LOW) {
scoreA++;
tone(buzzer, 400);
delay(500);
noTone(buzzer);
Serial.println(scoreA);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set " + String(SetAtual) + ":");
lcd.setCursor(0, 1);
lcd.print("Pontos: " + String(scoreA) + "-" + String(scoreB));
digitalWrite(Led_A, HIGH);
digitalWrite(Led_B, LOW);
Ntotal = Ntotal + 10000;
}
else if (digitalRead(btnVermelho_A) == LOW) {
scoreA--;
tone(buzzer, 100);
delay(500);
noTone(buzzer);
Serial.println(scoreA);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set " + String(SetAtual) + ":");
lcd.setCursor(0, 1);
lcd.print("Pontos: " + String(scoreA) + "-" + String(scoreB));
digitalWrite(Led_B, HIGH);
digitalWrite(Led_A, LOW);
Ntotal = Ntotal - 10000;
}
else if (digitalRead(btnVerde_B) == LOW) {
scoreB++;
tone(buzzer, 500);
delay(500);
noTone(buzzer);
Serial.println(scoreB);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set " + String(SetAtual) + ":");
lcd.setCursor(0, 1);
lcd.print("Pontos: " + String(scoreA) + "-" + String(scoreB));
digitalWrite(Led_B, HIGH);
digitalWrite(Led_A, LOW);
Ntotal++;
}
else if (digitalRead(btnVermelho_B) == LOW) {
scoreB--;
tone(buzzer, 100);
delay(500);
noTone(buzzer);
Serial.println(scoreB);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set " + String(SetAtual) + ":");
lcd.setCursor(0, 1);
lcd.print("Pontos: " + String(scoreA) + "-" + String(scoreB));
digitalWrite(Led_A, HIGH);
digitalWrite(Led_B, LOW);
Ntotal--;
}
}
void resetScores() {
scoreA = 0;
scoreB = 0;
SetAtual++;
if (SetAtual <= 3) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set " + String(SetAtual) + ":");
lcd.setCursor(0, 1);
lcd.print("Pontos: 0-0");
musica();
delay(30000);
} else {
// Fim do jogo
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Jogo terminou");
delay(30000);
reset();
}
}
void reset() {
scoreA = 0;
scoreB = 0;
setsA = 0;
setsB = 0;
Ntotal = 0;
SetAtual = 1;
Quadra = true;
tiebreak = false;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Gire o Encoder");
}
void escolheModo() {
lcd.setCursor(3, 1);
lcd.print("Escolha Entre:");
lcd.setCursor(0, 2);
lcd.print("a. Quadra b. Areia");
delay(1000);
IniciarEncoder();
if (modalidade != ""){
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set " + String(SetAtual) + ":");
lcd.setCursor(0, 1);
lcd.print("Pontos: 0-0");
}
}
void LERencoder() {
int dtvalue = digitalRead(DT);
delay(100);
if (dtvalue == LOW){
modalidade = "Areia";
modo = 2;
}
else if (dtvalue == HIGH){
modalidade = "Quadra";
modo = 1;
}
escolha = true;
}
void IniciarEncoder() {
pinMode(CLK, INPUT);
pinMode(DT, INPUT);
pinMode(SW, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(CLK), LERencoder, FALLING);
while (escolha == false) {
delay(25);
}
LERencoder();
lcd.clear();
lcd.setCursor(2,0);
lcd.print("Modalidade");
lcd.setCursor(8 - sizeof(modalidade) / 2, 1);
lcd.print(modalidade);
delay(3000);
lcd.clear();
}
void musica() {
int tempo = 400;
tom(buzzer,440,tempo); //LA
delay(tempo);
tom(buzzer,294,tempo); //RE
delay(tempo);
tom(buzzer,349,tempo/2); //FA
delay(tempo/2);
tom(buzzer,392,tempo/2); //SOL
delay(tempo/2);
tom(buzzer,440,tempo); //LA
delay(tempo);
tom(buzzer,294,tempo); //RE
delay(tempo);
tom(buzzer,349,tempo/2); //FA
delay(tempo/2);
tom(buzzer,392,tempo/2); //SOL
delay(tempo/2);
tom(buzzer,330,tempo);
}
void tom(char pino, int frequencia, int duracao){
float periodo = 1000.0/frequencia; //Periodo em ms
for (int i = 0; i< duracao/(periodo);i++){ //Executa a rotina de dentro o tanta de vezes que a frequencia desejada cabe dentro da duracao
digitalWrite(pino,HIGH);
delayMicroseconds(periodo*500); //Metade do periodo em ms
digitalWrite(pino, LOW);
delayMicroseconds(periodo*500);
}
}