#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// Definições do display
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
// Instância do display
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Pinos dos botões para cada contador
const int botao1Pin = 2; // Incrementa A
const int botao2Pin = 3; // Decrementa A
const int botao3Pin = 4; // Incrementa B
const int botao4Pin = 5; // Decrementa B
const int botao5Pin = 6; // Incrementa C
const int botao6Pin = 7; // Decrementa C
// Variáveis para os contadores
int contadorA = 0;
int contadorB = 0;
int contadorC = 0;
// Variáveis para debouncing e estado dos botões
int botaoState[6] = {HIGH, HIGH, HIGH, HIGH, HIGH, HIGH};
int lastBotaoState[6] = {HIGH, HIGH, HIGH, HIGH, HIGH, HIGH};
unsigned long lastDebounceTime[6] = {0, 0, 0, 0, 0, 0};
unsigned long botaoPressionadoTime[6] = {0, 0, 0, 0, 0, 0};
unsigned long lastIncrementTime[6] = {0, 0, 0, 0, 0, 0};
bool botaoPressionado[6] = {false, false, false, false, false, false};
unsigned long debounceDelay = 50; // Tempo de debounce
unsigned long holdDelay = 500; // Tempo para considerar que o botão está sendo segurado (500 ms)
unsigned long repeatDelay = 35; // Intervalo entre incrementos/decrementos quando o botão está sendo segurado (35 ms)
void setup() {
// Inicializa o display OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("Falha ao inicializar o display OLED"));
for (;;);
}
// Configura os pinos dos botões como entradas com resistores pull-up internos
pinMode(botao1Pin, INPUT_PULLUP);
pinMode(botao2Pin, INPUT_PULLUP);
pinMode(botao3Pin, INPUT_PULLUP);
pinMode(botao4Pin, INPUT_PULLUP);
pinMode(botao5Pin, INPUT_PULLUP);
pinMode(botao6Pin, INPUT_PULLUP);
// Limpa e exibe os valores iniciais
display.clearDisplay();
atualizarDisplay();
}
void loop() {
unsigned long tempoAtual = millis();
// Verifica cada botão e realiza a operação correspondente
verificarBotao(botao1Pin, 0, &contadorA, 100, 1, tempoAtual); // Incrementa A
verificarBotao(botao2Pin, 1, &contadorA, 0, -1, tempoAtual); // Decrementa A
verificarBotao(botao3Pin, 2, &contadorB, 100, 1, tempoAtual); // Incrementa B
verificarBotao(botao4Pin, 3, &contadorB, 0, -1, tempoAtual); // Decrementa B
verificarBotao(botao5Pin, 4, &contadorC, 100, 1, tempoAtual); // Incrementa C
verificarBotao(botao6Pin, 5, &contadorC, 0, -1, tempoAtual); // Decrementa C
}
// Função para verificar o estado de um botão
void verificarBotao(int pin, int indice, int* contador, int limite, int operacao, unsigned long tempoAtual) {
int leitura = digitalRead(pin);
if (leitura != lastBotaoState[indice]) {
lastDebounceTime[indice] = tempoAtual;
}
if ((tempoAtual - lastDebounceTime[indice]) > debounceDelay) {
if (leitura != botaoState[indice]) {
botaoState[indice] = leitura;
if (botaoState[indice] == LOW) {
// Botão pressionado
botaoPressionado[indice] = true;
botaoPressionadoTime[indice] = tempoAtual;
lastIncrementTime[indice] = tempoAtual; // Inicializa o tempo do último incremento
// Aciona uma vez imediatamente
alterarContador(contador, limite, operacao);
} else {
// Botão liberado
botaoPressionado[indice] = false;
}
}
}
lastBotaoState[indice] = leitura;
// Verifica se o botão está sendo segurado
if (botaoPressionado[indice]) {
if ((tempoAtual - botaoPressionadoTime[indice]) > holdDelay) {
if ((tempoAtual - lastIncrementTime[indice]) >= repeatDelay) {
alterarContador(contador, limite, operacao);
lastIncrementTime[indice] = tempoAtual;
}
}
}
}
// Função para alterar o contador respeitando os limites
void alterarContador(int* contador, int limite, int operacao) {
if (operacao == 1 && *contador < limite) {
(*contador)++;
atualizarDisplay();
} else if (operacao == -1 && *contador > limite) {
(*contador)--;
atualizarDisplay();
}
}
// Função para atualizar o display OLED com os valores dos contadores e desenhar as barras
void atualizarDisplay() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
// Exibe o cabeçalho "PRESET 01" centralizado
display.setTextSize(1); // Tamanho de texto para o cabeçalho
centralizarTexto("PRESET 01", 0, SCREEN_WIDTH, 0);
// Configuração para centralizar o texto
display.setTextSize(1); // Tamanho de texto para os números e rótulos
// Posições Y para os números, barras e rótulos
int posYNumero = 12;
int posYBarraTopo = 25;
int posYBarraBase = 55;
int posYRotulo = 57;
// Altura máxima da barra
int alturaMaxBarra = posYBarraBase - posYBarraTopo;
// Largura de cada coluna
int larguraColuna = SCREEN_WIDTH / 3;
// Largura da barra
int larguraBarra = 15; // A largura da barra gráfica
// Exibe o contador A
int colA = 0 * larguraColuna;
String valorA = String(contadorA);
centralizarTexto(valorA, colA, larguraColuna, posYNumero);
desenharBarra(contadorA, colA + (larguraColuna - larguraBarra) / 2, posYBarraTopo, larguraBarra, alturaMaxBarra);
centralizarTexto("A", colA, larguraColuna, posYRotulo);
// Exibe o contador B
int colB = 1 * larguraColuna;
String valorB = String(contadorB);
centralizarTexto(valorB, colB, larguraColuna, posYNumero);
desenharBarra(contadorB, colB + (larguraColuna - larguraBarra) / 2, posYBarraTopo, larguraBarra, alturaMaxBarra);
centralizarTexto("B", colB, larguraColuna, posYRotulo);
// Exibe o contador C
int colC = 2 * larguraColuna;
String valorC = String(contadorC);
centralizarTexto(valorC, colC, larguraColuna, posYNumero);
desenharBarra(contadorC, colC + (larguraColuna - larguraBarra) / 2, posYBarraTopo, larguraBarra, alturaMaxBarra);
centralizarTexto("C", colC, larguraColuna, posYRotulo);
// Atualiza o display
display.display();
}
// Função para desenhar a barra vertical
void desenharBarra(int valor, int posX, int posYTopo, int largura, int alturaMaxima) {
// Calcula a altura da barra proporcional ao valor (0 a 100)
int alturaBarra = map(valor, 0, 100, 0, alturaMaxima);
// Calcula a posição Y inicial da barra para que cresça de baixo para cima
int posYBarra = posYTopo + (alturaMaxima - alturaBarra);
// Desenha o retângulo preenchido representando a barra
display.fillRect(posX, posYBarra, largura, alturaBarra, SSD1306_WHITE);
}
// Função auxiliar para centralizar o texto em uma área específica
void centralizarTexto(String texto, int xInicio, int largura, int posY) {
int16_t x1, y1;
uint16_t w, h;
display.getTextBounds(texto, 0, 0, &x1, &y1, &w, &h);
int posX = xInicio + (largura - w) / 2;
display.setCursor(posX, posY);
display.print(texto);
}