#include <SD.h>
#include <SPI.h>
#include <Bounce2.h>
// #include <Adafruit_GFX.h>
// #include <Adafruit_SSD1306.h>
// #define SCREEN_WIDTH 128 // OLED display width, in pixels
// #define SCREEN_HEIGHT 64 // OLED display height, in pixels
// // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
// Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define BUTTON1_PIN 2
#define BUTTON2_PIN 3
#define BUTTON3_PIN 4
#define LONG_PRESS_TIME 1000 // Tempo em milissegundos para considerar um pressionamento longo
#define CLICK_INTERVAL 500 // Intervalo máximo em milissegundos entre cliques para considerar duplo ou triplo clique
Bounce debouncer1 = Bounce();
Bounce debouncer2 = Bounce();
Bounce debouncer3 = Bounce();
unsigned long pressStartTime1 = 0;
unsigned long pressStartTime2 = 0;
unsigned long pressStartTime3 = 0;
int clickCount1 = 0;
int clickCount2 = 0;
int clickCount3 = 0;
bool longPressDetected1 = false;
bool longPressDetected2 = false;
bool longPressDetected3 = false;
bool simultaneousPressDetected12 = false;
bool simultaneousPressDetected23 = false;
// Estrutura para armazenar type, val e channel
struct ButtonAction {
int type;
int val;
int channel;
};
ButtonAction buttonActions[3][3][3];
// Variável para armazenar o banco atual
int currentBank = 1;
const int maxBank = 3;
int lastStateFxPot = 0; // Último valor lido do potenciômetro
#define POT_PIN A0 // Pino analógico para o potenciômetro
void setup() {
pinMode(BUTTON1_PIN, INPUT_PULLUP);
pinMode(BUTTON2_PIN, INPUT_PULLUP);
pinMode(BUTTON3_PIN, INPUT_PULLUP);
debouncer1.attach(BUTTON1_PIN);
debouncer2.attach(BUTTON2_PIN);
debouncer3.attach(BUTTON3_PIN);
debouncer1.interval(25);
debouncer2.interval(25);
debouncer3.interval(25);
Serial.begin(9600);
// Inicializar o cartão SD
if (!SD.begin(10)) { // Substitua 10 pelo pino CS do seu módulo SD
Serial.println("Falha ao inicializar o cartão SD!");
return;
}
// Ler o arquivo de texto
File file = SD.open("/b1.txt");
if (!file) {
Serial.println("Erro ao abrir o arquivo!");
return;
}
// Ler linha por linha
while (file.available()) {
String line = file.readStringUntil('\n');
line.trim(); // Remove espaços em branco extras no início e no fim
if (line.length() > 0) {
parseLine(line);
}
}
file.close();
// // Inicializa o display
// if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
// Serial.println(F("Falha ao inicializar o display OLED"));
// for(;;); // Travar aqui em caso de falha
// }
// display.clearDisplay();
// display.setTextSize(2);
// display.setTextColor(SSD1306_WHITE);
}
void parseLine(String line) {
int buttonIndex = -1;
int bank = 0;
int clickType = 0;
int val = 0;
int channel = 0;
// Quebrar a linha por vírgulas
char buffer[line.length() + 1];
line.toCharArray(buffer, sizeof(buffer));
char* token = strtok(buffer, ",");
if (strcmp(token, "BUTTON1") == 0) {
buttonIndex = 0;
} else if (strcmp(token, "BUTTON2") == 0) {
buttonIndex = 1;
} else if (strcmp(token, "BUTTON3") == 0) {
buttonIndex = 2;
}
if (buttonIndex != -1) {
token = strtok(NULL, ",");
bank = atoi(token);
token = strtok(NULL, ",");
clickType = atoi(token);
token = strtok(NULL, ",");
val = atoi(token);
token = strtok(NULL, ",");
channel = atoi(token);
// Armazenar as ações no array buttonActions
buttonActions[buttonIndex][bank - 1][clickType - 1] = { clickType, val, channel };
}
}
void loop() {
debouncer1.update();
debouncer2.update();
debouncer3.update();
handleButton(debouncer1, pressStartTime1, clickCount1, longPressDetected1, BUTTON1_PIN, "Botão 1");
handleButton(debouncer2, pressStartTime2, clickCount2, longPressDetected2, BUTTON2_PIN, "Botão 2");
handleButton(debouncer3, pressStartTime3, clickCount3, longPressDetected3, BUTTON3_PIN, "Botão 3");
handleSimultaneousPress();
// Leitura e mapeamento do potenciômetro
int potValue = analogRead(POT_PIN);
int mapPot = constrain(map(potValue, 0, 1023, 0, 127), 0, 127);
// Verifica se a mudança é significativa
if (abs(mapPot - lastStateFxPot) > 1) {
Serial.print("Leitura = ");
Serial.print(mapPot);
Serial.print(" | Último = ");
Serial.println(lastStateFxPot);
}
// Atualiza o último estado
lastStateFxPot = mapPot;
//BUTTONX, banco, tipo de clique, valor, canal.
delay(10); // Pequeno delay para evitar muitas leituras consecutivas
}
// Matriz para armazenar as ações simultâneas
ButtonAction simultaneousActions[2][5] = {
{
{10, 200, 1}, {11, 210, 2}, {12, 220, 3} // Botões 1 e 2
},
{
{15, 250, 1}, {16, 260, 2}, {17, 270, 3} // Botões 2 e 3
}
};
ButtonAction getActionForButtonAndBank(int buttonPin, int clickCount) {
int buttonIndex = -1;
// Determina o índice do botão com base no pino
if (buttonPin == BUTTON1_PIN) {
buttonIndex = 0;
} else if (buttonPin == BUTTON2_PIN) {
buttonIndex = 1;
} else if (buttonPin == BUTTON3_PIN) {
buttonIndex = 2;
}
// Se o botão for válido, retorna a ação correspondente ao banco e clique atual
if (buttonIndex != -1 && clickCount >= 1 && clickCount <= 3) {
return buttonActions[buttonIndex][currentBank - 1][clickCount - 1];
}
// Retorna uma ação inválida se o botão ou clickCount for inválido
return { -1, -1, -1 };
}
ButtonAction getSimultaneousAction(int button1, int button2) {
if (button1 == BUTTON1_PIN && button2 == BUTTON2_PIN) {
return simultaneousActions[0][currentBank - 1]; // Ação para Botões 1 e 2
} else if (button1 == BUTTON2_PIN && button2 == BUTTON3_PIN) {
return simultaneousActions[1][currentBank - 1]; // Ação para Botões 2 e 3
}
// Retorna uma ação inválida se a combinação for inválida
return { -1, -1, -1 };
}
void processClicks(int clickCount, const char *buttonName, int buttonPin) {
ButtonAction action = getActionForButtonAndBank(buttonPin, clickCount);
if (clickCount == 1) {
Serial.print(buttonName);
Serial.print(": Clique simples detectado! Type: ");
} else if (clickCount == 2) {
Serial.print(buttonName);
Serial.print(": Duplo clique detectado! Type: ");
} else if (clickCount == 3) {
Serial.print(buttonName);
Serial.print(": Triplo clique detectado! Type: ");
}
Serial.print(action.type);
Serial.print(", Val: ");
Serial.print(action.val);
Serial.print(", Channel: ");
Serial.println(action.channel);
}
void handleSimultaneousPress() {
if (debouncer2.fell() && debouncer1.read() == LOW) {
simultaneousPressDetected12 = true;
ButtonAction action = getSimultaneousAction(BUTTON1_PIN, BUTTON2_PIN);
Serial.print("Botão 1 e Botão 2 pressionados simultaneamente! Type: ");
Serial.print(action.type);
Serial.print(", Val: ");
Serial.print(action.val);
Serial.print(", Channel: ");
Serial.println(action.channel);
clickCount1 = 0;
clickCount2 = 0;
}
if (debouncer2.fell() && debouncer3.read() == LOW) {
simultaneousPressDetected23 = true;
ButtonAction action = getSimultaneousAction(BUTTON2_PIN, BUTTON3_PIN);
Serial.print("Botão 2 e Botão 3 pressionados simultaneamente! Type: ");
Serial.print(action.type);
Serial.print(", Val: ");
Serial.print(action.val);
Serial.print(", Channel: ");
Serial.println(action.channel);
clickCount2 = 0;
clickCount3 = 0;
}
}
void displayBank() {
Serial.println(currentBank);
// display.clearDisplay();
// display.setCursor(0,0);
// display.print("Banco: ");
// display.print(currentBank);
// display.display();
}
void handleButton(Bounce &debouncer, unsigned long &pressStartTime, int &clickCount, bool &longPressDetected, int buttonPin, const char *buttonName) {
if (debouncer.fell()) {
pressStartTime = millis();
clickCount++;
longPressDetected = false;
simultaneousPressDetected12 = false;
simultaneousPressDetected23 = false;
}
if (debouncer.read() == LOW) {
unsigned long pressDuration = millis() - pressStartTime;
if (pressDuration >= LONG_PRESS_TIME && !longPressDetected) {
if (buttonPin == BUTTON1_PIN && currentBank > 1) {
currentBank--;
displayBank();
}
if (buttonPin == BUTTON3_PIN && currentBank < maxBank) {
currentBank++;
displayBank();
}
longPressDetected = true;
Serial.print(buttonName);
Serial.println(": Pressionamento longo detectado!");
clickCount = 0; // Reset click count to avoid triggering simple click
}
} else if (debouncer.rose() && !longPressDetected) {
if (millis() - pressStartTime <= LONG_PRESS_TIME) {
// Do nothing for now, will be handled in click processing
}
} else {
if (millis() - pressStartTime > CLICK_INTERVAL && clickCount > 0 && !longPressDetected && !simultaneousPressDetected12 && !simultaneousPressDetected23) {
processClicks(clickCount, buttonName, buttonPin);
clickCount = 0;
}
}
}