#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Fonts/FreeSansBold9pt7b.h>
#include <Fonts/Picopixel.h>
#define ENCODER_CLK 2
#define ENCODER_DT 3
#define ENCODER_SW 4
uint8_t volume = 50;
uint8_t bass = 25;
uint8_t treble = 66;
typedef enum {
SET_VOLUME,
SET_BASS,
SET_TREBLE,
} Mode;
#include <Wire.h>
#include <Adafruit_NeoPixel.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <RTClib.h>
#include <Bounce2.h>
// OLED
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// NeoPixel
#define NUM_PIXELS 8
#define PIN_PIXELS 6
Adafruit_NeoPixel pixels(NUM_PIXELS, PIN_PIXELS, NEO_GRB + NEO_KHZ800);
// RTC
RTC_DS3231 rtc;
// Pinos dos sensores e atuadores
#define MIC1 A0
#define MIC2 A1
#define POT A2
#define BATT_LEVEL A3
// Pinos dos motores
#define MOTOR_OMBRO_ESQ 3
#define MOTOR_OMBRO_DIR 4
#define MOTOR_MEIO_ESQ 5
#define MOTOR_MEIO_DIR 7
#define MOTOR_LATERAL_ESQ 8
#define MOTOR_LATERAL_DIR 9
// Encoder rotativo
#define ENCODER_CLK 2
#define ENCODER_DT 10
#define ENCODER_BTN 11
int encoderPos = 0;
int lastClk = HIGH;
Bounce debouncer = Bounce();
int intensidadeManual = 100;
int nivelSelecionado = 1; // Níveis: 1 = Baixo, 2 = Médio, 3 = Alto
void setup() {
Serial.begin(9600);
// Display OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("Erro no display OLED"));
for (;;);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
// RTC
if (!rtc.begin()) {
Serial.println("Erro no RTC!");
}
// NeoPixels
pixels.begin();
pixels.show();
// Motores
pinMode(MOTOR_OMBRO_ESQ, OUTPUT);
pinMode(MOTOR_OMBRO_DIR, OUTPUT);
pinMode(MOTOR_MEIO_ESQ, OUTPUT);
pinMode(MOTOR_MEIO_DIR, OUTPUT);
pinMode(MOTOR_LATERAL_ESQ, OUTPUT);
pinMode(MOTOR_LATERAL_DIR, OUTPUT);
// Encoder
pinMode(ENCODER_CLK, INPUT_PULLUP);
pinMode(ENCODER_DT, INPUT_PULLUP);
pinMode(ENCODER_BTN, INPUT_PULLUP);
debouncer.attach(ENCODER_BTN);
debouncer.interval(25);
}
void loop() {
// === Leitura do Encoder ===
int currentClk = digitalRead(ENCODER_CLK);
if (currentClk != lastClk && currentClk == LOW) {
if (digitalRead(ENCODER_DT) == HIGH) {
nivelSelecionado++;
} else {
nivelSelecionado--;
}
nivelSelecionado = constrain(nivelSelecionado, 1, 3);
}
lastClk = currentClk;
debouncer.update();
if (debouncer.fell()) {
// Resetar intensidade manual para o nível selecionado
switch (nivelSelecionado) {
case 1: intensidadeManual = 80; break;
case 2: intensidadeManual = 150; break;
case 3: intensidadeManual = 255; break;
}
}
// === Leitura dos sensores ===
int mic1 = analogRead(MIC1);
int mic2 = analogRead(MIC2);
int batt = analogRead(BATT_LEVEL);
// === Acionamento dos motores ===
bool som1 = mic1 > 550;
bool som2 = mic2 > 550;
analogWrite(MOTOR_OMBRO_ESQ, som1 ? intensidadeManual : 0);
analogWrite(MOTOR_OMBRO_DIR, som2 ? intensidadeManual : 0);
analogWrite(MOTOR_MEIO_ESQ, som1 ? intensidadeManual : 0);
analogWrite(MOTOR_MEIO_DIR, som2 ? intensidadeManual : 0);
analogWrite(MOTOR_LATERAL_ESQ, som1 ? intensidadeManual : 0);
analogWrite(MOTOR_LATERAL_DIR, som2 ? intensidadeManual : 0);
// === NeoPixels ===
int brilho = map(max(mic1, mic2), 0, 1023, 0, 255);
for (int i = 0; i < NUM_PIXELS; i++) {
pixels.setPixelColor(i, pixels.Color(brilho, 255 - brilho, 100));
}
pixels.show();
// === Display OLED ===
DateTime now = rtc.now();
display.clearDisplay();
display.setCursor(0, 0);
display.print("Mic1: "); display.println(mic1);
display.print("Mic2: "); display.println(mic2);
display.print("Intensidade: "); display.println(intensidadeManual);
display.print("Nivel: ");
switch (nivelSelecionado) {
case 1: display.println("Baixo"); break;
case 2: display.println("Medio"); break;
case 3: display.println("Alto"); break;
}
display.print("Bateria: ");
display.print(map(batt, 0, 1023, 0, 100));
display.println("%");
display.print("Hora: ");
if (now.hour() < 10) display.print("0");
display.print(now.hour());
display.print(":");
if (now.minute() < 10) display.print("0");
display.print(now.minute());
display.display();
delay(100);
}
Adafruit_SSD1306 display(128, 64, &Wire, -1);
void nextMode() {
switch (mode) {
case SET_VOLUME:
mode = SET_BASS;
break;
case SET_BASS:
mode = SET_TREBLE;
break;
case SET_TREBLE:
mode = SET_VOLUME;
break;
}
}
void updateValue(int delta) {
switch (mode) {
case SET_VOLUME:
volume = constrain(volume + delta, 0, 100);
break;
case SET_BASS:
bass = constrain(bass + delta, 0, 100);
break;
case SET_TREBLE:
treble = constrain(treble + delta, 0, 100);
break;
}
}
void updateDisplay() {
display.clearDisplay();
display.setFont();
display.setTextColor(1);
display.setCursor(42, 2);
display.print("Volume");
display.drawRoundRect(10, 12, 102, 9, 2, WHITE);
display.fillRect(11, 13, volume, 7, WHITE);
if (mode == SET_VOLUME) {
display.setCursor(32, 2);
display.print(">");
}
display.setCursor(48, 22);
display.print("Bass");
display.drawRoundRect(10, 32, 102, 9, 2, WHITE);
display.fillRect(11, 33, bass, 7, WHITE);
if (mode == SET_BASS) {
display.setCursor(38, 22);
display.print(">");
}
display.setCursor(42, 42);
display.print("Treble");
display.drawRoundRect(10, 52, 102, 9, 2, WHITE);
display.fillRect(11, 53, treble, 7, WHITE);
if (mode == SET_TREBLE) {
display.setCursor(32, 42);
display.print(">");
}
display.display();
}
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
pinMode(ENCODER_CLK, INPUT);
pinMode(ENCODER_DT, INPUT);
pinMode(ENCODER_SW, INPUT_PULLUP);
updateDisplay();
}
long int modeLastChanged = 0;
int prevClk = HIGH;
void loop() {
if (digitalRead(ENCODER_SW) == LOW && millis() - modeLastChanged > 300) {
modeLastChanged = millis();
nextMode();
updateDisplay();
}
int clk = digitalRead(ENCODER_CLK);
if (clk != prevClk && clk == LOW) {
int dt = digitalRead(ENCODER_DT);
int delta = dt == HIGH ? 5 : -5;
updateValue(delta);
updateDisplay();
}
prevClk = clk;
}