// --- ABA PRINCIPAL: sketch.ino ---
// 🔌 CHAVE SELETORA CHIP-TUNING:
// true = Modo RealDash ativo na USB Principal (Textos vão para a Serial3)
// false = Modo Teste/Bancada (Textos em português saem na USB Principal do PC)
const bool MODO_REALDASH = false;
// CHAVE DE CONFIGURAÇÃO DE OPICIONAIS (Habilita/Desabilita Funções)
//Altere para 'false' para desativar os alarmes se o carro não possuir os sensores.
const bool USAR_CINTO_MOTORISTA = false; // true = monitora o pino 13 | 'false' ignora e finge que está ok
const bool USAR_CINTO_PASSAGEIRO = false; // true = monitora pinos 23/24 | 'false' = ignora e finge que está ok
// Estrutura do pacote de dados para o RealDash (Protocolo Serial Customizado - 16 Bytes totais)
struct RealDashFrame {
uint32_t canId; // ID Identificador do pacote (padrão 3200)
uint16_t velocidade; // Velocidade calculada (2 bytes)
uint16_t rpm; // RPM calculado (2 bytes)
uint16_t temperatura; // Temperatura do motor em Celsius (2 bytes)
uint16_t bateria; // Tensão da bateria multiplicada por 10 (2 bytes)
uint16_t economometro;// Índice do economômetro de 0 a 100 (2 bytes)
uint16_t combustivel; // Nível de combustível de 0 a 100% (2 bytes)
uint8_t luzes; // Faróis e setas compactados em bits (1 byte)
uint8_t alarmes; // Portas, capô, óleo, freio e cintos em bits (1 byte)
};
// Pino de Saída PWM para o MOSFET IRF520 (Controlar intensidade dos LEDs de Cortesia)
const int pinoLedCortesia = 44;
// Variáveis para o efeito Fade (Luz de Cortesia)
float brilhoAtualLed = 0;
unsigned long ultimaAtualizacaoLed = 0;
void setup() {
// Inicialização dinâmica baseada no modo escolhido
Serial.begin(115200); // USB Nativa principal
Serial3.begin(115200); // Canal extra para Notebook de debug no modo RealDash
configurarIndicadores(); // Inicializa pinos da aba indicadores.ino
configurarAlarmes(); // Inicializa pinos da aba alarmes.ino
pinMode(pinoLedCortesia, OUTPUT);
analogWrite(pinoLedCortesia, 0);
if (!MODO_REALDASH) {
Serial.println("--- MODO BANCADA ATIVO (Monitor Serial USB Aberto) ---");
} else {
Serial3.println("--- ECU Uno Ativa em Modo RealDash (Monitorando via Serial3) ---");
}
}
void loop() {
unsigned long tempoAtual = millis();
// 1. Coleta as leituras dos sensores tratadas pelas demais abas
int velocidadeAtual = calcularVelocidade();
int rpmDoUno = calcularRPM();
int tempMotor = lerTemperatura();
float tensaoBat = lerTensaoBateria();
int nivelTanque = lerNivelCombustivel();
int econInstantaneo = calcularEconomometro(velocidadeAtual, rpmDoUno);
// 2. Lógica Inteligente da Luz de Cortesia (Efeito Fade Suave)
// Verifica se QUALQUER porta, capô ou porta-malas está aberto
bool cabineAberta = (lerPortaMotorista() || lerPortaCarona() ||
lerPortaTraseiraEsquerda() || lerPortaTraseiraDireita() ||
lerPortaMalas() || lerCapo());
// Atualiza o brilho a cada 5 milissegundos
if (tempoAtual - ultimaAtualizacaoLed >= 5) {
if (cabineAberta && brilhoAtualLed < 255) {
brilhoAtualLed += 2.5; // Acende de forma rápida ao abrir a porta
} else if (!cabineAberta && brilhoAtualLed > 0) {
brilhoAtualLed -= 1.0; // Apaga suavemente (efeito cortesia gradual)
}
brilhoAtualLed = constrain(brilhoAtualLed, 0, 255);
analogWrite(pinoLedCortesia, (int)brilhoAtualLed);
ultimaAtualizacaoLed = tempoAtual;
}
// =========================================================================
// MODO TRANSMISSÃO: CONFIGURAÇÃO DE SAÍDAS DE DADOS
// =========================================================================
if (MODO_REALDASH) {
// -----------------------------------------------------------------------
// ENVIANDO FRAME BINÁRIO PARA O TABLET (VIA SERIAL USB)
// -----------------------------------------------------------------------
RealDashFrame frame;
frame.canId = 3200;
frame.velocidade = velocidadeAtual;
frame.rpm = rpmDoUno;
frame.temperatura = tempMotor;
frame.bateria = (uint16_t)(tensaoBat * 10);
frame.economometro = econInstantaneo;
frame.combustivel = nivelTanque;
// Mapeamento corrigido das Luzes (True se ativo, aciona os bits corretos)
frame.luzes = 0;
if (lerFarolBaixo()) frame.luzes |= (1 << 0);
if (lerFarolAlto()) frame.luzes |= (1 << 1);
if (lerFaroldeMilha()) frame.luzes |= (1 << 2);
if (lerSetaEsquerda()) frame.luzes |= (1 << 3);
if (lerSetaDireita()) frame.luzes |= (1 << 4);
if (lerPartidaFrioBaixo()) frame.luzes |= (1 << 5);
// Mapeamento dos Alarmes e Cintos
frame.alarmes = 0;
if (lerPortaMotorista()) frame.alarmes |= (1 << 0);
if (lerPortaCarona()) frame.alarmes |= (1 << 1);
if (lerPortaTraseiraEsquerda()) frame.alarmes |= (1 << 2);
if (lerPortaTraseiraDireita()) frame.alarmes |= (1 << 3);
if (lerPortaMalas()) frame.alarmes |= (1 << 4);
if (lerCapo()) frame.alarmes |= (1 << 5);
if (lerPressaoOleo()) frame.alarmes |= (1 << 6); // CORRIGIDO: Bit crítico de óleo inserido
// Alarme Geral de Cinto em movimento (> 20 km/h)
if (velocidadeAtual > 20) {
if (lerCintoMotoristaSolto() || (lerBancoCaronaOcupado() && lerCintoCaronaSolto())) {
frame.alarmes |= (1 << 7);
}
}
// Envia o cabeçalho obrigatório do RealDash ("DASH") e o pacote de dados
uint8_t serialBlockHeader[4] = {0x44, 0x41, 0x53, 0x48};
Serial.write(serialBlockHeader, 4);
Serial.write((uint8_t*)&frame, sizeof(RealDashFrame));
// -----------------------------------------------------------------------
// CÓPIA DOS TEXTOS DE DEBUG PARA O NOTEBOOK (VIA SERIAL 3)
// -----------------------------------------------------------------------
Serial3.print("RPM: "); Serial3.print(rpmDoUno);
Serial3.print(" | VEL: "); Serial3.print(velocidadeAtual); Serial3.print(" km/h");
Serial3.print(" | BAT: "); Serial3.print(tensaoBat, 1); Serial3.print("V");
Serial3.print(" | COMB: "); Serial3.print(nivelTanque); Serial3.print("%");
if (lerPressaoOleo()) { Serial3.print(" | [⚠️ PRESSÃO DE ÓLEO BAIXA!]"); }
if (lerFreioDeMao()) { Serial3.print(" | [FREIO DE MÃO]"); }
if (cabineAberta) { Serial3.print(" | [PORTA/CAPÔ ABERTO]"); }
Serial3.println();
} else {
// -----------------------------------------------------------------------
// MODO TEXTO PURO NA USB COMUM (BANCADA / SIMULAÇÃO NO PC)
// -----------------------------------------------------------------------
Serial.print("RPM: "); Serial.print(rpmDoUno);
Serial.print(" | Temp: "); Serial.print(tempMotor);
Serial.print(" | VEL: "); Serial.print(velocidadeAtual); Serial.print(" km/h");
Serial.print(" | BAT: "); Serial.print(tensaoBat, 1); Serial.print("V");
Serial.print(" | ECON: "); Serial.print(econInstantaneo); Serial.print("%");
Serial.print(" | COMB: "); Serial.print(nivelTanque); Serial.print("%");
if (lerFarolBaixo()) { Serial.print(" | Baixo: ON"); }
if (lerFarolAlto()) { Serial.print(" | Alto: ON !!!"); }
if (lerFaroldeMilha()) { Serial.print(" | Milha: ON"); }
if (lerPressaoOleo()) { Serial.print(" | [⚠️ ÓLEO]"); }
if (lerFreioDeMao()) { Serial.print(" | [FREIO MÃO]"); }
if (cabineAberta) { Serial.print(" | [PORTAS ABERTAS]"); }
if (velocidadeAtual > 20) {
if (lerCintoMotoristaSolto()) { Serial.print(" | [⚠️ CINTO MOT.]"); }
if (lerBancoCaronaOcupado() && lerCintoCaronaSolto()) { Serial.print(" | [⚠️ CINTO CARONA]"); }
}
Serial.println();
}
delay(30); // Mantém o ciclo em torno de 33Hz para resposta instantânea na tela
}