#include "Arduino.h" #include "PCF8574.h" // --- Definições para os Andares --- #define DESTINO_TERREO 1 #define DESTINO_ANDAR1 2 #define DESTINO_TERRACO 3 // --- Definições para os Estados do Elevador --- #define ESTADO_PARADO 0 #define ESTADO_TRABALHANDO 1 #define ESTADO_ERRO 2 // Opcional: para futuros estados de erro // --- Definições para as Posições do Elevador --- #define POSICAO_DESCONHECIDO 0 #define POSICAO_TERREO 1 #define POSICAO_ANDAR1 2 #define POSICAO_TERRACO 3 // --- Definições para os pinos de ENTRADA (PCF8574_1) --- #define FIM_CURSO_TERREO_PRINCIPAL 0 // P0 - Entrada 1 (do PCF8574_1) #define FIM_CURSO_TERREO_PARADA_SUAVE 1 // P1 - Entrada 2 #define FIM_CURSO_ANDAR1_PARADA_BAIXO 2 // P2 - Entrada 3 #define FIM_CURSO_ANDAR1_PRINCIPAL 3 // P3 - Entrada 4 #define FIM_CURSO_ANDAR1_PARADA_CIMA 4 // P4 - Entrada 5 #define FIM_CURSO_TERRACO_PARADA_BAIXO 5 // P5 - Entrada 6 #define FIM_CURSO_TERRACO_PRINCIPAL 6 // P6 - Entrada 7 #define FIM_CURSO_TERRACO_EMERGENCIA 7 // P7 - Entrada 8 // --- Definições para os pinos de ENTRADA (PCF8574_2) --- #define SENSOR_FISICO_PORTAS 0 // P0 - Entrada 9 (do PCF8574_2) #define BOTAO_CHAMADA_TERRACO 4 // P4 - Entrada 13 #define BOTAO_CHAMADA_ANDAR1 5 // P5 - Entrada 14 #define BOTAO_CHAMADA_TERREO 6 // P6 - Entrada 15 #define ENTRADA_VERIFICACAO 7 // P7 - Entrada 16 // Os pinos P1, P2, P3 do 0x21 (Entradas 10, 11, 12) não têm defines específicos de leitura, o que está de acordo. // Se precisar de acesso direto a eles no loop, você ainda pode usar pcf8574_2.digitalRead(P1), etc. // --- Definições para os pinos de SAÍDA (PCF8574_3) --- #define RELE_GIRA_PARA_MOTOR 0 // P0 - Relé 1 #define RELE_SENTIDO_GIRO_SOBE_DESCE 1 // P1 - Relé 2 #define RELE_JOG_AJUSTE_FINO 2 // P2 - Relé 3 #define RELE_PARADA_EMERGENCIAL 3 // P3 - Relé 4 // P4 e P5 (Relés 5 e 6) - (sem nome específico) #define SIRENE_ERRO 6 // P6 - Relé 7 #define RELE_CONTATORA 7 // P7 - Relé 8 // --- Variáveis de controle para os modos/sub-modos --- // --- Definições de TEMPO (em milissegundos) --- const unsigned long INTERVALO_TENTATIVA = 200; // Tempo entre tentativas de RF (200ms) const unsigned long INTERVALO_TENTATIVA_RF = 10; // Intervalo para o loop de retentativas RF const unsigned long TIMEOUT_ACK_POR_TENTATIVA = 500; // Tempo máximo para esperar um ACK em cada tentativa const unsigned long TIMEOUT_ABERTURA_FISICA = 5000; // Tempo máximo para as portas abrirem fisicamente (5 segundos) const unsigned long TIMEOUT_FECHAMENTO_FISICO = 5000; // Tempo máximo para as portas fecharem fisicamente (5 segundos) const unsigned long TIMEOUT_VERIFICACAO_FINAL_FISICA = 10000; // Tempo limite para verificação final das portas (10 segundos) // Estes timeout v s de movimento devem ser ajustados conforme o tempo real de viagem do seu elevador const unsigned long TIMEOUT_MOVIMENTO_ANDAR1_TERREO = 30000; // Exemplo: 30 segundos const unsigned long TIMEOUT_MOVIMENTO_TERRACO_TERREO = 50000; // Exemplo: 50 segundos const unsigned long TIMEOUT_MOVIMENTO_TERRACO_ANDAR1 = 30000; // Exemplo: 30 segundos const unsigned long TIMEOUT_MOVIMENTO_TERREO_ANDAR1 = 30000; // Exemplo: 30 segundos const unsigned long TIMEOUT_MOVIMENTO_ANDAR1_TERRACO = 30000; // Exemplo: 30 segundos const unsigned long TIMEOUT_MOVIMENTO_TERREO_TERRACO = 50000; // Exemplo: 50 segundos const unsigned long TIMEOUT_MOVIMENTO_DESCONHECIDO_TERREO = 60000; // Exemplo: 60 segundos para posição desconhecida // Variáveis Globais int EstadoElevador = ESTADO_PARADO; // Inicializa o elevador como PARADO int PosicaoElevador = POSICAO_DESCONHECIDO; // Inicializa a posição como DESCONHECIDO para segurança int logError = 0; // Variável para armazenar códigos de erro // ENTRADAS IC2 DA PLACA PCF8574 pcf8574_1(0x22,4,5); // channel 1-8 address: 100010 PCF8574 pcf8574_2(0x21,4,5); //channel 9-16 address: 100001 // SAIDAS IC2 DA PLACA PCF8574 pcf8574_3(0x24,4,5); // Saídas 1-8 no endereço 0x24 PCF8574 pcf8574_4(0x25,4,5); // Saídas 9-16 no endereço 0x25 // --- PROTÓTIPOS DAS FUNÇÕES --- // Declaração das funções ANTES do setup() para que possam ser chamadas. void turnAllRelaysOff(); void CHAMADO_INICIAR(int destino); void DESCER_ANDAR1_TERREO(); void DESCER_TERRACO_TERREO(); void DESCER_TERRACO_ANDAR1(); void SUBIR_TERREO_ANDAR1(); void SUBIR_ANDAR1_TERRACO(); void SUBIR_TERREO_TERRACO(); void DESCER_DESCONHECIDO_TERREO(); bool VERIFICACAO_PORTAS(); bool FECHAR_PORTAS_RF(); void ABRIR_PORTAS(); void LOG_ERROR(int errorCode); void setup() { Serial.begin(115200); delay(1000); // Configuração dos pinos de ENTRADA pcf8574_1.pinMode(P0, INPUT_PULLUP); pcf8574_1.pinMode(P1, INPUT_PULLUP); pcf8574_1.pinMode(P2, INPUT_PULLUP); pcf8574_1.pinMode(P3, INPUT_PULLUP); pcf8574_1.pinMode(P4, INPUT_PULLUP); pcf8574_1.pinMode(P5, INPUT_PULLUP); pcf8574_1.pinMode(P6, INPUT_PULLUP); pcf8574_1.pinMode(P7, INPUT_PULLUP); pcf8574_2.pinMode(P0, INPUT_PULLUP); pcf8574_2.pinMode(P1, INPUT_PULLUP); pcf8574_2.pinMode(P2, INPUT_PULLUP); pcf8574_2.pinMode(P3, INPUT_PULLUP); pcf8574_2.pinMode(P4, INPUT_PULLUP); pcf8574_2.pinMode(P5, INPUT_PULLUP); pcf8574_2.pinMode(P6, INPUT_PULLUP); pcf8574_2.pinMode(P7, INPUT_PULLUP); // Configuração dos pinos de SAÍDA pcf8574_3.pinMode(P0, OUTPUT); pcf8574_3.pinMode(P1, OUTPUT); pcf8574_3.pinMode(P2, OUTPUT); pcf8574_3.pinMode(P3, OUTPUT); pcf8574_3.pinMode(P4, OUTPUT); pcf8574_3.pinMode(P5, OUTPUT); pcf8574_3.pinMode(P6, OUTPUT); pcf8574_3.pinMode(P7, OUTPUT); pcf8574_4.pinMode(P0, OUTPUT); pcf8574_4.pinMode(P1, OUTPUT); pcf8574_4.pinMode(P2, OUTPUT); pcf8574_4.pinMode(P3, OUTPUT); pcf8574_4.pinMode(P4, OUTPUT); pcf8574_4.pinMode(P5, OUTPUT); pcf8574_4.pinMode(P6, OUTPUT); pcf8574_4.pinMode(P7, OUTPUT); // Inicialização dos módulos I2C Serial.print("Init pcf8574_1..."); if (pcf8574_1.begin()){ Serial.println("pcf8574_1_OK"); }else{ Serial.println("pcf8574_1_KO"); } Serial.print("Init pcf8574_2..."); if (pcf8574_2.begin()){ Serial.println("pcf8574_2_OK"); }else{ Serial.println("pcf8574_2_KO"); } Serial.print("Init pcf8574_3..."); if (pcf8574_3.begin()){ Serial.println("pcf8574_3_OK"); }else{ Serial.println("pcf8574_3_KO"); } Serial.print("Init pcf8574_4..."); if (pcf8574_4.begin()){ Serial.println("pcf8574_4_OK"); }else{ Serial.println("pcf8574_4_KO"); } // Estado inicial: Desliga todos os relés na inicialização turnAllRelaysOff(); Serial.println("\n--- Sistema Pronto ---"); Serial.println("Aguardando chamado do elevador."); } void loop() { // Leitura e atualização da posição ATUAL VERIFICAR_POSICAO_ATUAL(); // LEITURA DE ESTADOS DAS CHAMADAS // Entradas do PCF8574_2 // Agora, com as suas macros corrigidas, você lê o pino do PCF8574_2 // usando pcf8574_2.digitalRead() e passando a macro (que agora é o número do pino) uint8_t leitura_BOTAO_CHAMADA_TERRACO = pcf8574_2.digitalRead(BOTAO_CHAMADA_TERRACO); uint8_t leitura_BOTAO_CHAMADA_ANDAR1 = pcf8574_2.digitalRead(BOTAO_CHAMADA_ANDAR1); uint8_t leitura_BOTAO_CHAMADA_TERREO = pcf8574_2.digitalRead(BOTAO_CHAMADA_TERREO); // Aqui vai a logica para ler SINAIS RF de chamada. // Aqui vai ser adicionado o primeiro conjunto de IFs, que serão responsáveis por enviar o destino para CHAMADA_INICIADA como a origem da chamada. // IF que chamará a FUNÇÃO ELEVADOR DESTINO TERREO --- // Apenas um botão de chamada será processado por vez. // A lógica de 'if/else if' para os botões continua correta, // assumindo que os botões puxam o pino para LOW quando pressionados (active-low). if (leitura_BOTAO_CHAMADA_TERREO == LOW) { Serial.println("Botão de Chamada Terreo Pressionado! Iniciando CHAMADO_INICIAR(DESTINO_TERREO)"); CHAMADO_INICIAR(DESTINO_TERREO); } else if (leitura_BOTAO_CHAMADA_ANDAR1 == LOW) { Serial.println("Botão de Chamada Andar 1 Pressionado! Iniciando CHAMADO_INICIAR(DESTINO_ANDAR1)"); CHAMADO_INICIAR(DESTINO_ANDAR1); } else if (leitura_BOTAO_CHAMADA_TERRACO == LOW) { Serial.println("Botão de Chamada Terraco Pressionado! Iniciando CHAMADO_INICIAR(DESTINO_TERRACO)"); CHAMADO_INICIAR(DESTINO_TERRACO); } delay(300); // Pequeno atraso para estabilização e evitar spam no serial } void CHAMADO_INICIAR(int destino) { Serial.print("CHAMADO_INICIAR acionada para o destino: "); // 1. Atualiza o EstadoElevador para TRABALHANDO EstadoElevador = ESTADO_TRABALHANDO; Serial.print("Estado do Elevador: "); if (EstadoElevador == ESTADO_TRABALHANDO) { Serial.println("TRABALHANDO"); } else { // Nunca deve cair aqui se a linha acima for executada Serial.println("ERRO_ESTADO"); } // 2. Obtém e exibe o valor da variável global PosicaoElevador Serial.print("Posição Atual do Elevador (antes do movimento): "); if (PosicaoElevador == POSICAO_TERREO) { Serial.println("TERREO"); } else if (PosicaoElevador == POSICAO_ANDAR1) { Serial.println("ANDAR 1"); } else if (PosicaoElevador == POSICAO_TERRACO) { Serial.println("TERRACO"); } else { // POSICAO_DESCONHECIDO ou outro valor Serial.println("DESCONHECIDO"); // NOVO: Chama DESCOBRIR_POSICAO se a posição for desconhecida DESCOBRIR_POSICAO(); // Após DESCOBRIR_POSICAO, o elevador deverá estar no térreo ou a posição definida. // É crucial reavaliar a posição aqui, pois ela pode ter mudado para TERREO. Serial.print("Posição após tentativa de descoberta: "); if (PosicaoElevador == POSICAO_TERREO) { Serial.println("TERREO"); } else if (PosicaoElevador == POSICAO_ANDAR1) { // Pode ser Andar 1 se o sensor estava ativo Serial.println("ANDAR 1"); } else if (PosicaoElevador == POSICAO_TERRACO) { // Pode ser Terraço se o sensor estava ativo Serial.println("TERRACO"); } else { Serial.println("AINDA DESCONHECIDO OU EM ERRO!"); // Se o erro persistir após a descoberta // Considerar uma ação de segurança ou alarme aqui return; // Sai da função CHAMADO_INICIAR se a posição ainda for desconhecida/erro } } // Lógica para destino TERREO if (destino == DESTINO_TERREO) { Serial.println("TERREO"); // *** NOVA LÓGICA PARA DESTINO TERREO *** if (PosicaoElevador == POSICAO_TERREO) { Serial.println("Já no Térreo. Abrindo portas..."); ABRIR_PORTAS(); } else if (PosicaoElevador == POSICAO_ANDAR1) { Serial.println("No Andar 1. Iniciando descida para o Térreo..."); DESCER_ANDAR1_TERREO(); } else if (PosicaoElevador == POSICAO_TERRACO) { Serial.println("No Terraço. Iniciando descida para o Térreo..."); DESCER_TERRACO_TERREO(); } else { // Posição Desconhecida ou Inesperada Serial.println("Posição desconhecida. Tentando descer para o Térreo de forma segura..."); // Aqui você pode adicionar uma lógica de recuperação ou ir para uma posição de segurança. // Por enquanto, vamos assumir que ele tentaria descer como se estivesse no terraço. DESCER_TERRACO_TERREO(); // OU chamar uma função de "busca pelo térreo" } // Logica para o destino ANDAR1 } else if (destino == DESTINO_ANDAR1) { Serial.println("ANDAR 1"); // *** NOVA LÓGICA PARA DESTINO ANDAR 1 *** if (PosicaoElevador == POSICAO_ANDAR1) { Serial.println("Já no Andar 1. Abrindo portas..."); ABRIR_PORTAS(); } else if (PosicaoElevador == POSICAO_TERRACO) { Serial.println("No Terraço. Iniciando descida para o Andar 1..."); DESCER_TERRACO_ANDAR1(); } else if (PosicaoElevador == POSICAO_TERREO) { Serial.println("No Térreo. Iniciando subida para o Andar 1..."); SUBIR_TERREO_ANDAR1(); } else { // Posição Desconhecida ou Inesperada Serial.println("Posição desconhecida. Tentando ir para o Terraço de forma segura..."); // Você pode adicionar uma lógica de "busca" pelo terraço aqui. // Por enquanto, vamos assumir que ele tentaria subir do térreo. // OU chamar uma função de "busca pelo terraço" } // Lógica para o destino TERRAÇO } else if (destino == DESTINO_TERRACO) { Serial.println("TERRACO"); // *** NOVA LÓGICA PARA DESTINO TERRAÇO *** if (PosicaoElevador == POSICAO_TERRACO) { Serial.println("Já no Terraço. Abrindo portas..."); ABRIR_PORTAS(); } else if (PosicaoElevador == POSICAO_ANDAR1) { Serial.println("No Andar 1. Iniciando subida para o Terraço..."); SUBIR_ANDAR1_TERRACO(); } else if (PosicaoElevador == POSICAO_TERREO) { Serial.println("No Térreo. Iniciando subida para o Terraço..."); SUBIR_TERREO_TERRACO(); } else { // Posição Desconhecida ou Inesperada Serial.println("Posição desconhecida. Tentando ir para o Terraço de forma segura..."); // Você pode adicionar uma lógica de "busca" pelo terraço aqui. // Por enquanto, vamos assumir que ele tentaria subir do térreo. SUBIR_TERREO_TERRACO(); // OU chamar uma função de "busca pelo terraço" } } else { Serial.println("DESTINO DESCONHECIDO!"); } // A lógica de movimento real do elevador virá aqui, com base na PosicaoElevador atual e no 'destino'. // IMPORTANTE: No final do movimento, você precisará definir EstadoElevador = ESTADO_PARADO; // e PosicaoElevador = (a nova posição). } // FUNÇÃO PARA DESCER O ELEVADOR DO TERRAÇO PARA O ANDAR 1 void DESCER_TERRACO_ANDAR1() { Serial.println("DEBUG: Funcao DESCER_TERRACO_ANDAR1 acionada."); // Primeiro, chamar a função para fechar as portas via RF. FECHAR_PORTAS_RF(); // Em seguida, verifica se as portas estão fisicamente fechadas. // VERIFICACAO_PORTAS() já vai verificar o logError definido por FECHAR_PORTAS_RF(). if (!VERIFICACAO_PORTAS()) { Serial.println("DESCER_TERRACO_ANDAR1 abortada devido a problema na porta."); EstadoElevador = ESTADO_PARADO; // Garante que o elevador está parado em caso de falha na porta return; // Sai da função se a verificação falhar } Serial.println("Iniciando descida do Terraço para o Andar 1..."); // Inicializa o tempo para o timeout geral de movimento unsigned long startTimeMovimento = millis(); const unsigned long TIMEOUT_MOVIMENTO_TERRACO_ANDAR1 = 30000; // 30 segundos de timeout total // 1. Liga RELE_GIRA_PARA_MOTOR e RELE_SENTIDO_GIRO_SOBE_DESCE (para descer) pcf8574_3.digitalWrite(RELE_GIRA_PARA_MOTOR, HIGH); // Liga o motor pcf8574_3.digitalWrite(RELE_SENTIDO_GIRO_SOBE_DESCE, LOW); // Define sentido para descer (assumindo LOW) Serial.println("Motor ligado em sentido de descida."); // 2. Aguarda FIM_CURSO_ANDAR1_PARADA_CIMA ser ACIONADO (ou seja, ler HIGH) // E verifica se o principal não foi ACIONADO por acidente (passou direto) Serial.println("Aguardando FIM_CURSO_ANDAR1_PARADA_CIMA ser acionado para iniciar parada suave..."); // CORRIGIDO: Agora usando pcf8574_1.digitalRead() para o sensor de fim de curso while (pcf8574_1.digitalRead(FIM_CURSO_ANDAR1_PARADA_CIMA) == LOW) { // Enquanto o sensor de parada suave NÃO estiver ACIONADO (ler LOW) // Verifica o timeout geral do movimento if (millis() - startTimeMovimento > TIMEOUT_MOVIMENTO_TERRACO_ANDAR1) { Serial.println("ERRO 21: Timeout geral atingido antes de FIM_CURSO_ANDAR1_PARADA_CIMA."); LOG_ERROR(21); return; } // Verifica se o sensor principal foi ACIONADO inesperadamente (passou direto pelo parada suave) // CORRIGIDO: Agora usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_ANDAR1_PRINCIPAL) == HIGH) { // Se o sensor principal ESTIVER ACIONADO (ler HIGH) Serial.println("ALERTA: FIM_CURSO_ANDAR1_PRINCIPAL ativado antes do esperado! Parada de emergencia."); PosicaoElevador = POSICAO_ANDAR1; // Assume que chegou, mas com anomalia LOG_ERROR(41); ABRIR_PORTAS (); return; } delay(10); // Pequeno atraso } Serial.println("FIM_CURSO_ANDAR1_PARADA_CIMA acionado. Iniciando transicao para parada suave."); // 3. Desliga SOMENTE o RELE_GIRA_PARA_MOTOR pcf8574_3.digitalWrite(RELE_GIRA_PARA_MOTOR, LOW); // Desliga o motor principal Serial.println("RELE_GIRA_PARA_MOTOR desligado. Iniciando contagem de 3 segundos com monitoramento do sensor principal."); // 4. Aguarda 3 segundos OU até FIM_CURSO_ANDAR1_PRINCIPAL ser ACIONADO unsigned long startTimeJogDelay = millis(); while (millis() - startTimeJogDelay < 3000) { // Verifica o timeout geral durante o atraso if (millis() - startTimeMovimento > TIMEOUT_MOVIMENTO_TERRACO_ANDAR1) { Serial.println("ERRO 21: Timeout geral atingido durante delay para RELE_JOG."); LOG_ERROR(21); return; } // VERIFICACAO CONSTANTE DO SENSOR PRINCIPAL DURANTE OS 3 SEGUNDOS // CORRIGIDO: Agora usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_ANDAR1_PRINCIPAL) == HIGH) { // Se o sensor principal ESTIVER ACIONADO (ler HIGH) Serial.println("FIM_CURSO_ANDAR1_PRINCIPAL acionado durante os 3 segundos de delay! Parando."); break; // Sai do loop de 3 segundos, indo direto para a parada final } delay(10); } // Após o loop de 3 segundos, verifica novamente se o sensor principal já foi acionado // CORRIGIDO: Agora usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_ANDAR1_PRINCIPAL) == HIGH) { // Se o sensor principal já estiver ACIONADO Serial.println("FIM_CURSO_ANDAR1_PRINCIPAL ja acionado. Finalizando movimento sem JOG."); pcf8574_3.digitalWrite(RELE_PARADA_EMERGENCIAL, HIGH); PosicaoElevador = POSICAO_ANDAR1; EstadoElevador = ESTADO_PARADO; logError = 0; ABRIR_PORTAS(); pcf8574_3.digitalWrite(RELE_PARADA_EMERGENCIAL, LOW); pcf8574_3.digitalWrite(RELE_SENTIDO_GIRO_SOBE_DESCE, LOW); return; // Sai da função, pois já chegou } // 5. Liga RELE_JOG_AJUSTE_FINO (mantendo RELE_SENTIDO_GIRO_SOBE_DESCE ligado) pcf8574_3.digitalWrite(RELE_JOG_AJUSTE_FINO, HIGH); // Liga o ajuste fino (JOG) Serial.println("RELE_JOG_AJUSTE_FINO ligado. Movimento lento para FIM_CURSO_ANDAR1_PRINCIPAL."); // 6. Aguarda FIM_CURSO_ANDAR1_PRINCIPAL ser ACIONADO Serial.println("Aguardando FIM_CURSO_ANDAR1_PRINCIPAL ser acionado para parada final."); // CORRIGIDO: Agora usando pcf8574_1.digitalRead() para o sensor de fim de curso while (pcf8574_1.digitalRead(FIM_CURSO_ANDAR1_PRINCIPAL) == LOW) { // Enquanto o sensor principal NÃO estiver ACIONADO (ler LOW) // Verifica o timeout geral do movimento if (millis() - startTimeMovimento > TIMEOUT_MOVIMENTO_TERRACO_ANDAR1) { Serial.println("ERRO 21: Timeout geral atingido antes de FIM_CURSO_ANDAR1_PRINCIPAL (com JOG)."); LOG_ERROR(21); return; } delay(10); // Pequeno atraso } Serial.println("FIM_CURSO_ANDAR1_PRINCIPAL acionado. Parada final."); // 7. Desliga todos os relés de movimento turnAllRelaysOff(); // Atualiza a posição e o estado PosicaoElevador = POSICAO_ANDAR1; EstadoElevador = ESTADO_PARADO; logError = 0; // Reseta erros de movimento Serial.println("Elevador chegou ao Andar 1. PosicaoElevador definida como ANDAR1. Abrindo portas."); ABRIR_PORTAS(); // Abre as portas ao chegar } //FUNÇÃO PARA SUBIR O ELEVADOR DO TÉRREO PARA O ANDAR 1 void SUBIR_TERREO_ANDAR1() { Serial.println("DEBUG: Funcao SUBIR_TERREO_ANDAR1 acionada."); // 1. Chamar a função para fechar as portas via RF. FECHAR_PORTAS_RF(); // 2. Em seguida, verifica se as portas estão fisicamente fechadas. // VERIFICACAO_PORTAS() já vai verificar o logError definido por FECHAR_PORTAS_RF(). if (!VERIFICACAO_PORTAS()) { Serial.println("SUBIR_TERREO_ANDAR1 abortada devido a problema na porta."); EstadoElevador = ESTADO_PARADO; // Garante que o elevador está parado em caso de falha na porta return; // Sai da função se a verificação falhar } Serial.println("Iniciando subida do Térreo para o Andar 1..."); // Inicializa o tempo para o timeout geral de movimento unsigned long startTimeMovimento = millis(); // Você precisará ajustar este timeout (30000 ms) conforme o tempo real de viagem const unsigned long TIMEOUT_MOVIMENTO_TERREO_ANDAR1 = 30000; // Exemplo: 30 segundos de timeout total // 3. Liga RELE_GIRA_PARA_MOTOR e RELE_SENTIDO_GIRO_SOBE_DESCE (para subir) pcf8574_3.digitalWrite(RELE_GIRA_PARA_MOTOR, HIGH); // Liga o motor pcf8574_3.digitalWrite(RELE_SENTIDO_GIRO_SOBE_DESCE, HIGH); // Define sentido para subir (assumindo HIGH) Serial.println("Motor ligado em sentido de subida."); // 4. Aguarda FIM_CURSO_ANDAR1_PARADA_BAIXO ser ACIONADO (ou seja, ler HIGH) // E verifica se o principal não foi ACIONADO por acidente (passou direto) Serial.println("Aguardando FIM_CURSO_ANDAR1_PARADA_BAIXO ser acionado para iniciar parada suave..."); // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso while (pcf8574_1.digitalRead(FIM_CURSO_ANDAR1_PARADA_BAIXO) == LOW) { // Enquanto o sensor de parada suave NÃO estiver ACIONADO (ler LOW) // Verifica o timeout geral do movimento if (millis() - startTimeMovimento > TIMEOUT_MOVIMENTO_TERREO_ANDAR1) { Serial.println("ERRO 24: Timeout geral atingido antes de FIM_CURSO_ANDAR1_PARADA_BAIXO."); LOG_ERROR(24); return; } // Verifica se o sensor principal foi ACIONADO inesperadamente (passou direto pelo parada suave) // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_ANDAR1_PRINCIPAL) == HIGH) { // Se o sensor principal ESTIVER ACIONADO (ler HIGH) Serial.println("ALERTA: FIM_CURSO_ANDAR1_PRINCIPAL ativado antes do esperado! Parada de emergencia."); PosicaoElevador = POSICAO_ANDAR1; // Assume que chegou, mas com anomalia LOG_ERROR(42); // NOVO CÓDIGO DE ERRO: Sensor principal ativado prematuramente (subida) ABRIR_PORTAS(); // Tenta abrir portas para desembarque se seguro return; } delay(10); // Pequeno atraso } Serial.println("FIM_CURSO_ANDAR1_PARADA_BAIXO acionado. Iniciando transicao para parada suave."); // 5. Desliga SOMENTE o RELE_GIRA_PARA_MOTOR pcf8574_3.digitalWrite(RELE_GIRA_PARA_MOTOR, LOW); // Desliga o motor principal Serial.println("RELE_GIRA_PARA_MOTOR desligado. Iniciando contagem de 3 segundos com monitoramento do sensor principal."); // 6. Aguarda 3 segundos OU até FIM_CURSO_ANDAR1_PRINCIPAL ser ACIONADO unsigned long startTimeJogDelay = millis(); while (millis() - startTimeJogDelay < 3000) { // Verifica o timeout geral durante o atraso if (millis() - startTimeMovimento > TIMEOUT_MOVIMENTO_TERREO_ANDAR1) { Serial.println("ERRO 24: Timeout geral atingido durante delay para RELE_JOG."); LOG_ERROR(24); return; } // VERIFICACAO CONSTANTE DO SENSOR PRINCIPAL DURANTE OS 3 SEGUNDOS // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_ANDAR1_PRINCIPAL) == HIGH) { // Se o sensor principal ESTIVER ACIONADO (ler HIGH) Serial.println("FIM_CURSO_ANDAR1_PRINCIPAL acionado durante os 3 segundos de delay! Parando."); break; // Sai do loop de 3 segundos, indo direto para a parada final } delay(10); } // Após o loop de 3 segundos, verifica novamente se o sensor principal já foi acionado // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_ANDAR1_PRINCIPAL) == HIGH) { // Se o sensor principal já estiver ACIONADO Serial.println("FIM_CURSO_ANDAR1_PRINCIPAL ja acionado. Finalizando movimento sem JOG."); pcf8574_3.digitalWrite(RELE_PARADA_EMERGENCIAL, HIGH); PosicaoElevador = POSICAO_ANDAR1; EstadoElevador = ESTADO_PARADO; logError = 0; ABRIR_PORTAS(); pcf8574_3.digitalWrite(RELE_PARADA_EMERGENCIAL, LOW); pcf8574_3.digitalWrite(RELE_SENTIDO_GIRO_SOBE_DESCE, LOW); return; // Sai da função, pois já chegou } // 7. Liga RELE_JOG_AJUSTE_FINO (mantendo RELE_SENTIDO_GIRO_SOBE_DESCE ligado) pcf8574_3.digitalWrite(RELE_JOG_AJUSTE_FINO, HIGH); // Liga o ajuste fino (JOG) Serial.println("RELE_JOG_AJUSTE_FINO ligado. Movimento lento para FIM_CURSO_ANDAR1_PRINCIPAL."); // 8. Aguarda FIM_CURSO_ANDAR1_PRINCIPAL ser ACIONADO Serial.println("Aguardando FIM_CURSO_ANDAR1_PRINCIPAL ser acionado para parada final."); // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso while (pcf8574_1.digitalRead(FIM_CURSO_ANDAR1_PRINCIPAL) == LOW) { // Enquanto o sensor principal NÃO estiver ACIONADO (ler LOW) // Verifica o timeout geral do movimento if (millis() - startTimeMovimento > TIMEOUT_MOVIMENTO_TERREO_ANDAR1) { Serial.println("ERRO 24: Timeout geral atingido antes de FIM_CURSO_ANDAR1_PRINCIPAL (com JOG)."); LOG_ERROR(24); return; } delay(10); // Pequeno atraso } Serial.println("FIM_CURSO_ANDAR1_PRINCIPAL acionado. Parada final."); // 9. Desliga todos os relés de movimento turnAllRelaysOff(); // Atualiza a posição e o estado PosicaoElevador = POSICAO_ANDAR1; EstadoElevador = ESTADO_PARADO; logError = 0; // Reseta erros de movimento Serial.println("Elevador chegou ao Andar 1. PosicaoElevador definida como ANDAR1."); ABRIR_PORTAS(); // Abre as portas ao chegar } // --- FUNÇÃO PARA DESCER O ELEVADOR DO ANDAR 1 PARA O TÉRREO --- void DESCER_ANDAR1_TERREO() { Serial.println("DEBUG: Funcao DESCER_ANDAR1_TERREO acionada."); // 1. Chamar a função para fechar as portas via RF. FECHAR_PORTAS_RF(); // 2. Em seguida, verifica se as portas estão fisicamente fechadas. // VERIFICACAO_PORTAS() já vai verificar o logError definido por FECHAR_PORTAS_RF(). if (!VERIFICACAO_PORTAS()) { Serial.println("DESCER_ANDAR1_TERREO abortada devido a problema na porta."); EstadoElevador = ESTADO_PARADO; // Garante que o elevador está parado em caso de falha na porta return; // Sai da função se a verificação falhar } Serial.println("Iniciando descida do Andar 1 para o Térreo..."); // Inicializa o tempo para o timeout geral de movimento unsigned long startTimeMovimento = millis(); // Você precisará ajustar este timeout (20000 ms) conforme o tempo real de viagem const unsigned long TIMEOUT_MOVIMENTO_ANDAR1_TERREO = 20000; // Exemplo: 20 segundos de timeout total // 3. Liga RELE_GIRA_PARA_MOTOR e RELE_SENTIDO_GIRO_SOBE_DESCE (para descer) pcf8574_3.digitalWrite(RELE_GIRA_PARA_MOTOR, HIGH); // Liga o motor pcf8574_3.digitalWrite(RELE_SENTIDO_GIRO_SOBE_DESCE, LOW); // Define sentido para descer (assumindo LOW) Serial.println("Motor ligado em sentido de descida."); // 4. Aguarda FIM_CURSO_TERREO_PARADA_SUAVE ser ACIONADO (ou seja, ler HIGH) // E verifica se o principal não foi ACIONADO por acidente (passou direto) Serial.println("Aguardando FIM_CURSO_TERREO_PARADA_SUAVE ser acionado para iniciar parada suave..."); // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso while (pcf8574_1.digitalRead(FIM_CURSO_TERREO_PARADA_SUAVE) == LOW) { // Enquanto o sensor de parada suave NÃO estiver ACIONADO (ler LOW) // Verifica o timeout geral do movimento if (millis() - startTimeMovimento > TIMEOUT_MOVIMENTO_ANDAR1_TERREO) { Serial.println("ERRO 25: Timeout geral atingido antes de FIM_CURSO_TERREO_PARADA_SUAVE."); LOG_ERROR(25); return; } // Verifica se o sensor principal foi ACIONADO inesperadamente (passou direto pelo parada suave) // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_TERREO_PRINCIPAL) == HIGH) { // Se o sensor principal ESTIVER ACIONADO (ler HIGH) Serial.println("ALERTA: FIM_CURSO_TERREO_PRINCIPAL ativado antes do esperado! Parada de emergencia."); PosicaoElevador = POSICAO_TERREO; // Assume que chegou, mas com anomalia LOG_ERROR(43); // NOVO CÓDIGO DE ERRO: Sensor principal ativado prematuramente (descida para Térreo) ABRIR_PORTAS(); // Tenta abrir portas para desembarque se seguro return; } delay(10); // Pequeno atraso } Serial.println("FIM_CURSO_TERREO_PARADA_SUAVE acionado. Iniciando transicao para parada suave."); // 5. Desliga SOMENTE o RELE_GIRA_PARA_MOTOR pcf8574_3.digitalWrite(RELE_GIRA_PARA_MOTOR, LOW); // Desliga o motor principal Serial.println("RELE_GIRA_PARA_MOTOR desligado. Iniciando contagem de 3 segundos com monitoramento do sensor principal."); // 6. Aguarda 3 segundos OU até FIM_CURSO_TERREO_PRINCIPAL ser ACIONADO unsigned long startTimeJogDelay = millis(); while (millis() - startTimeJogDelay < 3000) { // Verifica o timeout geral durante o atraso if (millis() - startTimeMovimento > TIMEOUT_MOVIMENTO_ANDAR1_TERREO) { Serial.println("ERRO 25: Timeout geral atingido durante delay para RELE_JOG."); LOG_ERROR(25); return; } // VERIFICACAO CONSTANTE DO SENSOR PRINCIPAL DURANTE OS 3 SEGUNDOS // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_TERREO_PRINCIPAL) == HIGH) { // Se o sensor principal ESTIVER ACIONADO (ler HIGH) Serial.println("FIM_CURSO_TERREO_PRINCIPAL acionado durante os 3 segundos de delay! Parando."); break; // Sai do loop de 3 segundos, indo direto para a parada final } delay(10); } // Após o loop de 3 segundos, verifica novamente se o sensor principal já foi acionado // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_TERREO_PRINCIPAL) == HIGH) { // Se o sensor principal já estiver ACIONADO Serial.println("FIM_CURSO_TERREO_PRINCIPAL ja acionado. Finalizando movimento sem JOG."); PosicaoElevador = POSICAO_TERREO; EstadoElevador = ESTADO_PARADO; pcf8574_3.digitalWrite(RELE_PARADA_EMERGENCIAL, HIGH); ABRIR_PORTAS (); pcf8574_3.digitalWrite(RELE_PARADA_EMERGENCIAL, LOW); pcf8574_3.digitalWrite(RELE_SENTIDO_GIRO_SOBE_DESCE, LOW); return; // Sai da função, pois já chegou } // 7. Liga RELE_JOG_AJUSTE_FINO (mantendo RELE_SENTIDO_GIRO_SOBE_DESCE ligado) pcf8574_3.digitalWrite(RELE_JOG_AJUSTE_FINO, HIGH); // Liga o ajuste fino (JOG) Serial.println("RELE_JOG_AJUSTE_FINO ligado. Movimento lento para FIM_CURSO_TERREO_PRINCIPAL."); // 8. Aguarda FIM_CURSO_TERREO_PRINCIPAL ser ACIONADO Serial.println("Aguardando FIM_CURSO_TERREO_PRINCIPAL ser acionado para parada final."); // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso while (pcf8574_1.digitalRead(FIM_CURSO_TERREO_PRINCIPAL) == LOW) { // Enquanto o sensor principal NÃO estiver ACIONADO (ler LOW) // Verifica o timeout geral do movimento if (millis() - startTimeMovimento > TIMEOUT_MOVIMENTO_ANDAR1_TERREO) { Serial.println("ERRO 25: Timeout geral atingido antes de FIM_CURSO_TERREO_PRINCIPAL (com JOG)."); LOG_ERROR(25); return; } delay(10); // Pequeno atraso } Serial.println("FIM_CURSO_TERREO_PRINCIPAL acionado. Parada final."); // 9. Desliga todos os relés de movimento turnAllRelaysOff(); // Atualiza a posição e o estado PosicaoElevador = POSICAO_TERREO; EstadoElevador = ESTADO_PARADO; logError = 0; // Reseta erros de movimento Serial.println("Elevador chegou ao Térreo. PosicaoElevador definida como TERREO."); ABRIR_PORTAS(); // Abre as portas ao chegar } // --- FUNÇÃO PARA DESCER O ELEVADOR DO TERRAÇO PARA O TÉRREO --- void DESCER_TERRACO_TERREO() { Serial.println("DEBUG: Funcao DESCER_TERRACO_TERREO acionada."); // 1. Chamar a função para fechar as portas via RF. FECHAR_PORTAS_RF(); // 2. Em seguida, verifica se as portas estão fisicamente fechadas. if (!VERIFICACAO_PORTAS()) { Serial.println("DESCER_TERRACO_TERREO abortada devido a problema na porta."); EstadoElevador = ESTADO_PARADO; // Garante que o elevador está parado em caso de falha na porta return; // Sai da função se a verificação falhar } Serial.println("Iniciando descida do Terraço para o Térreo..."); // Inicializa o tempo para o timeout geral de movimento unsigned long startTimeMovimento = millis(); // Ajuste este timeout conforme o tempo real de viagem Terraço -> Térreo const unsigned long TIMEOUT_MOVIMENTO_TERRACO_TERREO = 50000; // Exemplo: 50 segundos de timeout total // 3. Liga RELE_GIRA_PARA_MOTOR e RELE_SENTIDO_GIRO_SOBE_DESCE (para descer) pcf8574_3.digitalWrite(RELE_GIRA_PARA_MOTOR, HIGH); // Liga o motor pcf8574_3.digitalWrite(RELE_SENTIDO_GIRO_SOBE_DESCE, LOW); // Define sentido para descer (assumindo LOW) Serial.println("Motor ligado em sentido de descida."); // 4. Aguarda passagem pelo FIM_CURSO_ANDAR1_PRINCIPAL (sensor principal do Andar 1) Serial.println("Aguardando passagem pelo Andar 1..."); bool passouPeloAndar1 = false; while (!passouPeloAndar1) { // Verifica o timeout geral do movimento if (millis() - startTimeMovimento > TIMEOUT_MOVIMENTO_TERRACO_TERREO) { Serial.println("ERRO 26: Timeout geral atingido antes de passar pelo Andar 1."); LOG_ERROR(26); return; } // Quando o elevador atinge o FIM_CURSO_ANDAR1_PRINCIPAL (NF acionado = HIGH) // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_ANDAR1_PRINCIPAL) == HIGH) { Serial.println("Elevador passando pelo Andar 1. Posicao temporaria: ANDAR1."); PosicaoElevador = POSICAO_ANDAR1; // Atualiza a posição temporariamente // Agora espera que o sensor seja desacionado para confirmar que passou // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso while (pcf8574_1.digitalRead(FIM_CURSO_ANDAR1_PRINCIPAL) == HIGH) { // Monitora o timeout enquanto o elevador está sobre o sensor if (millis() - startTimeMovimento > TIMEOUT_MOVIMENTO_TERRACO_TERREO) { Serial.println("ERRO 26: Timeout atingido enquanto sobre FIM_CURSO_ANDAR1_PRINCIPAL."); LOG_ERROR(26); return; } delay(10); } Serial.println("Elevador passou pelo Andar 1."); passouPeloAndar1 = true; // Marca que passou e sai do loop } delay(10); } // 5. Agora, foca na parada suave para o Térreo Serial.println("Aguardando FIM_CURSO_TERREO_PARADA_SUAVE ser acionado para iniciar parada suave..."); // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso while (pcf8574_1.digitalRead(FIM_CURSO_TERREO_PARADA_SUAVE) == LOW) { // Enquanto o sensor de parada suave NÃO estiver ACIONADO (ler LOW) // Verifica o timeout geral do movimento if (millis() - startTimeMovimento > TIMEOUT_MOVIMENTO_TERRACO_TERREO) { Serial.println("ERRO 26: Timeout geral atingido antes de FIM_CURSO_TERREO_PARADA_SUAVE."); LOG_ERROR(26); return; } // Verifica se o sensor principal do Térreo foi ACIONADO inesperadamente (passou direto) // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_TERREO_PRINCIPAL) == HIGH) { // Se o sensor principal ESTIVER ACIONADO (ler HIGH) Serial.println("ALERTA: FIM_CURSO_TERREO_PRINCIPAL ativado antes do esperado! Parada de emergencia."); PosicaoElevador = POSICAO_TERREO; // Assume que chegou, mas com anomalia LOG_ERROR(44); ABRIR_PORTAS(); // Tenta abrir portas para desembarque se seguro return; } delay(10); // Pequeno atraso } Serial.println("FIM_CURSO_TERREO_PARADA_SUAVE acionado. Iniciando transicao para parada suave."); // 6. Desliga SOMENTE o RELE_GIRA_PARA_MOTOR pcf8574_3.digitalWrite(RELE_GIRA_PARA_MOTOR, LOW); // Desliga o motor principal Serial.println("RELE_GIRA_PARA_MOTOR desligado. Iniciando contagem de 3 segundos com monitoramento do sensor principal."); // 7. Aguarda 3 segundos OU até FIM_CURSO_TERREO_PRINCIPAL ser ACIONADO unsigned long startTimeJogDelay = millis(); while (millis() - startTimeJogDelay < 3000) { // Verifica o timeout geral durante o atraso if (millis() - startTimeMovimento > TIMEOUT_MOVIMENTO_TERRACO_TERREO) { Serial.println("ERRO 26: Timeout geral atingido durante delay para RELE_JOG."); LOG_ERROR(26); return; } // VERIFICACAO CONSTANTE DO SENSOR PRINCIPAL DURANTE OS 3 SEGUNDOS // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_TERREO_PRINCIPAL) == HIGH) { // Se o sensor principal ESTIVER ACIONADO (ler HIGH) Serial.println("FIM_CURSO_TERREO_PRINCIPAL acionado durante os 3 segundos de delay! Parando."); break; // Sai do loop de 3 segundos, indo direto para a parada final } delay(10); } // Após o loop de 3 segundos, verifica novamente se o sensor principal já foi acionado // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_TERREO_PRINCIPAL) == HIGH) { // Se o sensor principal já estiver ACIONADO Serial.println("FIM_CURSO_TERREO_PRINCIPAL ja acionado. Finalizando movimento sem JOG."); pcf8574_3.digitalWrite(RELE_PARADA_EMERGENCIAL, HIGH); PosicaoElevador = POSICAO_TERREO; EstadoElevador = ESTADO_PARADO; logError = 0; ABRIR_PORTAS(); pcf8574_3.digitalWrite(RELE_PARADA_EMERGENCIAL, LOW); pcf8574_3.digitalWrite(RELE_SENTIDO_GIRO_SOBE_DESCE, LOW); return; // Sai da função, pois já chegou } // 8. Liga RELE_JOG_AJUSTE_FINO (mantendo RELE_SENTIDO_GIRO_SOBE_DESCE ligado) pcf8574_3.digitalWrite(RELE_JOG_AJUSTE_FINO, HIGH); // Liga o ajuste fino (JOG) Serial.println("RELE_JOG_AJUSTE_FINO ligado. Movimento lento para FIM_CURSO_TERREO_PRINCIPAL."); // 9. Aguarda FIM_CURSO_TERREO_PRINCIPAL ser ACIONADO Serial.println("Aguardando FIM_CURSO_TERREO_PRINCIPAL ser acionado para parada final."); // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso while (pcf8574_1.digitalRead(FIM_CURSO_TERREO_PRINCIPAL) == LOW) { // Enquanto o sensor principal NÃO estiver ACIONADO (ler LOW) // Verifica o timeout geral do movimento if (millis() - startTimeMovimento > TIMEOUT_MOVIMENTO_TERRACO_TERREO) { Serial.println("ERRO 26: Timeout geral atingido antes de FIM_CURSO_TERREO_PRINCIPAL (com JOG)."); LOG_ERROR(26); return; } delay(10); // Pequeno atraso } Serial.println("FIM_CURSO_TERREO_PRINCIPAL acionado. Parada final."); // 10. Desliga todos os relés de movimento turnAllRelaysOff(); // Atualiza a posição e o estado PosicaoElevador = POSICAO_TERREO; EstadoElevador = ESTADO_PARADO; logError = 0; // Reseta erros de movimento Serial.println("Elevador chegou ao Térreo. PosicaoElevador definida como TERREO."); ABRIR_PORTAS(); // Abre as portas ao chegar } // --- FUNÇÃO PARA SUBIR O ELEVADOR DO ANDAR 1 PARA O TERRAÇO --- void SUBIR_ANDAR1_TERRACO() { Serial.println("DEBUG: Funcao SUBIR_ANDAR1_TERRACO acionada."); // 1. Chamar a função para fechar as portas via RF. FECHAR_PORTAS_RF(); // 2. Em seguida, verifica se as portas estão fisicamente fechadas. // VERIFICACAO_PORTAS() já vai verificar o logError definido por FECHAR_PORTAS_RF(). if (!VERIFICACAO_PORTAS()) { Serial.println("SUBIR_ANDAR1_TERRACO abortada devido a problema na porta."); EstadoElevador = ESTADO_PARADO; // Garante que o elevador está parado em caso de falha na porta return; // Sai da função se a verificação falhar } Serial.println("Iniciando subida do Andar 1 para o Terraço..."); // Inicializa o tempo para o timeout geral de movimento unsigned long startTimeMovimento = millis(); // Você precisará ajustar este timeout (30000 ms) conforme o tempo real de viagem const unsigned long TIMEOUT_MOVIMENTO_ANDAR1_TERRACO = 30000; // Exemplo: 30 segundos de timeout total // 3. Liga RELE_GIRA_PARA_MOTOR e RELE_SENTIDO_GIRO_SOBE_DESCE (para subir) pcf8574_3.digitalWrite(RELE_GIRA_PARA_MOTOR, HIGH); // Liga o motor pcf8574_3.digitalWrite(RELE_SENTIDO_GIRO_SOBE_DESCE, HIGH); // Define sentido para subir (assumindo HIGH) Serial.println("Motor ligado em sentido de subida."); // 4. Aguarda FIM_CURSO_TERRACO_PARADA_BAIXO ser ACIONADO (ou seja, ler HIGH) // E verifica se o principal não foi ACIONADO por acidente (passou direto) Serial.println("Aguardando FIM_CURSO_TERRACO_PARADA_BAIXO ser acionado para iniciar parada suave..."); // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso while (pcf8574_1.digitalRead(FIM_CURSO_TERRACO_PARADA_BAIXO) == LOW) { // Enquanto o sensor de parada suave NÃO estiver ACIONADO (ler LOW) // Verifica o timeout geral do movimento if (millis() - startTimeMovimento > TIMEOUT_MOVIMENTO_ANDAR1_TERRACO) { Serial.println("ERRO 27: Timeout geral atingido antes de FIM_CURSO_TERRACO_PARADA_BAIXO."); LOG_ERROR(27); return; } // Verifica se o sensor principal foi ACIONADO inesperadamente (passou direto pelo parada suave) // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_TERRACO_PRINCIPAL) == HIGH) { // Se o sensor principal ESTIVER ACIONADO (ler HIGH) Serial.println("ALERTA: FIM_CURSO_TERRACO_PRINCIPAL ativado antes do esperado! Parada de emergencia."); PosicaoElevador = POSICAO_TERRACO; // Assume que chegou, mas com anomalia LOG_ERROR(45); ABRIR_PORTAS(); // Tenta abrir portas para desembarque se seguro return; } delay(10); // Pequeno atraso } Serial.println("FIM_CURSO_TERRACO_PARADA_BAIXO acionado. Iniciando transicao para parada suave."); // 5. Desliga SOMENTE o RELE_GIRA_PARA_MOTOR pcf8574_3.digitalWrite(RELE_GIRA_PARA_MOTOR, LOW); // Desliga o motor principal Serial.println("RELE_GIRA_PARA_MOTOR desligado. Iniciando contagem de 3 segundos com monitoramento do sensor principal."); // 6. Aguarda 3 segundos OU até FIM_CURSO_TERRACO_PRINCIPAL ser ACIONADO unsigned long startTimeJogDelay = millis(); while (millis() - startTimeJogDelay < 3000) { // Verifica o timeout geral durante o atraso if (millis() - startTimeMovimento > TIMEOUT_MOVIMENTO_ANDAR1_TERRACO) { Serial.println("ERRO 27: Timeout geral atingido durante delay para RELE_JOG."); LOG_ERROR(27); return; } // VERIFICACAO CONSTANTE DO SENSOR PRINCIPAL DURANTE OS 3 SEGUNDOS // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_TERRACO_PRINCIPAL) == HIGH) { // Se o sensor principal ESTIVER ACIONADO (ler HIGH) Serial.println("FIM_CURSO_TERRACO_PRINCIPAL acionado durante os 3 segundos de delay! Parando."); break; // Sai do loop de 3 segundos, indo direto para a parada final } delay(10); } // Após o loop de 3 segundos, verifica novamente se o sensor principal já foi acionado // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_TERRACO_PRINCIPAL) == HIGH) { // Se o sensor principal já estiver ACIONADO Serial.println("FIM_CURSO_TERRACO_PRINCIPAL ja acionado. Finalizando movimento sem JOG."); pcf8574_3.digitalWrite(RELE_PARADA_EMERGENCIAL, HIGH); PosicaoElevador = POSICAO_TERRACO; EstadoElevador = ESTADO_PARADO; ABRIR_PORTAS(); pcf8574_3.digitalWrite(RELE_PARADA_EMERGENCIAL, LOW); pcf8574_3.digitalWrite(RELE_SENTIDO_GIRO_SOBE_DESCE, LOW); return; // Sai da função, pois já chegou } // 7. Liga RELE_JOG_AJUSTE_FINO (mantendo RELE_SENTIDO_GIRO_SOBE_DESCE ligado) pcf8574_3.digitalWrite(RELE_JOG_AJUSTE_FINO, HIGH); // Liga o ajuste fino (JOG) Serial.println("RELE_JOG_AJUSTE_FINO ligado. Movimento lento para FIM_CURSO_TERRACO_PRINCIPAL."); // 8. Aguarda FIM_CURSO_TERRACO_PRINCIPAL ser ACIONADO Serial.println("Aguardando FIM_CURSO_TERRACO_PRINCIPAL ser acionado para parada final."); // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso while (pcf8574_1.digitalRead(FIM_CURSO_TERRACO_PRINCIPAL) == LOW) { // Enquanto o sensor principal NÃO estiver ACIONADO (ler LOW) // Verifica o timeout geral do movimento if (millis() - startTimeMovimento > TIMEOUT_MOVIMENTO_ANDAR1_TERRACO) { Serial.println("ERRO 27: Timeout geral atingido antes de FIM_CURSO_TERRACO_PRINCIPAL (com JOG)."); LOG_ERROR(27); return; } delay(10); // Pequeno atraso } Serial.println("FIM_CURSO_TERRACO_PRINCIPAL acionado. Parada final."); // 9. Desliga todos os relés de movimento turnAllRelaysOff(); // Atualiza a posição e o estado PosicaoElevador = POSICAO_TERRACO; EstadoElevador = ESTADO_PARADO; logError = 0; // Reseta erros de movimento Serial.println("Elevador chegou ao Terraço. PosicaoElevador definida como TERRACO."); ABRIR_PORTAS(); // Abre as portas ao chegar } // --- FUNÇÃO PARA SUBIR O ELEVADOR DO TÉRREO PARA O TERRAÇO --- void SUBIR_TERREO_TERRACO() { Serial.println("DEBUG: Funcao SUBIR_TERREO_TERRACO acionada."); // 1. Chamar a função para fechar as portas via RF. FECHAR_PORTAS_RF(); // 2. Em seguida, verifica se as portas estão fisicamente fechadas. if (!VERIFICACAO_PORTAS()) { Serial.println("SUBIR_TERREO_TERRACO abortada devido a problema na porta."); EstadoElevador = ESTADO_PARADO; // Garante que o elevador está parado em caso de falha na porta return; // Sai da função se a verificação falhar } Serial.println("Iniciando subida do Térreo para o Terraço..."); // Inicializa o tempo para o timeout geral de movimento unsigned long startTimeMovimento = millis(); // Ajuste este timeout conforme o tempo real de viagem Térreo -> Terraço const unsigned long TIMEOUT_MOVIMENTO_TERREO_TERRACO = 50000; // Exemplo: 50 segundos de timeout total // 3. Liga RELE_GIRA_PARA_MOTOR e RELE_SENTIDO_GIRO_SOBE_DESCE (para subir) pcf8574_3.digitalWrite(RELE_GIRA_PARA_MOTOR, HIGH); // Liga o motor pcf8574_3.digitalWrite(RELE_SENTIDO_GIRO_SOBE_DESCE, HIGH); // Define sentido para subir (assumindo HIGH) Serial.println("Motor ligado em sentido de subida."); // 4. Aguarda passagem pelo FIM_CURSO_ANDAR1_PRINCIPAL (sensor principal do Andar 1) Serial.println("Aguardando passagem pelo Andar 1..."); bool passouPeloAndar1 = false; while (!passouPeloAndar1) { // Verifica o timeout geral do movimento if (millis() - startTimeMovimento > TIMEOUT_MOVIMENTO_TERREO_TERRACO) { Serial.println("ERRO 28: Timeout geral atingido antes de passar pelo Andar 1 (subindo)."); LOG_ERROR(28); return; } // Quando o elevador atinge o FIM_CURSO_ANDAR1_PRINCIPAL (NF acionado = HIGH) // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_ANDAR1_PRINCIPAL) == HIGH) { Serial.println("Elevador passando pelo Andar 1. Posicao temporaria: ANDAR1."); PosicaoElevador = POSICAO_ANDAR1; // Atualiza a posição temporariamente // Agora espera que o sensor seja desacionado para confirmar que passou // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso while (pcf8574_1.digitalRead(FIM_CURSO_ANDAR1_PRINCIPAL) == HIGH) { // Monitora o timeout enquanto o elevador está sobre o sensor if (millis() - startTimeMovimento > TIMEOUT_MOVIMENTO_TERREO_TERRACO) { Serial.println("ERRO 28: Timeout atingido enquanto sobre FIM_CURSO_ANDAR1_PRINCIPAL (subindo)."); LOG_ERROR(28); return; } delay(10); } Serial.println("Elevador passou pelo Andar 1."); passouPeloAndar1 = true; // Marca que passou e sai do loop } delay(10); } // 5. Agora, foca na parada suave para o Terraço Serial.println("Aguardando FIM_CURSO_TERRACO_PARADA_BAIXO ser acionado para iniciar parada suave..."); // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso while (pcf8574_1.digitalRead(FIM_CURSO_TERRACO_PARADA_BAIXO) == LOW) { // Enquanto o sensor de parada suave NÃO estiver ACIONADO (ler LOW) // Verifica o timeout geral do movimento if (millis() - startTimeMovimento > TIMEOUT_MOVIMENTO_TERREO_TERRACO) { Serial.println("ERRO 28: Timeout geral atingido antes de FIM_CURSO_TERRACO_PARADA_BAIXO."); LOG_ERROR(28); return; } // Verifica se o sensor principal foi ACIONADO inesperadamente (passou direto) // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_TERRACO_PRINCIPAL) == HIGH) { // Se o sensor principal ESTIVER ACIONADO (ler HIGH) Serial.println("ALERTA: FIM_CURSO_TERRACO_PRINCIPAL ativado antes do esperado! Parada de emergencia."); PosicaoElevador = POSICAO_TERRACO; // Assume que chegou, mas com anomalia EstadoElevador = ESTADO_ERRO; // Marca estado de erro para investigação LOG_ERROR(46); ABRIR_PORTAS(); // Tenta abrir portas para desembarque se seguro return; } delay(10); // Pequeno atraso } Serial.println("FIM_CURSO_TERRACO_PARADA_BAIXO acionado. Iniciando transicao para parada suave."); // 6. Desliga SOMENTE o RELE_GIRA_PARA_MOTOR pcf8574_3.digitalWrite(RELE_GIRA_PARA_MOTOR, LOW); // Desliga o motor principal Serial.println("RELE_GIRA_PARA_MOTOR desligado. Iniciando contagem de 3 segundos com monitoramento do sensor principal."); // 7. Aguarda 3 segundos OU até FIM_CURSO_TERRACO_PRINCIPAL ser ACIONADO unsigned long startTimeJogDelay = millis(); while (millis() - startTimeJogDelay < 3000) { // Verifica o timeout geral durante o atraso if (millis() - startTimeMovimento > TIMEOUT_MOVIMENTO_TERREO_TERRACO) { Serial.println("ERRO 28: Timeout geral atingido durante delay para RELE_JOG."); LOG_ERROR(28); return; } // VERIFICACAO CONSTANTE DO SENSOR PRINCIPAL DURANTE OS 3 SEGUNDOS // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_TERRACO_PRINCIPAL) == HIGH) { // Se o sensor principal ESTIVER ACIONADO (ler HIGH) Serial.println("FIM_CURSO_TERRACO_PRINCIPAL ativado durante os 3 segundos de delay! Parando."); break; // Sai do loop de 3 segundos, indo direto para a parada final } delay(10); } // Após o loop de 3 segundos, verifica novamente se o sensor principal já foi acionado // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_TERRACO_PRINCIPAL) == HIGH) { // Se o sensor principal já estiver ACIONADO Serial.println("FIM_CURSO_TERRACO_PRINCIPAL ja acionado. Finalizando movimento sem JOG."); pcf8574_3.digitalWrite(RELE_PARADA_EMERGENCIAL, HIGH); PosicaoElevador = POSICAO_TERRACO; EstadoElevador = ESTADO_PARADO; logError = 0; ABRIR_PORTAS(); pcf8574_3.digitalWrite(RELE_PARADA_EMERGENCIAL, LOW); pcf8574_3.digitalWrite(RELE_SENTIDO_GIRO_SOBE_DESCE, LOW); return; // Sai da função, pois já chegou } // 8. Liga RELE_JOG_AJUSTE_FINO (mantendo RELE_SENTIDO_GIRO_SOBE_DESCE ligado) pcf8574_3.digitalWrite(RELE_JOG_AJUSTE_FINO, HIGH); // Liga o ajuste fino (JOG) Serial.println("RELE_JOG_AJUSTE_FINO ligado. Movimento lento para FIM_CURSO_TERRACO_PRINCIPAL."); // 9. Aguarda FIM_CURSO_TERRACO_PRINCIPAL ser ACIONADO Serial.println("Aguardando FIM_CURSO_TERRACO_PRINCIPAL ser acionado para parada final."); // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso while (pcf8574_1.digitalRead(FIM_CURSO_TERRACO_PRINCIPAL) == LOW) { // Enquanto o sensor principal NÃO estiver ACIONADO (ler LOW) // Verifica o timeout geral do movimento if (millis() - startTimeMovimento > TIMEOUT_MOVIMENTO_TERREO_TERRACO) { Serial.println("ERRO 28: Timeout geral atingido antes de FIM_CURSO_TERRACO_PRINCIPAL (com JOG)."); LOG_ERROR(28); return; } delay(10); // Pequeno atraso } Serial.println("FIM_CURSO_TERRACO_PRINCIPAL acionado. Parada final."); // 10. Desliga todos os relés de movimento turnAllRelaysOff(); // Atualiza a posição e o estado PosicaoElevador = POSICAO_TERRACO; EstadoElevador = ESTADO_PARADO; logError = 0; // Reseta erros de movimento Serial.println("Elevador chegou ao Terraço. PosicaoElevador definida como TERRACO."); ABRIR_PORTAS(); // Abre as portas ao chegar } // --- FUNÇÃO PARA DESCER O ELEVADOR QUANDO A POSIÇÃO É DESCONHECIDA ATÉ O TÉRREO --- void DESCER_DESCONHECIDO_TERREO() { Serial.println("DEBUG: Funcao DESCER_DESCONHECIDO_TERREO acionada."); // 1. Chamar a função para fechar as portas via RF. FECHAR_PORTAS_RF(); // 2. Em seguida, verifica se as portas estão fisicamente fechadas. if (!VERIFICACAO_PORTAS()) { Serial.println("DESCER_DESCONHECIDO_TERREO abortada devido a problema na porta."); EstadoElevador = ESTADO_PARADO; // Garante que o elevador está parado em caso de falha na porta return; // Sai da função se a verificação falhar } Serial.println("Movendo para o Térreo para recalibrar a posição com parada suave..."); // Inicializa o tempo para o timeout geral de movimento unsigned long startTimeMovimento = millis(); // Ajuste este timeout conforme o tempo máximo esperado para o elevador chegar ao Térreo de qualquer posição const unsigned long TIMEOUT_DESCIDA_DESCONHECIDO = 60000; // Exemplo: 60 segundos de timeout para recalibracao // 3. Liga RELE_GIRA_PARA_MOTOR e RELE_SENTIDO_GIRO_SOBE_DESCE (para descer) pcf8574_3.digitalWrite(RELE_GIRA_PARA_MOTOR, HIGH); // Liga o motor pcf8574_3.digitalWrite(RELE_SENTIDO_GIRO_SOBE_DESCE, LOW); // Define sentido para descer (assumindo LOW) Serial.println("Motor ligado em sentido de descida para recalibracao."); // 4. Aguarda FIM_CURSO_TERREO_PARADA_SUAVE ser ACIONADO (ou seja, ler HIGH) // E verifica se o principal não foi ACIONADO por acidente (passou direto) Serial.println("Aguardando FIM_CURSO_TERREO_PARADA_SUAVE ser acionado para iniciar parada suave..."); // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso while (pcf8574_1.digitalRead(FIM_CURSO_TERREO_PARADA_SUAVE) == LOW) { // Enquanto o sensor de parada suave NÃO estiver ACIONADO (ler LOW) // Verifica o timeout geral do movimento if (millis() - startTimeMovimento > TIMEOUT_DESCIDA_DESCONHECIDO) { Serial.println("ERRO 29: Timeout geral atingido antes de FIM_CURSO_TERREO_PARADA_SUAVE (recalibracao)."); LOG_ERROR(29); return; } // Verifica se o sensor principal foi ACIONADO inesperadamente (passou direto pelo parada suave) // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_TERREO_PRINCIPAL) == HIGH) { // Se o sensor principal ESTIVER ACIONADO (ler HIGH) Serial.println("ALERTA: FIM_CURSO_TERREO_PRINCIPAL ativado antes do esperado! Parada de emergencia (recalibracao)."); PosicaoElevador = POSICAO_TERREO; // Assume que chegou, mas com anomalia EstadoElevador = ESTADO_ERRO; // Marca estado de erro para investigação LOG_ERROR(47); ABRIR_PORTAS(); // Tenta abrir portas para desembarque se seguro return; } delay(10); // Pequeno atraso } Serial.println("FIM_CURSO_TERREO_PARADA_SUAVE acionado. Iniciando transicao para parada suave (recalibracao)."); // 5. Desliga SOMENTE o RELE_GIRA_PARA_MOTOR pcf8574_3.digitalWrite(RELE_GIRA_PARA_MOTOR, LOW); // Desliga o motor principal Serial.println("RELE_GIRA_PARA_MOTOR desligado. Iniciando contagem de 3 segundos com monitoramento do sensor principal (recalibracao)."); // 6. Aguarda 3 segundos OU até FIM_CURSO_TERREO_PRINCIPAL ser ACIONADO unsigned long startTimeJogDelay = millis(); while (millis() - startTimeJogDelay < 3000) { // Verifica o timeout geral durante o atraso if (millis() - startTimeMovimento > TIMEOUT_DESCIDA_DESCONHECIDO) { Serial.println("ERRO 29: Timeout geral atingido durante delay para RELE_JOG (recalibracao)."); LOG_ERROR(29); return; } // VERIFICACAO CONSTANTE DO SENSOR PRINCIPAL DURANTE OS 3 SEGUNDOS // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_TERREO_PRINCIPAL) == HIGH) { // Se o sensor principal ESTIVER ACIONADO (ler HIGH) Serial.println("FIM_CURSO_TERREO_PRINCIPAL acionado durante os 3 segundos de delay! Parando (recalibracao)."); break; // Sai do loop de 3 segundos, indo direto para a parada final } delay(10); } // Após o loop de 3 segundos, verifica novamente se o sensor principal já foi acionado // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso if (pcf8574_1.digitalRead(FIM_CURSO_TERREO_PRINCIPAL) == HIGH) { // Se o sensor principal já estiver ACIONADO Serial.println("FIM_CURSO_TERREO_PRINCIPAL ja acionado. Finalizando movimento sem JOG (recalibracao)."); pcf8574_3.digitalWrite(RELE_PARADA_EMERGENCIAL, HIGH); PosicaoElevador = POSICAO_TERREO; EstadoElevador = ESTADO_PARADO; logError = 0; ABRIR_PORTAS(); pcf8574_3.digitalWrite(RELE_PARADA_EMERGENCIAL, LOW); pcf8574_3.digitalWrite(RELE_SENTIDO_GIRO_SOBE_DESCE, LOW); return; // Sai da função, pois já chegou } // 7. Liga RELE_JOG_AJUSTE_FINO (mantendo RELE_SENTIDO_GIRO_SOBE_DESCE ligado) pcf8574_3.digitalWrite(RELE_JOG_AJUSTE_FINO, HIGH); // Liga o ajuste fino (JOG) Serial.println("RELE_JOG_AJUSTE_FINO ligado. Movimento lento para FIM_CURSO_TERREO_PRINCIPAL (recalibracao)."); // 8. Aguarda FIM_CURSO_TERREO_PRINCIPAL ser ACIONADO Serial.println("Aguardando FIM_CURSO_TERREO_PRINCIPAL ser acionado para parada final (recalibracao)."); // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso while (pcf8574_1.digitalRead(FIM_CURSO_TERREO_PRINCIPAL) == LOW) { // Enquanto o sensor principal NÃO estiver ACIONADO (ler LOW) // Verifica o timeout geral do movimento if (millis() - startTimeMovimento > TIMEOUT_DESCIDA_DESCONHECIDO) { Serial.println("ERRO 29: Timeout geral atingido antes de FIM_CURSO_TERREO_PRINCIPAL (com JOG) (recalibracao)."); LOG_ERROR(29); return; } delay(10); // Pequeno atraso } Serial.println("FIM_CURSO_TERREO_PRINCIPAL acionado. Parada final (recalibracao)."); // 9. Desliga todos os relés de movimento turnAllRelaysOff(); // Atualiza a posição e o estado PosicaoElevador = POSICAO_TERREO; EstadoElevador = ESTADO_PARADO; logError = 0; // Reseta erros de movimento Serial.println("Elevador recalibrado com sucesso: PosicaoElevador definida como TERREO, abrindo portas..."); ABRIR_PORTAS(); // Abre as portas ao chegar } // --- FUNÇÃO PARA VERIFICAR A POSICAO ATUAL EM TEMPO REAL (PARA O LOOP) --- void VERIFICAR_POSICAO_ATUAL() { // Variáveis estáticas para manter o estado anterior entre chamadas da função static int posicaoAnterior = -1; // Para rastrear mudanças na PosicaoElevador // Variável estática para guardar o estado anterior do sensor de portas static int previousPortSensorState = -1; // Inicializa com um valor que não seja HIGH/LOW // Novo array estático para guardar o estado anterior das entradas 1 a 8 (do PCF8574_1) static int previousLimitSwitchState[8] = {-1, -1, -1, -1, -1, -1, -1, -1}; // Novos estáticos para os botões e entrada de verificação (do PCF8574_2, P4 a P7) static int previousButtonTerracoState = -1; static int previousButtonAndar1State = -1; static int previousButtonTerreoState = -1; static int previousEntradaVerificacaoState = -1; // Lê e verifica as mudanças para as ENTRADAS 1 a 8 (PCF8574_1) // Agora, você usa pcf8574_1.digitalRead() com a MACRO que define o PINO int currentFCTerreoPrincipalState = pcf8574_1.digitalRead(FIM_CURSO_TERREO_PRINCIPAL); if (currentFCTerreoPrincipalState != previousLimitSwitchState[0]) { Serial.print("MENSAGEM: FIM_CURSO_TERREO_PRINCIPAL (Pino 1) STATUS: "); Serial.println(currentFCTerreoPrincipalState == HIGH ? "HIGH (Aberto)" : "LOW (Fechado)"); previousLimitSwitchState[0] = currentFCTerreoPrincipalState; } int currentFCTerreoParadaSuaveState = pcf8574_1.digitalRead(FIM_CURSO_TERREO_PARADA_SUAVE); if (currentFCTerreoParadaSuaveState != previousLimitSwitchState[1]) { Serial.print("MENSAGEM: FIM_CURSO_TERREO_PARADA_SUAVE (Pino 2) STATUS: "); Serial.println(currentFCTerreoParadaSuaveState == HIGH ? "HIGH (Aberto)" : "LOW (Fechado)"); previousLimitSwitchState[1] = currentFCTerreoParadaSuaveState; } int currentFCAndar1ParadaBaixoState = pcf8574_1.digitalRead(FIM_CURSO_ANDAR1_PARADA_BAIXO); if (currentFCAndar1ParadaBaixoState != previousLimitSwitchState[2]) { Serial.print("MENSAGEM: FIM_CURSO_ANDAR1_PARADA_BAIXO (Pino 3) STATUS: "); Serial.println(currentFCAndar1ParadaBaixoState == HIGH ? "HIGH (Aberto)" : "LOW (Fechado)"); previousLimitSwitchState[2] = currentFCAndar1ParadaBaixoState; } int currentFCAndar1PrincipalState = pcf8574_1.digitalRead(FIM_CURSO_ANDAR1_PRINCIPAL); if (currentFCAndar1PrincipalState != previousLimitSwitchState[3]) { Serial.print("MENSAGEM: FIM_CURSO_ANDAR1_PRINCIPAL (Pino 4) STATUS: "); Serial.println(currentFCAndar1PrincipalState == HIGH ? "HIGH (Aberto)" : "LOW (Fechado)"); previousLimitSwitchState[3] = currentFCAndar1PrincipalState; } int currentFCAndar1ParadaCimaState = pcf8574_1.digitalRead(FIM_CURSO_ANDAR1_PARADA_CIMA); if (currentFCAndar1ParadaCimaState != previousLimitSwitchState[4]) { Serial.print("MENSAGEM: FIM_CURSO_ANDAR1_PARADA_CIMA (Pino 5) STATUS: "); Serial.println(currentFCAndar1ParadaCimaState == HIGH ? "HIGH (Aberto)" : "LOW (Fechado)"); previousLimitSwitchState[4] = currentFCAndar1ParadaCimaState; } int currentFCTerracoParadaBaixoState = pcf8574_1.digitalRead(FIM_CURSO_TERRACO_PARADA_BAIXO); if (currentFCTerracoParadaBaixoState != previousLimitSwitchState[5]) { Serial.print("MENSAGEM: FIM_CURSO_TERRACO_PARADA_BAIXO (Pino 6) STATUS: "); Serial.println(currentFCTerracoParadaBaixoState == HIGH ? "HIGH (Aberto)" : "LOW (Fechado)"); previousLimitSwitchState[5] = currentFCTerracoParadaBaixoState; } int currentFCTerracoPrincipalState = pcf8574_1.digitalRead(FIM_CURSO_TERRACO_PRINCIPAL); if (currentFCTerracoPrincipalState != previousLimitSwitchState[6]) { Serial.print("MENSAGEM: FIM_CURSO_TERRACO_PRINCIPAL (Pino 7) STATUS: "); Serial.println(currentFCTerracoPrincipalState == HIGH ? "HIGH (Aberto)" : "LOW (Fechado)"); previousLimitSwitchState[6] = currentFCTerracoPrincipalState; } int currentFCTerracoEmergenciaState = pcf8574_1.digitalRead(FIM_CURSO_TERRACO_EMERGENCIA); if (currentFCTerracoEmergenciaState != previousLimitSwitchState[7]) { Serial.print("MENSAGEM: FIM_CURSO_TERRACO_EMERGENCIA (Pino 8) STATUS: "); Serial.println(currentFCTerracoEmergenciaState == HIGH ? "HIGH (Aberto)" : "LOW (Fechado)"); previousLimitSwitchState[7] = currentFCTerracoEmergenciaState; } // Lê e verifica as mudanças para SENSOR_FISICO_PORTAS (Pino 9 - PCF8574_2) int currentPortSensorState = pcf8574_2.digitalRead(SENSOR_FISICO_PORTAS); if (currentPortSensorState != previousPortSensorState) { Serial.print("MENSAGEM: SENSOR_FISICO_PORTAS (Pino 9) STATUS: "); Serial.println(currentPortSensorState == HIGH ? "HIGH (Aberto)" : "LOW (Fechado)"); previousPortSensorState = currentPortSensorState; } // CORRIGIDO: Usando pcf8574_2.digitalRead() para o botão de chamada int currentButtonTerracoState = pcf8574_2.digitalRead(BOTAO_CHAMADA_TERRACO); if (currentButtonTerracoState != previousButtonTerracoState) { Serial.print("MENSAGEM: BOTAO_CHAMADA_TERRACO (Pino 13) STATUS: "); Serial.println(currentButtonTerracoState == HIGH ? "HIGH (Aberto)" : "LOW (Fechado)"); previousButtonTerracoState = currentButtonTerracoState; } // CORRIGIDO: Usando pcf8574_2.digitalRead() para o botão de chamada int currentButtonAndar1State = pcf8574_2.digitalRead(BOTAO_CHAMADA_ANDAR1); if (currentButtonAndar1State != previousButtonAndar1State) { Serial.print("MENSAGEM: BOTAO_CHAMADA_ANDAR1 (Pino 14) STATUS: "); Serial.println(currentButtonAndar1State == HIGH ? "HIGH (Aberto)" : "LOW (Fechado)"); previousButtonAndar1State = currentButtonAndar1State; } // CORRIGIDO: Usando pcf8574_2.digitalRead() para o botão de chamada int currentButtonTerreoState = pcf8574_2.digitalRead(BOTAO_CHAMADA_TERREO); if (currentButtonTerreoState != previousButtonTerreoState) { Serial.print("MENSAGEM: BOTAO_CHAMADA_TERREO (Pino 15) STATUS: "); Serial.println(currentButtonTerreoState == HIGH ? "HIGH (Aberto)" : "LOW (Fechado)"); previousButtonTerreoState = currentButtonTerreoState; } // CORRIGIDO: Usando pcf8574_2.digitalRead() para a entrada de verificação int currentEntradaVerificacaoState = pcf8574_2.digitalRead(ENTRADA_VERIFICACAO); if (currentEntradaVerificacaoState != previousEntradaVerificacaoState) { Serial.print("MENSAGEM: ENTRADA_VERIFICACAO (Pino 16) STATUS: "); Serial.println(currentEntradaVerificacaoState == HIGH ? "HIGH (Aberto)" : "LOW (Fechado)"); previousEntradaVerificacaoState = currentEntradaVerificacaoState; } bool fcTerreoAberto = (pcf8574_1.digitalRead(FIM_CURSO_TERREO_PRINCIPAL) == HIGH); bool fcAndar1Aberto = (pcf8574_1.digitalRead(FIM_CURSO_ANDAR1_PRINCIPAL) == HIGH); bool fcTerracoAberto = (pcf8574_1.digitalRead(FIM_CURSO_TERRACO_PRINCIPAL) == HIGH); // Contagem para detecção de múltiplos sensores int sensoresAbertosCount = 0; if (fcTerreoAberto) sensoresAbertosCount++; if (fcAndar1Aberto) sensoresAbertosCount++; if (fcTerracoAberto) sensoresAbertosCount++; if (sensoresAbertosCount == 1) { // Apenas um sensor principal está ativo (HIGH) if (fcTerreoAberto) { PosicaoElevador = POSICAO_TERREO; } else if (fcAndar1Aberto) { PosicaoElevador = POSICAO_ANDAR1; } else if (fcTerracoAberto) { PosicaoElevador = POSICAO_TERRACO; } logError = 0; // Se estava em erro de múltiplos sensores, reseta } else if (sensoresAbertosCount >= 2) { // Erro: Múltiplos sensores ativos (HIGH) if (logError != 15) { // Para não imprimir a cada ciclo do loop Serial.println("ERRO - DOIS OU MAIS SENSORES ABERTOS (VERIFICACAO CONTÍNUA)!"); Serial.println("Chamando função log error = 15"); // --- DEBUG ADICIONADO AQUI --- Serial.print("DEBUG NO ERRO 15: Leitura Terreo Principal: "); Serial.println(pcf8574_1.digitalRead(FIM_CURSO_TERREO_PRINCIPAL)); Serial.print("DEBUG NO ERRO 15: Leitura Andar1 Principal: "); Serial.println(pcf8574_1.digitalRead(FIM_CURSO_ANDAR1_PRINCIPAL)); Serial.print("DEBUG NO ERRO 15: Leitura Terraco Principal: "); Serial.println(pcf8574_1.digitalRead(FIM_CURSO_TERRACO_PRINCIPAL)); Serial.print("DEBUG NO ERRO 15: Sensores Abertos Contados: "); Serial.println(sensoresAbertosCount); // --- FIM DO DEBUG ADICIONADO --- } LOG_ERROR(15); } else { // Nenhum sensor principal está ativo (elevador em trânsito ou desconhecido) if (EstadoElevador == ESTADO_PARADO && PosicaoElevador != POSICAO_DESCONHECIDO) { Serial.println("ATENÇÃO: Elevador PARADO e entre andares ou posição perdida. Posição DESCONHECIDA."); PosicaoElevador = POSICAO_DESCONHECIDO; } else if (EstadoElevador == ESTADO_TRABALHANDO) { PosicaoElevador = POSICAO_DESCONHECIDO; } else { PosicaoElevador = POSICAO_DESCONHECIDO; } } // --- Lógica para imprimir a posição do elevador SOMENTE SE HOUVE MUDANÇA --- if (PosicaoElevador != posicaoAnterior) { Serial.print("Posicao Elevador atualizada: "); switch (PosicaoElevador) { case POSICAO_TERREO: Serial.println("TERREO"); break; case POSICAO_ANDAR1: Serial.println("ANDAR1"); break; case POSICAO_TERRACO: Serial.println("TERRACO"); break; case POSICAO_DESCONHECIDO: Serial.println("DESCONHECIDO"); break; default: Serial.println("INDEFINIDO"); break; } posicaoAnterior = PosicaoElevador; // Atualiza a posição anterior } } // --- FUNÇÃO PARA DESCOBRIR A POSIÇÃO COM CHAMADO PARA TERREO (CASO DESCONHECIDO) --- void DESCOBRIR_POSICAO() { Serial.println("\n--- DESCOBRINDO POSIÇÃO DO ELEVADOR ---"); // Lendo os estados dos fins de curso principais diretamente // Assumimos que LOW = aterrado/fechado e HIGH = aberto/não aterrado, como você descreveu. // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso bool fcTerreoAberto = (pcf8574_1.digitalRead(FIM_CURSO_TERREO_PRINCIPAL) == HIGH); // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso bool fcAndar1Aberto = (pcf8574_1.digitalRead(FIM_CURSO_ANDAR1_PRINCIPAL) == HIGH); // CORRIGIDO: Usando pcf8574_1.digitalRead() para o sensor de fim de curso bool fcTerracoAberto = (pcf8574_1.digitalRead(FIM_CURSO_TERRACO_PRINCIPAL) == HIGH); int sensoresAbertosCount = 0; if (fcTerreoAberto) { sensoresAbertosCount++; } if (fcAndar1Aberto) { sensoresAbertosCount++; } if (fcTerracoAberto) { sensoresAbertosCount++; } if (sensoresAbertosCount == 1) { if (fcTerreoAberto) { PosicaoElevador = POSICAO_TERREO; Serial.println("Posição Definida: TERREO."); } else if (fcAndar1Aberto) { PosicaoElevador = POSICAO_ANDAR1; Serial.println("Posição Definida: ANDAR 1."); } else if (fcTerracoAberto) { PosicaoElevador = POSICAO_TERRACO; Serial.println("Posição Definida: TERRACO."); } logError = 0; // Resetar erro se a posição foi descoberta com sucesso // erroMultiplosSensoresAtivo = false; // Resetar flag de erro } else if (sensoresAbertosCount >= 2) { // if (!erroMultiplosSensoresAtivo) { // Imprimir o erro apenas uma vez até que seja resolvido Serial.println("ERRO - DOIS OU MAIS SENSORES ABERTOS!"); LOG_ERROR(15); } else { // nenhum sensor principal está aberto Serial.println("Sensores desconhecido, Elevador nao esta em nenhuma posicao principal"); Serial.println("Iniciando descida até o térreo para descobrir posição..."); PosicaoElevador = POSICAO_DESCONHECIDO; // Certifica-se que a posição é desconhecida antes de mover DESCER_DESCONHECIDO_TERREO(); // Inicia o procedimento de busca pelo térreo } } // --- FUNÇÃO PARA ABRIR AS PORTAS DO ELEVADOR VIA RF COM RETENTATIVAS --- void ABRIR_PORTAS() { Serial.println("DEBUG: Funcao ABRIR_PORTAS acionada. Enviando comando para abrir portas via RF com retentativas..."); // *** ATENÇÃO: Substitua estas linhas pela sua lógica real de RF *** // const String COMANDO_RF_ABRIR_PORTAS = "CMD_ABRIR"; // const String COMANDO_RF_ACK_ABRIR_PORTAS = "ACK_ABRIR"; // ******************************************************************* const int MAX_TENTATIVAS = 5; // Número de tentativas para enviar o comando RF const unsigned long INTERVALO_TENTATIVA = 3000; // 3 segundos entre as tentativas const unsigned long TIMEOUT_ACK_POR_TENTATIVA = 5000; // 5 segundos para o ACK RF const unsigned long TIMEOUT_ABERTURA_FISICA = 60000; // 60 segundos para as portas abrirem fisicamente bool ackRecebido = false; bool portasAbertasFisicamente = false; // Flag para monitorar o sensor físico delay(2000); Serial.println("--- Estado inicial das portas (ABRIR_PORTAS) ---"); // CORRIGIDO: Usando pcf8574_2.digitalRead() para o único sensor de porta Serial.print(" SENSOR_FISICO_PORTAS (Pino 9): "); Serial.println(pcf8574_2.digitalRead(SENSOR_FISICO_PORTAS) == HIGH ? "ABERTO" : "FECHADO"); Serial.println("-------------------------------------------------"); // --- Etapa 1: Enviar Comando RF e Esperar ACK --- for (int tentativa = 1; tentativa <= MAX_TENTATIVAS; tentativa++) { Serial.print("Tentativa "); Serial.print(tentativa); Serial.println(" de enviar comando RF para abrir portas..."); // *** ATENÇÃO: Substitua esta linha pela sua função real de envio de RF *** // ENVIAR_COMANDO_RF(COMANDO_RF_ABRIR_PORTAS); // ******************************************************************* unsigned long startTimeTentativa = millis(); while (millis() - startTimeTentativa < TIMEOUT_ACK_POR_TENTATIVA) { // *** BLOCO DE SIMULAÇÃO RF E ABERTURA FÍSICA (MANTER PARA TESTES) *** // Simula ACK e abertura física na primeira tentativa para testes if (tentativa == 1) { ackRecebido = true; // Simula a porta abrindo (mude para false para testar o erro 64) // Se você quiser simular a porta abrindo um pouco depois do ACK, pode adicionar um delay aqui // portasAbertasFisicamente = true; // Removido para garantir a verificação real abaixo } // *** FIM DO BLOCO DE SIMULAÇÃO *** // *** ATENÇÃO: Substitua esta linha pela sua função real de leitura de RF *** // String comandoRecebido = LER_COMANDO_RF(); // if (comandoRecebido == COMANDO_RF_ACK_ABRIR_PORTAS) { // ackRecebido = true; // } // ******************************************************************* // Verifica se as portas abriram fisicamente (SENSOR_FISICO_PORTAS == HIGH) // CORRIGIDO: Usando pcf8574_2.digitalRead() para o único sensor de porta if (pcf8574_2.digitalRead(SENSOR_FISICO_PORTAS) == HIGH) { portasAbertasFisicamente = true; } // Se ambos forem confirmados, podemos sair antes do timeout if (ackRecebido && portasAbertasFisicamente) { Serial.println("DEBUG: ACK RF e abertura fisica confirmados durante espera inicial."); logError = 0; // Reseta qualquer erro anterior return; // Sai da função ABRIR_PORTAS() com sucesso } delay(50); // Pequeno atraso para não sobrecarregar o loop de leitura/verificação } // Após o TIMEOUT_ACK_POR_TENTATIVA if (ackRecebido) { Serial.println("ACK RF recebido nesta tentativa. Prosseguindo para verificacao fisica."); break; // Sai do loop de tentativas RF para a verificação física } else { Serial.println("ACK RF nao recebido nesta tentativa. Reenviando..."); // Espera o restante do intervalo entre tentativas (se ainda houver tentativas) if (tentativa < MAX_TENTATIVAS) { delay(INTERVALO_TENTATIVA - (millis() - startTimeTentativa)); } } } // Fim do loop de tentativas de ACK RF if (!ackRecebido) { Serial.println("ERRO 23: Todas as tentativas de enviar/receber ACK RF de abertura falharam."); LOG_ERROR(23); delay(100); // Pequeno delay conforme o código original // --- Segunda alternativa: Tentar verificar a abertura física das portas por 20 segundos --- Serial.println("ERRO 23: 2ª tentativa, verificando abertura física das portas por 20 segundos."); unsigned long startTimeSegundaAlternativa = millis(); const unsigned long TIMEOUT_SEGUNDA_ALTERNATIVA_FISICA = 20000; // 20 segundos // Enquanto o sensor de porta estiver FECHADO (lendo LOW) // CORRIGIDO: Usando pcf8574_2.digitalRead() para o único sensor de porta while ((pcf8574_2.digitalRead(SENSOR_FISICO_PORTAS) == LOW) && (millis() - startTimeSegundaAlternativa < TIMEOUT_SEGUNDA_ALTERNATIVA_FISICA)) { delay(50); // Pequeno atraso para não sobrecarregar } // --- Verificação do resultado após o loop da segunda alternativa --- // Se o sensor está HIGH, significa que as portas ABRIRAM fisicamente // CORRIGIDO: Usando pcf8574_2.digitalRead() para o único sensor de porta if (pcf8574_2.digitalRead(SENSOR_FISICO_PORTAS) == HIGH) { Serial.println("Portas abriram fisicamente na 2a tentativa (sem ACK RF)."); logError = 0; // Reseta o erro Serial.println("Abertura de portas concluida com sucesso (fisico confirmado)."); return; // Sai da função com sucesso } else { // Se o loop terminou porque o tempo limite foi atingido E as portas ainda não abriram Serial.println("ERRO 64: Portas NAO abriram fisicamente apos 2a tentativa (sem ACK RF). Verificar motor da porta ou sensor de abertura!"); LOG_ERROR(64); // Este é um erro do tipo RESET (volta para o estado PARADO) return; // Sai da função } } // --- Etapa 2: ACK RF Recebido. Agora Aguarda Abertura Física --- Serial.println("ACK RF recebido. Aguardando abertura física das portas (sensor de porta 9 HIGH)..."); unsigned long startTimeAberturaFisica = millis(); // Enquanto o sensor de porta estiver FECHADO (lendo LOW) // CORRIGIDO: Usando pcf8574_2.digitalRead() para o único sensor de porta while (pcf8574_2.digitalRead(SENSOR_FISICO_PORTAS) == LOW) { if (millis() - startTimeAberturaFisica > TIMEOUT_ABERTURA_FISICA) { Serial.println("ERRO 64: ACK RF recebido, mas portas NAO abriram fisicamente no tempo limite. Verificar motor da porta ou sensor de abertura!"); LOG_ERROR(64); return; // Sai da função } delay(50); // Pequeno atraso } // Portas abriram fisicamente (sensor de porta 9 acionado)! Serial.println("Portas abriram fisicamente (sensor de porta 9 acionado)!"); logError = 0; // Reseta qualquer erro Serial.println("Abertura de portas concluida com sucesso (RF e Fisico)!"); return; // Sucesso (void function) } // --- FUNÇÃO PARA ENVIAR COMANDO RF DE FECHAR PORTAS E AGUARDAR ACK --- bool FECHAR_PORTAS_RF() { Serial.println("DEBUG: Funcao FECHAR_PORTAS_RF acionada. Enviando comando para fechar portas via RF..."); // *** ATENÇÃO: Substitua estas linhas pela sua lógica real de RF *** // const String COMANDO_RF_FECHAR_PORTAS = "CMD_FECHAR"; // Exemplo: Seu comando para enviar // const String COMANDO_RF_ACK_FECHAR_PORTAS = "ACK_FECHAR"; // Exemplo: O ACK que você espera // ******************************************************************* const int MAX_TENTATIVAS_RF = 3; // Número de tentativas para enviar o comando RF const unsigned long INTERVALO_TENTATIVA_RF = 2000; // 2 segundos entre as tentativas (mantido, mas o foco é o timeout por tentativa) const unsigned long TIMEOUT_ACK_POR_TENTATIVA = 5000; // 5 segundos para o ACK RF const unsigned long TIMEOUT_FECHAMENTO_FISICO = 60000; // 60 segundos para as portas fecharem fisicamente bool ackRecebido = false; bool portasFechadasFisicamente = false; // Flag para monitorar o fechamento físico Serial.println("DEBUG: Estado anterior ao chamado para fechar portas (FECHAR_PORTAS_RF):"); // CORRIGIDO: Usando pcf8574_2.digitalRead() para o único sensor de porta Serial.print(" SENSOR_FISICO_PORTAS (Pino 9): "); Serial.println(pcf8574_2.digitalRead(SENSOR_FISICO_PORTAS) == LOW ? "FECHADO" : "ABERTO"); // --- Etapa 1: Enviar Comando RF e Esperar ACK --- for (int tentativa = 1; tentativa <= MAX_TENTATIVAS_RF; tentativa++) { Serial.print("Tentativa RF "); Serial.print(tentativa); Serial.println(" de fechar portas..."); // *** ATENÇÃO: Substitua esta linha pela sua função real de envio de RF *** // ENVIAR_COMANDO_RF(COMANDO_RF_FECHAR_PORTAS); // ******************************************************************* unsigned long startTimeACK = millis(); while (millis() - startTimeACK < TIMEOUT_ACK_POR_TENTATIVA) { // *** BLOCO DE SIMULAÇÃO RF (MANTER PARA TESTES) *** // Simula ACK recebido após 500ms na primeira tentativa if (tentativa == 1 && millis() - startTimeACK >= 500) { ackRecebido = true; Serial.println("ACK RF de fechamento de portas recebido (simulado)!"); break; // Sai do while interno (espera de ACK) } // *** FIM DO BLOCO DE SIMULAÇÃO *** // *** ATENÇÃO: Substitua esta linha pela sua função real de leitura de RF *** // String comandoRecebido = LER_COMANDO_RF(); // if (comandoRecebido == COMANDO_RF_ACK_FECHAR_PORTAS) { // ackRecebido = true; // break; // Sai do while interno (espera de ACK) // } // ******************************************************************* delay(50); // Pequeno atraso para não sobrecarregar o loop de leitura } if (ackRecebido) { Serial.println("ACK RF de fechamento de portas confirmado com sucesso!"); break; // Sai do loop de tentativas RF } else { Serial.println("ACK RF nao recebido nesta tentativa. Reenviando..."); // Espera o restante do intervalo entre tentativas (se ainda houver tentativas) if (tentativa < MAX_TENTATIVAS_RF) { delay(INTERVALO_TENTATIVA_RF - (millis() - startTimeACK)); } } } // Fim do loop de tentativas de ACK RF // Se chegou aqui e o ACK não foi recebido após todas as tentativas RF if (!ackRecebido) { Serial.println("ERRO 22: Timeout atingido para ACK RF de fechamento de portas. Nao recebi confirmacao."); LOG_ERROR(22); return false; // Retorna false, pois o comando não foi confirmado via RF } // --- Etapa 2: ACK RF Recebido. Agora Aguarda Fechamento Físico --- Serial.println("ACK RF recebido. Agora aguardando fechamento físico das portas (SENSOR_FISICO_PORTAS LOW)..."); unsigned long startTimeFechamentoFisico = millis(); // Enquanto o sensor de porta estiver ABERTO (lendo HIGH) // CORRIGIDO: Usando pcf8574_2.digitalRead() para o único sensor de porta while (pcf8574_2.digitalRead(SENSOR_FISICO_PORTAS) == HIGH) { // Continua enquanto o sensor estiver aberto if (millis() - startTimeFechamentoFisico > TIMEOUT_FECHAMENTO_FISICO) { // A mensagem de erro agora é específica para o novo sensor de porta. Serial.println("ERRO 65: Timeout de fechamento fisico das portas. O sensor de porta (9) nao ativou!"); LOG_ERROR(65); return false; // Retorna false, pois a verificacao nao foi concluida } delay(50); // Pequeno atraso } Serial.println("Portas fechadas fisicamente (SENSOR_FISICO_PORTAS acionado)!"); portasFechadasFisicamente = true; // Confirma que as portas fecharam // Se chegou aqui, ACK foi recebido E portas fecharam fisicamente logError = 0; // Reseta qualquer erro Serial.println("Fechamento de portas concluido com sucesso (RF e Fisico)!"); // CORRIGIDO: Usando pcf8574_3.digitalWrite() para o relé contatora pcf8574_3.digitalWrite(RELE_CONTATORA, LOW); delay(100); return true; // Sucesso } // --- FUNÇÃO PARA VERIFICAÇÃO DE PORTAS FECHADAS COM TIMEOUT --- bool VERIFICACAO_PORTAS() { Serial.println("DEBUG: Funcao VERIFICACAO_PORTAS acionada. Verificando estado da porta..."); // Primeiro, envia o comando RF para fechar as portas e espera o ACK. // Esta chamada já inclui a verificação do ACK RF e o timeout para o fechamento físico // dentro dela (logica do ERRO 65). if (!FECHAR_PORTAS_RF()) { Serial.println("VERIFICACAO_PORTAS abortada: Falha no processo de fechamento RF/Fisico."); EstadoElevador = ESTADO_PARADO; // Garante que o elevador está parado // logError já foi definido por FECHAR_PORTAS_RF() (ERRO 22 ou ERRO 65) return false; // Sai da função se o FECHAR_PORTAS_RF() falhou } // Se FECHAR_PORTAS_RF() retornou true, significa que o ACK foi recebido E o sensor físico // indicou que as portas fecharam. No entanto, vamos adicionar uma última verificação explícita aqui // para maior robustez, garantindo que o sensor esteja de fato em LOW. Serial.println("Comando RF para fechar portas enviado e ACK recebido. Portas supostamente fechadas. Confirmando estado físico final..."); unsigned long startTime = millis(); // Tempo limite para a verificação final do sensor físico (60 segundos, conforme solicitado) const unsigned long TIMEOUT_VERIFICACAO_FINAL_FISICA = 60000; // NOVO: Verifica a única entrada SENSOR_FISICO_PORTAS // Enquanto o SENSOR_FISICO_PORTAS estiver ABERTO (lendo HIGH) // CORRIGIDO: Usando pcf8574_2.digitalRead() para o único sensor de porta while (pcf8574_2.digitalRead(SENSOR_FISICO_PORTAS) == HIGH) { // Continua enquanto o sensor estiver aberto if (millis() - startTime > TIMEOUT_VERIFICACAO_FINAL_FISICA) { Serial.println("ERRO 20: Tempo limite final para verificacao das portas. O sensor de porta (9) nao ativou!"); LOG_ERROR(20); // Aqui voce pode adicionar um alarme sonoro, etc. return false; // Retorna falso, indicando que a verificacao final falhou } // Pequeno atraso para nao sobrecarregar o loop de verificacao delay(50); } // Se saiu do loop, significa que o SENSOR_FISICO_PORTAS está em LOW. Serial.println("Portas verificadas: Sensor em estado NF. Prontas para o movimento."); logError = 0; // Reseta o erro se a verificação foi bem-sucedida return true; // Retorna verdadeiro, indicando sucesso } // --- Implementação da Função LOG_ERROR com Categorias Detalhadas --- void LOG_ERROR(int errorCode) { logError = errorCode; // Sempre registra o último código de erro globalmente Serial.print("LOG_ERROR: Codigo: "); Serial.print(errorCode); Serial.print(" - Mensagem: "); // Declara flags para controlar as ações específicas bool isReparoError = false; bool isResetError = false; bool isPassiveError = false; bool isParadaEmergenciaError = false; // --- Mapeamento de Erros para Categorias e Mensagens --- switch (errorCode) { case 0: // Nenhum erro Serial.println("Nenhum erro."); break; // --- Erros de REPARO --- case 15: // Múltiplos sensores principais de posição ativos Serial.println("REPARO: Multiplos sensores principais de posicao ativos. Requer intervencao manual."); isReparoError = true; break; case 21: // Timeout de movimento: Terraço para Andar 1 case 24: // Timeout de movimento: Térreo para Andar 1 case 25: // Timeout de movimento: Andar 1 para Térreo case 26: // Timeout de movimento: Terraço para Térreo case 27: // Timeout de movimento: Andar 1 para Terraço case 28: // Timeout de movimento: Térreo para Terraço case 29: // Timeout de movimento: Recalibragem para Térreo (posição desconhecida) Serial.println("REPARO: Timeout de movimento. Elevador nao chegou ao destino esperado. Requer verificacao."); isReparoError = true; break; // --- Erros de RESET --- case 20: // Tempo limite atingido para o fechamento físico das portas. Serial.println("RESET: Timeout no fechamento fisico das portas. Tentando resetar."); isResetError = true; break; case 64: // ACK RF de abertura recebido, mas portas NÃO abriram fisicamente no tempo limite. Serial.println("RESET: Porta nao abriu fisicamente apos ACK RF. Tentando resetar."); isResetError = true; break; case 65: // ACK RF de fechamento recebido, mas portas NÃO fecharam fisicamente no tempo limite. Serial.println("RESET: Porta nao fechou fisicamente apos ACK RF. Tentando resetar."); isResetError = true; break; // --- Erros PASSIVO --- case 22: // Falha no envio/recebimento RF para fechar portas (ACK não recebido). Serial.println("PASSIVO: Falha no ACK RF de fechamento. Operacao continua."); isPassiveError = true; break; case 23: // Falha no envio/recebimento RF para abrir portas (ACK não recebido). Serial.println("PASSIVO: Falha no ACK RF de abertura. Operacao continua."); isPassiveError = true; break; // --- Erros de PARADA EMERGENCIA --- case 41: // Sensor principal do Andar 1 ativado prematuramente durante descida do Terraço. case 42: // Sensor principal do Andar 1 ativado prematuramente durante subida do Térreo. case 43: // Sensor principal do Térreo ativado prematuramente durante descida do Andar 1. case 44: // Sensor principal do Térreo ativado prematuramente durante descida do Terraço. case 45: // Sensor principal do Terraço ativado prematuramente durante subida do Andar 1. case 46: // Sensor principal do Terraço ativado prematuramente durante subida do Térreo. case 47: // Sensor principal do Térreo ativado prematuramente durante recalibragem. Serial.println("PARADA EMERGENCIA: Sensor principal ativado prematuramente. Ativando sequencia de emergencia."); isParadaEmergenciaError = true; break; default: // Erro desconhecido Serial.println("ERRO: Codigo desconhecido. Tratado como REPARO por seguranca."); isReparoError = true; // Por segurança, erros desconhecidos são tratados como REPARO break; } // --- Ações Baseadas nas Categorias de Erro --- // Ações para REPARO if (isReparoError) { Serial.println("Acao: REPARO - Ativando reles de seguranca e sirene infinitamente. Desligar disjuntor."); EstadoElevador = ESTADO_ERRO; // Garante que o estado é de erro turnAllRelaysOff(); // Desliga reles de movimento // Ativa reles de segurança e sirene indefinidamente // CORRIGIDO: Usando pcf8574_3.digitalWrite() para os relés e sirene pcf8574_3.digitalWrite(RELE_CONTATORA, HIGH); pcf8574_3.digitalWrite(RELE_PARADA_EMERGENCIAL, HIGH); pcf8574_3.digitalWrite(SIRENE_ERRO, HIGH); // Entra em um loop infinito, o elevador para e aguarda intervenção manual (reset físico) while (true) { delay(100); // Pequeno delay para evitar loop muito rápido } } // Ações para RESET else if (isResetError) { Serial.println("Acao: RESET - Sirene por 1s, depois elevador volta a esperar chamados."); // CORRIGIDO: Usando pcf8574_3.digitalWrite() para os relés e sirene pcf8574_3.digitalWrite(RELE_GIRA_PARA_MOTOR, LOW); pcf8574_3.digitalWrite(RELE_SENTIDO_GIRO_SOBE_DESCE, LOW); pcf8574_3.digitalWrite(SIRENE_ERRO, HIGH); // Liga a sirene delay(1000); // Sirene por 1 segundo pcf8574_3.digitalWrite(SIRENE_ERRO, LOW); // Desliga a sirene EstadoElevador = ESTADO_PARADO; // Elevador volta ao estado PARADO logError = 0; // Reseta o log de erro // O loop principal continua para esperar um novo chamado } // Ações para PASSIVO else if (isPassiveError) { Serial.println("Acao: PASSIVO - Operacao continua. Falha registrada."); // Não altera EstadoElevador nem desliga reles de forma emergencial // Lógica para registrar data/hora da falha para acesso futuro (requer hardware adicional) } // Ações para PARADA EMERGENCIA (Atualizado conforme sua nova solicitacao) else if (isParadaEmergenciaError) { Serial.println("Acao: PARADA EMERGENCIA - Ativando sequencia de reles e sirene piscante."); EstadoElevador = ESTADO_ERRO; // Define o estado do elevador como ERRO (parada) turnAllRelaysOff(); // Desliga todos os relés de movimento para segurança // 1. Ativa RELE_PARADA_EMERGENCIAL // CORRIGIDO: Usando pcf8574_3.digitalWrite() para o relé pcf8574_3.digitalWrite(RELE_PARADA_EMERGENCIAL, HIGH); Serial.println("RELE_PARADA_EMERGENCIAL ativado."); // 2. Espera 1 segundo delay(1000); // 3. Ativa RELE_CONTATORA // CORRIGIDO: Usando pcf8574_3.digitalWrite() para o relé pcf8574_3.digitalWrite(RELE_CONTATORA, HIGH); Serial.println("RELE_CONTATORA ativado."); // 4. Acionar a sirene por 1 segundo e desligar por 3x for (int i = 0; i < 3; i++) { // CORRIGIDO: Usando pcf8574_3.digitalWrite() para a sirene pcf8574_3.digitalWrite(SIRENE_ERRO, HIGH); // Sirene ON delay(1000); // 1 segundo ligada pcf8574_3.digitalWrite(SIRENE_ERRO, LOW); // Sirene OFF if (i < 2) { // Não atrasa depois da última piscada delay(1000); // Espera 1 segundo DESLIGADA } } //5. Abre as portas ABRIR_PORTAS(); // 6. Reseta o codigo para o loop inicial EstadoElevador = ESTADO_PARADO; // Elevador volta ao estado PARADO logError = 0; // Reseta o log de erro Serial.println("PARADA EMERGENCIA: Sequencia concluida. Elevador resetado para aguardar chamados."); // A função termina, e o loop() principal continuará a execução normal } } // --- FUNÇÃO PARA DESLIGAR TODOS OS RELÉS --- void turnAllRelaysOff() { for (int i = 0; i <= 7; i++) { // Os pinos do PCF8574 vão de 0 a 7 pcf8574_3.digitalWrite(i, LOW); // Desliga os pinos do pcf8574_3 pcf8574_4.digitalWrite(i, LOW); // Desliga os pinos do pcf8574_4 } Serial.println("Todos os reles estao DESATIVADOS na inicializacao."); }