Ir ao conteúdo
  • Cadastre-se

Arduino Função (delay) no Arduino


Posts recomendados

Bom dia pessoal.

Sou novo aqui no canal e também no mundo da programação Arduino.

Preciso de ajuda em um projeto de irrigação que estou desenvolvendo.

Basicamente o projeto possui leitura de sensores (DHT22, sensor capacitivo de umidade do solo, sensores de nível de água Sharp), um módulo RTC DS1307, relés para acionamento das solenóides e um visor LCD 20x4.

A irrigação precisa ser feita considerando-se o dia da semana e horários específicos, e cada item (solenoide) também é acionada de acordo com um dia específico e por um tempo também específico.

Em resumo, o sistema verifica em qual dia está e executa o processo daquele determinado dia, se atender mais alguns requisitos inseridos com função (if), como por exemplo se a umidade do solo está baixa e se o reservatório de água está completo.

O problema é que quando o sistema inicia a irrigação ele "congela" todos os outros processos, o que imagino ser por conta dos delays entre cada acionamento das solenóides.

Isso faz que por vezes o visor lcd, quando o processo termina, apresente caracteres estranhos, e por vezes o sistema todo trava e não desliga algum dos relés, fazendo com que se irrigue mais do que o necessário, além esvaziar todo o reservatório de água.

Não sei se é possível separar os processos de forma que um não interfira no outro, e alguns possam continuar executando em paralelo. 

Imagino que os sensores e o modulo RTC deveriam continuar em execução mesmo quando os relés estão sendo acionados.

Vocês podem me ajudar com esse problema? 

Anexo o sketch que estou usando.

SITIO_Irrig_v1.9.2_umidadesolo.zip

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Há maneiras de se abordar isso com uso de interrupções ao invés de if's. P.ex. a de mudança de estado de pino. Mas claro tem um monte de 'depende'. Sugiro você publicar ou estudar seus desenhos e esquemas. Também pode criar um fluxograma do sistema pra te guiar ou clarear melhor

 

1 hora atrás, Alexandre Mariz Paiva disse:

O problema é que quando o sistema inicia a irrigação ele "congela" todos os outros processos, o que imagino ser por conta dos delays entre cada acionamento das solenóides.

Isto também pode ser sintoma de problema na concepção do hardware: solenoide quando aciona gera interferências que devem ser suprimidas.

Não baixei seu anexo. Sugiro publicar direto no post usando a tag <> code

Link para o comentário
Compartilhar em outros sites

Entendi.

Vou tentar montar um fluxo para melhor esclarecimento.

Sobre a publicação do código, segue o mesmo abaixo.

 

/* 

  # Projeto    : Irrigação automática da plantação de orgânicos
  # Autor      : Alexandre Mariz Paiva
  # Data       : 16.11.2021
  # versão     : 1.9.2
  
  # Componentes: Arduino Uno Mega 2560, RTC DS1307 i2C, módulo DHT22,
                 Display LCD 20x4 i2C, módulo relé 8 canais, módulo relé 2 canais
                 Sensor nível de água Sharp, LEDs, push buttons
*/

// INCLUSÃO DE BIBLIOTECAS
#include <Wire.h>          
#include <LiquidCrystal_I2C.h>   //biblioteca para LCD I2C 
#include <DHT.h>

// DEFINIÇÕES
#define endereco  0x27    //endereço do display lcd I2C
#define colunas   20      //quantidade de colunas do display lcd
#define linhas    4       //quantidade de linhas do display lcd
#define DHT22_PIN 12       //pino de leitura do sensor DHT
#define DHTTYPE DHT22     //definição do tipo do sensor (se DHT11, DHT21 ou DHT22)
#define enderecoI2C 0x68      //endereço do modulo RTC
#define Sensor1_cx5M 7     //pino de leitura do sensor de nivel de agua
#define Sensor2_cx5M 6
#define Sensor3_cx5M 5
#define UmidSolo A0
 byte segundo, minuto, hora, diaDaSemana, diaDoMes, mes, ano;     //definicao das variaveis para um conjunto de 7 dados, pois o modulo RTC trabalha em grupos de 7 Bytes

// INSTANCIANDO OBJETOS
LiquidCrystal_I2C lcd(endereco, colunas, linhas);
DHT dht(DHT22_PIN, DHTTYPE);

 //declara as variaveis de execucao dos pinos que acionarao os reles.
 int rele1_CH1 = 22;
 int rele1_CH2 = 23;
 int rele1_CH3 = 24;
 int rele1_CH4 = 25;
 int rele1_CH5 = 26;
 int rele1_CH6 = 27;
 int rele1_CH7 = 28;
 int rele1_CH8 = 29;
 int rele2_CH1 = 30;
 int rele2_CH2 = 31;
  
 //declara a inicializacao do sensor de nivel
 int sensor1_cx5M = 1, sensor2_cx5M = 1, sensor3_cx5M = 1;
 int nivelinicial = 0;

 //declara a variável de acionamento do sensor umidade do solo, considerando valor para terra totalmente umida = 800
 int valoracionamentoUmid = 800;
  
  //declara as variaveis de execucao dos pinos que acenderao os LEDs no case LCD
 int ledred = 51;
 int ledgreen = 52;
 int ledgreenblink = 53;

   //declara as variaveis de execucao dos pinos que acenderao os LEDs no case botões
 int ledbotao1 = 44;
 int ledbotao2 = 45;
 int ledbotao3 = 46;
 int ledbotao4 = 47;
 int ledbotao5 = 48;
 int ledbotao6 = 49;

 //declara variáveis dos push buttons
 int botao1 = 38;
 int botao2 = 39;
 int botao3 = 40;
 int botao4 = 41;
 int botao5 = 42;
 int botao6 = 43;

 //variáveis booleanas para acionamento por push button
 bool RELE1_CH1 = 0;
 bool RELE1_CH2 = 0;
 bool RELE1_CH3 = 0;
 bool RELE1_CH4 = 0;
 bool RELE1_CH5 = 0;
 bool RELE1_CH6 = 0;
 bool RELE1_CH7 = 0;
 bool RELE1_CH8 = 0;
 bool RELE2_CH1 = 0;
 bool RELE2_CH2 = 0;
 
/* //variavel booleana para agrupamento de dados relés
 bool agrupaDadosReles = 0; */
 

void setup() {
   lcd.init();   //inicia a comunicação com o LCD
   lcd.setBacklight(HIGH);  //liga a luz de fundo do LCD
   Wire.begin();             //inicializando a biblioteca.
   Serial.begin(9600);       //configurando a comunicação via porta serial à uma velocidade de 9600bps(baud).
   dht.begin();  //Inica a comunicação com Monitor serial
  
  //configuraModulo();         //chamando a função para configurar o módulo.
  
   //define os pinos dos relés como "saída" 
   pinMode(rele1_CH1, OUTPUT); 
   pinMode(rele1_CH2, OUTPUT); 
   pinMode(rele1_CH3, OUTPUT); 
   pinMode(rele1_CH4, OUTPUT); 
   pinMode(rele1_CH5, OUTPUT); 
   pinMode(rele1_CH6, OUTPUT); 
   pinMode(rele1_CH7, OUTPUT); 
   pinMode(rele1_CH8, OUTPUT); 
   pinMode(rele2_CH1, OUTPUT); 
   pinMode(rele2_CH2, OUTPUT);

   //define o pino do sensor como "entrada"
   pinMode(Sensor1_cx5M, INPUT);
   pinMode(Sensor2_cx5M, INPUT);
   pinMode(Sensor3_cx5M, INPUT);  

   //define o pino do sensor umidade de solo como "entrada
   pinMode(UmidSolo, INPUT);

   //define os pinos dos LEDs como "saída" 
   pinMode(ledred, OUTPUT);
   pinMode(ledgreen, OUTPUT);
   pinMode(ledgreenblink, OUTPUT);
   pinMode(ledbotao1, OUTPUT);
   pinMode(ledbotao2, OUTPUT);
   pinMode(ledbotao3, OUTPUT);
   pinMode(ledbotao4, OUTPUT);
   pinMode(ledbotao5, OUTPUT);
   pinMode(ledbotao6, OUTPUT);

   //define os pinos dos botões como "entrada"
   pinMode(botao1, INPUT_PULLUP);
   pinMode(botao2, INPUT_PULLUP);
   pinMode(botao3, INPUT_PULLUP);
   pinMode(botao4, INPUT_PULLUP);
   pinMode(botao5, INPUT_PULLUP);
   pinMode(botao6, INPUT_PULLUP);
}



void loop() 
{
  digitalWrite(ledgreen, LOW); //apaga o led verde
  digitalWrite(ledgreenblink, LOW); //apaga o led verde
  digitalWrite(ledred, HIGH); //acende o rele vermelho

   //Loop de execução dos botões
  if(digitalRead(botao1) == LOW) {
    RELE2_CH1 = !RELE2_CH1;     //troca o estado do relé na variável
    digitalWrite(ledbotao1, HIGH);
    digitalWrite(rele2_CH1, RELE2_CH1); //aciona bomba e solenoide da horta externa
    while(digitalRead(botao1) == LOW);
      if(RELE2_CH1 == 0) {
        digitalWrite(ledbotao1, LOW);
      } 
   }
  else if (digitalRead(botao2) == LOW) {
    RELE1_CH1 = !RELE1_CH1;     //troca o estado do relé na variável
    digitalWrite(ledbotao2, HIGH);
    digitalWrite(rele1_CH1, RELE1_CH1); //aciona a horta debaixo
    while(digitalRead(botao2) == LOW);
      if(RELE1_CH1 == 0) {
        digitalWrite(ledbotao2, LOW);
      } 
   }
  else if(digitalRead(botao3) == LOW) {
    RELE1_CH2 = !RELE1_CH2;   //troca o estado do relé na variável
    RELE1_CH3 = !RELE1_CH3; 
    digitalWrite(ledbotao3, HIGH);
    digitalWrite(rele1_CH2, RELE1_CH2); //aciona o colibri e gotejo da estufa
    digitalWrite(rele1_CH3, RELE1_CH3);
    while(digitalRead(botao3) == LOW);
        if((RELE1_CH2 == 0) && (RELE1_CH3 == 0)) {
        digitalWrite(ledbotao3, LOW);
      } 
   }
  else if(digitalRead(botao4) == LOW) { 
    RELE1_CH5 = !RELE1_CH5;     //troca o estado do relé na variável
    digitalWrite(ledbotao4, HIGH);
    digitalWrite(rele1_CH5, RELE1_CH5); //aciona o pomar
    while(digitalRead(botao4) == LOW);
      if(RELE1_CH5 == 0) {
        digitalWrite(ledbotao4, LOW);
      } 
  }
  else if(digitalRead(botao5) == LOW) {
    RELE1_CH4 = !RELE1_CH4;   //troca o estado do relé na variável
    RELE1_CH6 = !RELE1_CH6;   
    digitalWrite(ledbotao5, HIGH);
    digitalWrite(rele1_CH4, RELE1_CH4);  //aciona mandioca e cana
    digitalWrite(rele1_CH6, RELE1_CH6);
    while(digitalRead(botao5) == LOW);
      if((RELE1_CH4 == 0) && (RELE1_CH6 == 0)) {
        digitalWrite(ledbotao5, LOW);
      } 
   }
  else if(digitalRead(botao6) == LOW) {
    RELE1_CH7 = !RELE1_CH7;   //troca o estado do relé na variável
    digitalWrite(ledbotao6, HIGH);
    digitalWrite(rele1_CH7, RELE1_CH7);  //aciona abacaxi
    while(digitalRead(botao6) == LOW);
      if(RELE1_CH7 == 0) {
        digitalWrite(ledbotao6, LOW);
      } 
   } 
 
 
  DadosmoduloRTC();    //chamando a função para imprimir os dados gravados no módulo RTC
  DadosmoduloDHT();    //chamando a função para imprimir os dados gravados no módulo DHT

  //funções de leitura do sensor umidade do solo
  int valorUmidSolo = analogRead(UmidSolo);
    /*Serial.print("Umidade Solo: ");
    Serial.println(valorUmidSolo);*/

  if(valorUmidSolo <= valoracionamentoUmid) {
    Serial.print("Umidade Solo: ");
    Serial.println("OK");
    lcd.setCursor(10,0);
    lcd.print("US: ");
    lcd.print("OK");
  }
  
  if(valorUmidSolo > valoracionamentoUmid) {
    Serial.print("Umidade Solo: ");
    Serial.println("MOLHAR");
    lcd.setCursor(10,0);
    lcd.print("US: ");
    lcd.print("MOLHAR");
  }
  
  
  //Loop de execução sensor de nível
  int sensor1_cx5M = digitalRead(Sensor1_cx5M);
  int sensor2_cx5M = digitalRead(Sensor2_cx5M);
  int sensor3_cx5M = digitalRead(Sensor3_cx5M);
 
  if ((sensor1_cx5M == 0) && (sensor2_cx5M == 0) && (sensor3_cx5M == 0)) {
    lcd.setCursor(0,2);
    lcd.print("Reserv:    Cheio   ");
    Serial.print("Reservatório: ");
    Serial.println("Cheio");
  }
  else if ((sensor1_cx5M == 0) && (sensor2_cx5M == 0) && (sensor3_cx5M == 1)) {
    lcd.setCursor(0,2);
    lcd.print("Reserv:   75% a 50%");
    Serial.print("Reservatório: ");
    Serial.println("75% a 50%");
  }
  else if ((sensor1_cx5M == 0) && (sensor2_cx5M == 1) && (sensor3_cx5M == 1)) {
    lcd.setCursor(0,2);
    lcd.print("Reserv:   50% a 25%");
    Serial.print("Reservatório: ");
    Serial.println("50% a 25%");
  }
  else if ((sensor1_cx5M == 1) && (sensor2_cx5M == 1) && (sensor3_cx5M == 1)) {
    lcd.setCursor(0,2);
    lcd.print("Reserv:    Vazio   ");
    Serial.print("Reservatório: ");
    Serial.println("Vazio");
  }  
  else {
    Serial.println("ALERTA - ERRO");
    lcd.setCursor(0,2);
    lcd.print("   ALERTA - ERRO   ");
   }
  
  delay(2000);  


   //Loop de execução acionamento reles
    switch(diaDaSemana) {
      case 1:
       if((sensor1_cx5M == 0) && (valorUmidSolo >= valoracionamentoUmid) && (hora == 06) && (minuto == 00)) {
             IrrigacaopadraoManha();
      } 

      if((sensor1_cx5M == 0) && (valorUmidSolo < valoracionamentoUmid) && (hora == 06) && (minuto == 00)) {
            IrrigacaopadraoChuva();  //chama a programação para irrigação da estufa, quando estiver chovendo
      }
     
      if((sensor1_cx5M == 0) && (valorUmidSolo >= valoracionamentoUmid) && (hora == 18) && (minuto == 20)) {  
            IrrigacaopadraonoitePomar();  //chama a programação para irrigação pela manhã

   //PROCESSO POR GRAVIDADE - 2
   digitalWrite(rele1_CH4, HIGH);  //liga gotejo mandiocal
   lcd.setCursor(0,3);
   lcd.print("S1:  ");
   lcd.print("Cana/Mandioca");
   delay(5000);
   digitalWrite(rele1_CH6, HIGH);  //liga gotejo canavial
   delay(600000);
   digitalWrite(rele1_CH4, LOW);   //desliga gotejo mandiocal
   delay(5000);
   digitalWrite(rele1_CH6, LOW);   //desliga gotejo canavial   
      } 
      
     if((sensor1_cx5M == 0) && (valorUmidSolo < valoracionamentoUmid) && (hora == 18) && (minuto == 20)) {
           IrrigacaopadraoChuva();  //chama a programação para irrigação da estufa, quando estiver chovendo
     }break;
    
 
    case 3:
     if((sensor1_cx5M == 0) && (valorUmidSolo >= valoracionamentoUmid) && (hora == 06) && (minuto == 00)) {
           IrrigacaopadraoManha();
      }

     if((sensor1_cx5M == 0) && (valorUmidSolo < valoracionamentoUmid) && (hora == 06) && (minuto == 00)) {  
           IrrigacaopadraoChuva();  //chama a programação para irrigação da estufa, quando estiver chovendo
      }
      
     if((sensor1_cx5M == 0) && (valorUmidSolo >= valoracionamentoUmid) && (hora == 18) && (minuto == 20)) { 
           IrrigacaopadraonoitePomar();

   //PROCESSO POR GRAVIDADE - 2
   lcd.setCursor(0,3);
   lcd.print("S3:  ");
   lcd.print("Cana         ");
   //delay(5000);
   digitalWrite(rele1_CH6, HIGH);  //liga gotejo canavial
   delay(300000);
   digitalWrite(rele1_CH6, LOW);   //desliga gotejo canavial
    } 
     
      if((sensor1_cx5M == 0) && (valorUmidSolo < valoracionamentoUmid) && (hora == 18) && (minuto == 20)) { 
            IrrigacaopadraoChuva();  //chama a programação para irrigação da estufa, quando estiver chovendo
      } break;

    
    case 5:
     if((sensor1_cx5M == 0) && (valorUmidSolo >= valoracionamentoUmid) && (hora == 06) && (minuto == 00)) {
           IrrigacaopadraoManha();
      } 

     if((sensor1_cx5M == 0) && (valorUmidSolo < valoracionamentoUmid) && (hora == 06) && (minuto == 00)) {
           IrrigacaopadraoChuva();  //chama a programação para irrigação da estufa, quando estiver chovendo
      }
       
     if((sensor1_cx5M == 0) && (valorUmidSolo >= valoracionamentoUmid) && (hora == 18) && (minuto == 20)) {
           IrrigacaopadraonoitePomar();

   //PROCESSO POR GRAVIDADE - 2
   digitalWrite(rele1_CH4, HIGH);  //liga gotejo mandiocal
   lcd.setCursor(0,3);
   lcd.print("S5:  ");
   lcd.print("Cana/Mandioca");
   delay(5000);
   digitalWrite(rele1_CH6, HIGH);  //liga gotejo canavial
   delay(480000);
   digitalWrite(rele1_CH4, LOW);   //desliga gotejo mandiocal
   delay(5000);
   digitalWrite(rele1_CH6, LOW);   //desliga gotejo canavial
    }
      
     if((sensor1_cx5M == 0) && (valorUmidSolo < valoracionamentoUmid) && (hora == 18) && (minuto == 20)) {
           IrrigacaopadraoChuva();  //chama a programação para irrigação da estufa, quando estiver chovendo
      } break;

    
      case 4:
       if((sensor1_cx5M == 0) && (valorUmidSolo >= valoracionamentoUmid) && (hora == 06) && (minuto == 00)) {
             IrrigacaopadraoManha();
  
   //PROCESSO POR GRAVIDADE
   delay(5000);
   digitalWrite(rele1_CH7, HIGH);   //liga gotejo abacaxi
   lcd.setCursor(0,3);
   lcd.print("S4:  ");
   lcd.print("Abacaxi        ");
   delay(180000);
   digitalWrite(rele1_CH7, LOW);   //desliga gotejo abacaxi    
          }

       if((sensor1_cx5M == 0) && (valorUmidSolo < valoracionamentoUmid) && (hora == 06) && (minuto == 00)) {
             IrrigacaopadraoChuva();  //chama a programação para irrigação da estufa, quando estiver chovendo
      }
        
       if((sensor1_cx5M == 0) && (valorUmidSolo >= valoracionamentoUmid) && (hora == 18) && (minuto == 20)) {
             IrrigacaopadraoNoite();
      }
      
       if((sensor1_cx5M == 0) && (valorUmidSolo < valoracionamentoUmid) && (hora == 18) && (minuto == 20)) {
             IrrigacaopadraoChuva();  //chama a programação para irrigação da estufa, quando estiver chovendo
      } break;

    
    default:
       if((sensor1_cx5M == 0) && (valorUmidSolo >= valoracionamentoUmid) && (hora == 06) && (minuto == 00)) {
             IrrigacaopadraoManha();     
     } 

       if((sensor1_cx5M == 0) && (valorUmidSolo < valoracionamentoUmid) && (hora == 06) && (minuto == 00)) {
             IrrigacaopadraoChuva();  //chama a programação para irrigação da estufa, quando estiver chovendo
      }

       if((sensor1_cx5M == 0) && (valorUmidSolo >= valoracionamentoUmid) && (hora == 18) && (minuto == 20)) {
             IrrigacaopadraoNoite();
     }

       if((sensor1_cx5M == 0) && (valorUmidSolo < valoracionamentoUmid) && (hora == 18) && (minuto == 20)) {
             IrrigacaopadraoChuva();  //chama a programação para irrigação da estufa, quando estiver chovendo

      }
    }
   }

  

void configuraModulo()
{
  segundo = 0;
  minuto = 14;
  hora = 17;
  diaDaSemana = 2;
  diaDoMes = 16;
  mes = 11;
  ano = 21;

  Wire.beginTransmission(enderecoI2C); //Abrindo o modo I2C no modo de gravação.
  Wire.write((byte)0x00);   //Redefinindo o ponteiro para o primeiro registro (0x00).
 
  //Para escrever dados no módulo é necessário uma conversão de Decimal para Binário
  Wire.write(decToBcd(segundo));      //convertendo os segundos.
  Wire.write(decToBcd(minuto));       //convertendo os minutos.
  Wire.write(decToBcd(hora));         //convertendo as horas.
  Wire.write(decToBcd(diaDaSemana));  //dia da semana, onde o domingo começa com "0".
  Wire.write(decToBcd(diaDoMes));     //convertendo o dia do mês.
  Wire.write(decToBcd(mes));          //convertendo o mês.
  Wire.write(decToBcd(ano));          //convertendo o ano.
  Wire.endTransmission();             //finalizando o modo de gravação.
}


void DadosmoduloDHT() {
  //lcd.clear();
  
   float h = dht.readHumidity();
   float t = dht.readTemperature();
   //float f = dht.readTemperature(true);

   if (isnan(h) || isnan(t)) {
      Serial.println(F("Falha na leitura do sensor DHT!"));
      return;
   }

   //float hif = dht.computeHeatIndex(f, h);
   //float hic = dht.computeHeatIndex(t, h, false);

   lcd.setCursor(0,1);
   lcd.print("T: ");
   lcd.print(t);
   lcd.print((char)223);
   lcd.print("C");
   lcd.setCursor(11,1);
   lcd.print("U: ");
   lcd.print(h);
   lcd.print("%");
   //lcd.setCursor(0,2);
   //lcd.print("S. termica: ");
   //lcd.print(hic);
   //lcd.print((char)223);
   //lcd.print("C");
   lcd.setCursor(0,3);
   lcd.print("Irrigacao desligada");
   //lcd.print(hif);
   
   Serial.print("Temperatura: ");
   Serial.print(t);
   Serial.print(" *C  ");
   Serial.print("Umidade : ");
   Serial.print(h);
   Serial.println("%");
}


void IrrigacaopadraoManha() {
  
    digitalWrite(ledred, LOW); //apaga o led vermelho
    digitalWrite(ledgreen, HIGH); //acende o led verde
    digitalWrite(ledgreenblink, HIGH); //acende o led verde
   
   //PROCESSO PRESSURIZADO
   digitalWrite(rele1_CH1, HIGH); //liga horta debaixo
   lcd.setCursor(0,3);
   lcd.print("S1:  ");
   lcd.print("Hortas        ");  
   delay(5000);
   digitalWrite(rele2_CH1, HIGH); //liga bomba e horta externa
   delay(240000);
   digitalWrite(rele1_CH1, LOW);  //desliga horta debaixo
   delay(5000); 
   digitalWrite(rele2_CH1, LOW);  //desliga bomba e horta externa
   delay(5000);
   
   //PROCESSO POR GRAVIDADE
   digitalWrite(rele1_CH2, HIGH); //liga colibri estufa
   lcd.setCursor(0,3);
   lcd.print("S1: ");
   lcd.print("Estufa        ");
   digitalWrite(rele1_CH3, HIGH); //liga gotejo estufa
   delay(360000);
   digitalWrite(rele1_CH2, LOW);  //desliga colibri estufa
   delay(5000);
   digitalWrite(rele1_CH3, LOW);  //desliga gotejo estufa
}


void IrrigacaopadraonoitePomar() {
  
    digitalWrite(ledred, LOW); //apaga o led vermelho
    digitalWrite(ledgreen, HIGH); //acende o led verde
    digitalWrite(ledgreenblink, HIGH); //acende o led verde
   
   //PROCESSO PRESSURIZADO
   digitalWrite(rele1_CH1, HIGH); //liga horta debaixo
   lcd.setCursor(0,3);
   lcd.print("S1N:  ");
   lcd.print("Hortas       "); 
   delay(5000);
   digitalWrite(rele2_CH1, HIGH); //liga bomba e horta externa
   delay(480000);
   digitalWrite(rele1_CH1, LOW);  //desliga horta debaixo
   delay(5000); 
   digitalWrite(rele2_CH1, LOW);  //desliga bomba e horta externa
   delay(5000);
   
   //PROCESSO POR GRAVIDADE
   digitalWrite(rele1_CH2, HIGH); //liga colibri estufa
   lcd.setCursor(0,3);
   lcd.print("S1N: ");
   lcd.print("Estufa       ");
   delay(5000);
   digitalWrite(rele1_CH3, HIGH); //liga gotejo estufa
   delay(360000);
   digitalWrite(rele1_CH2, LOW);  //desliga colibri estufa
   delay(5000);
   digitalWrite(rele1_CH3, LOW);  //desliga gotejo estufa
   delay(5000);
   digitalWrite(rele1_CH5, HIGH); //liga gotejo pomar
   lcd.setCursor(0,3);
   lcd.print("S1N: ");
   lcd.print("Pomar        ");
   delay(480000);
   digitalWrite(rele1_CH5, LOW);  //desliga gotejo pomar
}


void IrrigacaopadraoNoite() {
  
    digitalWrite(ledred, LOW); //apaga o led vermelho
    digitalWrite(ledgreen, HIGH); //acende o led verde
    digitalWrite(ledgreenblink, HIGH); //acende o led verde
   
   //PROCESSO PRESSURIZADO
   digitalWrite(rele1_CH1, HIGH); //liga horta debaixo
   lcd.setCursor(0,3);
   lcd.print("S1N:  ");
   lcd.print("Hortas       "); 
   delay(5000);
   digitalWrite(rele2_CH1, HIGH); //liga bomba e horta externa
   delay(480000);
   digitalWrite(rele1_CH1, LOW);  //desliga horta debaixo
   delay(5000); 
   digitalWrite(rele2_CH1, LOW);  //desliga bomba e horta externa
   delay(5000);
   
   //PROCESSO POR GRAVIDADE
   digitalWrite(rele1_CH2, HIGH); //liga colibri estufa
   lcd.setCursor(0,3);
   lcd.print("S1N: ");
   lcd.print("Estufa       ");
   delay(5000);
   digitalWrite(rele1_CH3, HIGH); //liga gotejo estufa
   delay(360000);
   digitalWrite(rele1_CH2, LOW);  //desliga colibri estufa
   delay(5000);
   digitalWrite(rele1_CH3, LOW);  //desliga gotejo estufa
}


void IrrigacaopadraoChuva() {

    digitalWrite(ledred, LOW); //apaga o led vermelho
    digitalWrite(ledgreen, HIGH); //acende o led verde
    digitalWrite(ledgreenblink, HIGH); //acende o led verde  
  
  //PROCESSO POR GRAVIDADE
   digitalWrite(rele1_CH2, HIGH); //liga colibri estufa
   lcd.setCursor(0,3);
   lcd.print("S1N: ");
   lcd.print("Estufa       ");
   delay(5000);
   digitalWrite(rele1_CH3, HIGH); //liga gotejo estufa
   delay(360000);
   digitalWrite(rele1_CH2, LOW);  //desliga colibri estufa
   delay(5000);
   digitalWrite(rele1_CH3, LOW);  //desliga gotejo estufa
}


void DadosmoduloRTC() {

  //o modulo de gravação trabalha com um digito para valores menores que 10, necessario
  //criacao de variaveis para inseris o numero zero nesses valores
  String ajustaSegundo;
  String ajustaMinuto;
  String ajustaHora;
  String ajustaDiaDoMes;
  String ajustaMes;
  
  Wire.beginTransmission(enderecoI2C); //Abrindo o modo I2C no modo de gravação.
  Wire.write((byte)0x00); //Redefinindo o ponteiro para o primeiro registro (0x00).
  Wire.endTransmission(); //finalizando o modo de gravação.
  Wire.requestFrom(enderecoI2C, 7);    //Abrindo o modo I2C no modo de leitura.

  //Para ler e posteriormente imprimir os dados lidos do módulo é necessário uma 
  //conversão de Binário para Decimal.
  segundo = bcdToDec(Wire.read() & 0x7f); //Alguns dados precisam de máscaras antes 
                                          //da conversão porque certos bits são 
                                          //bits de controle. 
  minuto = bcdToDec(Wire.read());         //convertendo os minutos. 
  hora = bcdToDec(Wire.read() & 0x3f);    //Alguns dados precisam de máscaras antes 
                                          //da conversão porque certos bits são 
                                          //bits de controle. Essa máscara define o
                                          //relógio para trabalhar no modo de 24h.
  diaDaSemana = bcdToDec(Wire.read());    //dia da semana, onde domingo começa com "0".
  diaDoMes = bcdToDec(Wire.read());       //convertendo o dia do mês.
  mes = bcdToDec(Wire.read());            //convertendo o mês.
  ano = bcdToDec(Wire.read());            //convertendo o ano.
 
  //Imprimindo os dois dígitos das horas separados por dois pontos.
  Serial.print("Agora sao: ");
  //chmando a função ajustaZero para o caso de dados gravado no módulo com apenas um dígito.
  ajustaHora += ajustaZero(hora); 
  Serial.print(ajustaHora);
  Serial.print(":");
  lcd.setCursor(0,0);
  lcd.print(ajustaHora);
  lcd.print(":"); 
  //chmando a função ajustaZero para o caso de dados gravado no módulo com apenas um dígito.
  ajustaMinuto += ajustaZero(minuto);
  Serial.print(ajustaMinuto);
  Serial.print(":");
  lcd.setCursor(3,0);
  lcd.print(ajustaMinuto);
  lcd.print(":"); 
  //chmando a função ajustaZero para o caso de dados gravado no módulo com apenas um dígito.
  ajustaSegundo += ajustaZero(segundo);
  Serial.println(ajustaSegundo);
  lcd.setCursor(6,0);
  lcd.print(ajustaSegundo);
  
  Serial.print("Dia da semana: ");

  switch(diaDaSemana)
  {
    case 0:Serial.println("Domingo"); break; //se a variável diaDaSemana for zero imprima na tela "Domingo"  
    case 1:Serial.println("Segunda-feira"); break; //idem ao anterior
    case 2:Serial.println("Terca-feira"); break;   //idem
    case 3:Serial.println("Quarta-feira"); break;  //idem
    case 4:Serial.println("Quinta-feira"); break;  //idem
    case 5:Serial.println("Sexta-feira"); break;   //idem
    case 6:Serial.println("sábado"); break;        //idem
  }
  
  //Imprimindo os dois dígitos das datas separadas por uma barra.
  Serial.print("Data: ");
  //chmando a função ajustaZero para o caso de dados gravado no módulo com apenas um dígito.
  ajustaDiaDoMes += ajustaZero(diaDoMes);
  Serial.print(ajustaDiaDoMes);
  Serial.print("/");
  //chmando a função ajustaZero para o caso de dados gravado no módulo com apenas um dígito.
  ajustaMes += ajustaZero(mes);
  Serial.print(ajustaMes);
  Serial.print("/");
  Serial.println(ano);
 
  Serial.println(); //salta uma linha.
}

//converte dados de decimal para binário, para gravação no modulo.
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}
 

//converte dados de binário para decimal, para impressao no monitor serial.
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}


//funcao que insere o numero zero nos valores abaixo de 10.
String ajustaZero(byte dado)
{
  String dadoAjustado;
  if (dado < 10) 
  {
    dadoAjustado += "0";  //concatena o dígito "0" ao valor da variável.
  }
  dadoAjustado += dado;   //concatena o dígito "0" ao valor do dado.
  
  return dadoAjustado;    //retorna o valor do dado ajustado.
}

 

Link para o comentário
Compartilhar em outros sites

Do jeito que a estrutura está, realmente o programa faz apenas uma coisa por vez.

 

Não estou familiarizado com a linguagem do Arduíno o suficiente para escrever fonte usando-a. Mas uma sugestão de lógica, apenas:

 

Que tal, em lugar dos delays, colocar contadores que o programa vá alterando a cada loop?

Um contador para cada relé e sua correspondente mensagem no display...

 

Explico: um delay é um contador automático. Você põe lá:

 

delay(5000);

 

e o Arduino não vai fazer mais nada além de contar de 0 a 5000. O programa vai ficar parado ali, só contando.

 

Agora imagine um loop principal que teria o único delay do programa todo:

 

void loop();
delay(1000);

if relé_canavial == 0 e condições adequadas do canavial (umidade, haver água no reservatório, estar no dia e na hora adequadas etc.)
   aciona o relé do canavial
   relé_canavial++

if relé_canavial == 3
   relé_canavial = 0

if relé_abacaxizal == 0 e condições adequadas do abacaxizal
   aciona o relé do canavial
   relé_abacaxizal++

if relé_abacaxizal == 5
   relé_abacaxizal = 0

 

Nesse caso, o relé_canavial ficará ligado por 3 segundos a cada vez que as condições para o canavial forem verdadeiras. E continuará ligado até que passem esses 3 segundos.

 

Já o relé_abacaxizal, esse ficará ligado por 5 segundos. E só será ligado de novo quando as condições para o abacaxizal forem adequadas novamente.

 

E quando essas condições dispararem esse relé, ele permanecerá ligado por 5 ciclos do programa, ou seja, por 5 segundos.

 

Ficam independentes, assim, as contagens de tempo de ambos, do canavial e do abacaxizal.

 

Faltou a parte do botões, que essa, por desconhecimento meu de Arduino, não consegui entender. Mas quem sabe esse pouquinho aí já ajuda, de alguma forma...

 

 

Ops! Faltou

 

desliga relé_canavial

 

depois de

 

if relé_canavial ==  3

 

 

 

e um

 

desliga relé_abacaxizal

 

depois de

 

if relé_abacaxizal == 5

Caramba! O "código" acima tem alguns erros.

Por favor, despreze-o e considere esse aqui

 

void loop();
delay(1000);

if relé_canavial == 0 e condições adequadas do canavial
                       (umidade, haver água no reservatório,
                        estar no dia e na hora adequadas etc.)
   aciona o relé do canavial
else
   relé_canavial++


if relé_canavial == 3
   desliga relé_canavial
   relé_canavial = 0

if relé_abacaxizal == 0 e condições adequadas do abacaxizal
   aciona o relé do abacaxizal
else
   relé_abacaxizal++

if relé_abacaxizal == 5
   desliga relé_abacaxizal
   relé_abacaxizal = 0

 

Link para o comentário
Compartilhar em outros sites

Certa vez eu tinha um problema parecido e resolvi assim:

Encontre um tempo, cujo valor é o MDC (mínimo divisor comum), ou o MDC / k, onde k é um inteiro.

Faça um único timer com interrupção em loop, com o valor anterior.

Dentro da interrupção inclua todas as suas variáveis com os respectivos valores limites.

Ex:

Variável X tem o limite Y, que é igual a N x MDC / k (ou N x MDC, o que você escolheu acima). 

A cada interrupção, incremente X e inclua um "IF" (se X >= Y, então a bandeira (flag) X1 = 1, X = 0, else X1 = 0). Isso conta o tempo da variável X. Depois de N interrupções a variável X alcança o valor Y.

Faça isso para todas as variáveis...

Assim, basta um timer para todas as variáveis.

No programa principal, faça um loop monitorando todas as bandeiras. Caso uma delas esteja em '1'. desvie para a sub rotina que trata da sua variável. Lembre-se, que a primeira coisa a fazer dentro da rotina é desligar a bandeira X1.

Claro que tem algumas implicações, tal como a rotinas tem que durar menos tempo do que o tempo entre duas interrupções consecutivas, mas geralmente cada rotina manda ligar ou desligar algo, portanto o tempo delas é mínimo.

MOR_AL

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Boa tarde pessoal.

 

Primeiro obrigado a todos pelo apoio.

Pelo que entendi tanto, tanto a dica do rmlazzari58 quanto a do MOR segue um mesmo racional: criar uma variável específica para armazenar o valor de contagem de cada processo, e montar uma rotina de leitura dessa variável. De acordo com o valor que a variável apresentar, executa uma função específica.

Seria isso?

Se sim, pergunto (isso porque também não sou tão especialista em Arduino): a função (Millis) não executa esse procedimento? 

Se for isso, não a usei porque em pesquisas que fiz me parece que essa função tem um limitador e gera problema após alguns dias.

Link para o comentário
Compartilhar em outros sites

1 hora atrás, Alexandre Mariz Paiva disse:

Se sim, pergunto (isso porque também não sou tão especialista em Arduino): a função (Millis) não executa esse procedimento? 

Se for isso, não a usei porque em pesquisas que fiz me parece que essa função tem um limitador e gera problema após alguns dias.

Isto está certo, porém, você tem um RTC, não precisa usar o timer do MC, pode usar a mesma lógica do millis mas usando o RTC

Link para o comentário
Compartilhar em outros sites

Veja o que você acha, Alexandre.

 

A rotina abaixo considera que

 

1 - só há um sensor de umidade.

2 - o horário para irrigação está definido em dia da semana, hora, minuto e segundo.

3 - no horário adequado, o abacaxizeiro será regado por 3 segundos, ou seja, o relé dos abacaxis ficará ligado durante 3 loops do programa e, depois desses 3 segundo, esse relé desliga e a irrigação dos abacaxis cessa.

4 - no horário adequado à cana, essa será irrigada por 10 segundos (ou 10 loops). Depois disso, para a irrigação.

5 - c_abacaxi, por exemplo, é o contador de quantas vezes o programa passa pelo trecho que trata da horta de abacaxis. Como o programa executa um ciclo a cada segundo (delay(1000)), esse contador será acrescido em 1 a cada segundo. Assim, depois que o relé do abacaxi for ligado, só será desligado depois de 3 ciclos (ou 3 segundos).  Ou seja, quando esse contador passar de 3, chegando a 4, o relé do abacaxi desliga. O mesmo para o contador da cana, o c_cana. O relé da cana só vais desligar quando o c_cana for 11, isto é, depois de 10 ciclos do programa todo.

 

c_abacaxi = 0
c_cana = 0
void loop()
   delay(1000)
   if solo está seco
      if tem água no reservatório

         // Trecho do abacaxi *********************
         if relé do abacaxi está desligado
            if data e hora de irrigar o abacaxi
               liga relé do abacaxi
               c_abacaxi++
         else // relé do abacaxi já está ligado
            c_abacaxi++
            if c_abacaxi == 4
               desliga relé do abacaxi
               c_abacaxi = 0

         // Trecho da cana *************************
         if relé da cana está desligado
            if data e hora de irrigar a cana
               liga relé da cana
               c_cana++
         else // relé da cana está ligado
            c_cana++
            if c_cana ==  11
               desliga relé da cana
               c_cana = 0

      else // não tem água no reservatório
         desliga todos os relés
         c_abacaxi = 0
         c_cana = 0
         mensagem "Não tem água no reservatório"
   else // o solo não está seco
      desliga todos os relés
      c_abacaxi = 0
      c_cana = 0
      mensagem "O solo não está seco"

 

Dá para acrescentar datas e horários para a rega de cada uma dessas plantas. Digamos, por exemplo, que o abacaxi precise ser regado em dois horários, noite e dia. O trecho do abacaxi ficaria assim:

 

         // Trecho do abacaxi *********************
         if relé do abacaxi está desligado
            if data e hora de irrigar o abacaxi || data e hora de irrigar o abacaxi
               liga relé do abacaxi
               c_abacaxi++
         else // relé do abacaxi já está ligado
            c_abacaxi++
            if c_abacaxi == 4
               desliga relé do abacaxi
               c_abacaxi = 0

 

Da mesma forma, dá para acrescentar outras hortas. Por exemplo, a horta de mandioca ficaria assim

 

         // Trecho da mandioca *********************
         if relé da mandioca está desligado
            if data e hora de irrigar a mandioca
               liga relé da mandioca
               c_mandioca++
         else // relé da mandioca já está ligado
            c_mandioca++
            if c_mandioca == 4
               desliga relé do mandioca
               c_mandioca = 0

 

Claro que no caso da mandioca - ou de outras hortas - lá no comecinho do programa tinha que ter feito

 

c_mandioca = 0

 

e caso o solo não esteja seco ou não haja água no reservatório, nos "elses" dos seus "ifs" também teria que zerar o contador da mandioca.

 

A ideia é um programa em loop que, acada volta, verifica

 

- o solo está seco? (Ou choveu... sei lá, não está seco, está úmido.

- tem água no reservatório?

- chegou o dia e a hora de regar cada uma das plantas?

 

de tal forma que, se o solo estiver seco, houver água no reservatório e chegou o momento de regar determinada planta, é isso que o programa fará.

 

Com certeza dá para melhorar. Por exemplo, não precisaria ficar mandando ligar relé que já está ligado, nem desligar o que já está desligado.

 

Mas a ideia é que o programa fique dando voltas eternamente. E a cada volta faça as verificações sobre "secura" da terra, abastecimento do reservatório, momento de ligar e de desligar a irrigação de cada planta. Isso a cada volta.

 

O RTC, nesse caso, é apenas para fornecer a data e a hora atual. A cada volta que o programa dá, tem que carregar uma variável com dados como dia da semana e hora a partir do RTC. Eu esqueci de colocar essa variável porque me ative apenas à estrutura mas tenho certeza de que você saberá colocá-la no lugar certo, inclusive fazendo as conversões adequadas, talvez atribuindo números aos dias da semana... essas operações de conversão, substring etc. eu vi que no programa que você trouxe já tem.

 

E não seria necessário o uso da Milis() porque o programa seria executado, bem, rs... "para sempre".

Link para o comentário
Compartilhar em outros sites

Eu faria uma rotina de interrupção por exemplo a cada segundo, leria o RTC  e incrementaria a minha base de tempo.

O programa principal usaria essa base de tempo e acionaria / desacionaria cada saída baseado nos tempos de cada uma.

E claro, no loop principal trataria o display.

O sistema nunca ficaria preso ....

 

Paulo

Link para o comentário
Compartilhar em outros sites

22 horas atrás, Alexandre Mariz Paiva disse:

criar uma variável específica para armazenar o valor de contagem de cada processo, e montar uma rotina de leitura dessa variável. De acordo com o valor que a variável apresentar, executa uma função específica.

Seria isso?

Sim, mas o pulo do gato é outra coisa.

Releia minha postagem, inclusive o exemplo.

Caso você tenha alguma dúvida, pergunte.

MOR_AL

Link para o comentário
Compartilhar em outros sites

Pessoal, boa tarde.

Ainda não consegui solucionar o problema (e acredito ser também porque não sou tão experiente nessa área).

Na prática, não consegui implementar as soluções, considerando que o horário para iniciar a irrigação de todos os itens é o mesmo (ou 6 da manhã ou 18hs), o que muda são os momentos em que cada um inicia.

Percebi, então, que da forma que a programação está hoje, o que está acontecendo é que como o sistema congela quando inicia, ele não volta a ler o horário, por isso não desliga quando o minuto muda e fica até o final (o que preciso que aconteça), porém isso tem me gerado outros problemas.

MOR, confesso que não consegui entender como montar da maneira como me sugeriu (porque sou iniciante).

rmlazzari58, tentei sua solução mas como preciso que cada relé inicie após o término do outro, não consegui implementar pois ainda que peça para que o segundo processo leia o valor da variável do primeiro, o loop retorna ele ao valor original e a partir dai somente quando por acaso ele lê e o estado está mudado é que o segundo processo inicia.

 

Link para o comentário
Compartilhar em outros sites

De fato eu tinha entendido que você queria que os processos de rega acontecessem simultaneamente e independentemente uns dos outros. Ou seja, tinha entendido que você queria que, digamos, a execução da rega "abacaxi" não congelasse o sistema a ponto de impedir que a rega "canavial" fosse feita ao mesmo tempo.

 

Bem... sabendo agora que uma rega tem que esperar a outra acabar (um relé por vez), não vejo porque os delays de cada rega não podem ficar dentro das subrotinas dessas próprias regas. Pelo seu programa e pelo fluxograma, creio que o melhor seria a criação das seguintes subrotinas, já com os delays dentro delas:

 

Horta

Estufa

Pomar

Cana

Mandioca

Noite

Abacaxi

 

A lógica, se entendi direito, ficaria assim:

(Desculpe o rabisco mas faz uns 20 anos que esqueci onde coloquei minha régua de fluxograma Trident.)

 

1610876429_Documentodigitalizado.thumb.jpg.1c6dadc54d3354ab66c2fc7ff0034184.jpg

 

Observações:

 

- A rotina de acionamento manual das regas por botão poderia ficar junto com o delay(2000). O problema que pode ocorrer é você comandar uma rega que leve 2 minutos quando for 17:59h.

(Tô brincando, rs... pelo jeito você usa a hora cheia, é isso? Ou é 6h ou é 18h ou não interessa...)

 

- Precisa colocar uma flag aí para evitar de fazer mais de uma rega no mesmo dia. Como esqueci de colocar essas flags, do jeito que tá várias regas acontecerão entre 18h e 18:59. Mas essas são bico: Já regou hoje? Então não rega mais. Algo assim... Acho que entre "Reservatório OK?" e "Solo molhado?"... será?

 

- Pode acontecer de começar a chover depois do início de alguma rega. Nesse caso o sensor de umidade só vai apontar que o solo está molhado depois de terminar a rega. Acho que para isso é que inventaram a expressão "chover no molhado", né?

 

- Também pode acontecer do reservatório secar durante alguma rega. Aí talvez seja o caso de você ajustar o medidor do reservatório para que ele aponte como vazio quando ainda tiver alguma água ali.

 

- Não precisaria da condicional "TER ou SAB ou DOM?" porque se não for segunda nem sexta nem quarta nem quinta, ou é terça ou é sábado ou domingo. Então se o reservatório estiver ok, se o solo não estiver molhado, se for 18h e não for segunda nem sexta nem quarta nem quinta, é para executar a rega Noite, sempre, é isso?

 

E nada disso dispensa o teste das solenóides que o @MOR falou.

 

Bem.... vê se serve, aí. De toda forma, vejo um trabalhão prá você que é destrinchar, estudar, verificar essa lógica e pior, "traduzir" fluxograma em código.

 

Qq coisa, 'tamos aí.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

@MOR e @rmlazzari58, só tenho a agradecer vocês pelo empenho em me ajudar.

Sobre as regras, acho que o que você está me passando @rmlazzari58 irá resolver, mas procurei validar primeiro se o problema é físico, como sugerido pelo @MOR.

Eu não instalei os LEDs, mas desliguei todos os cabos de acionamento das solenóides (110v) dos relés, e o que verifiquei é que sem as cargas não há interferências no display lcd, nem mesmo os problemas de travamento (que como reparei sempre aconteciam - quando aconteciam -  no mesmo relé) que faziam com que um relé não desligasse e assim esvaziasse o reservatório.

Minha pergunta agora é: o teste é válido somente com o acionamento dos relés sem carga, ou é necessário instalar os LEDs para testar?

E, se for válido da maneira como fiz, isso comprovaria a interferência eletromagnética?

E ainda, se realmente essa interferência existe, tem alguma maneira de bloquea-la/filtra-la?

  • Curtir 1
  • Triste 1
Link para o comentário
Compartilhar em outros sites

7 horas atrás, Alexandre Mariz Paiva disse:

@MOR e @rmlazzari58, só tenho a agradecer vocês pelo empenho em me ajudar.

 

Na verdade, além de escrever programa ser um prazer, @Alexandre Mariz Paiva, está me ajudando a conhecer a linguagem do Arduíno.

 

E se você me permite algumas observações, vou colar aqui um trecho do seu fonte sem as tags < e > que é para poder tratar esse trecho com bolds, highligths e cores.

 

1 - Nomenclatura das variáveis. É boa prática da escrita de fontes aproximar o máximo possível o texto a ser compilado, da linguagem natural da gente, a que a gente fala normalmente. Assim, se em lugar de chamar o relé no pino 22 de "rele1_CH1", o programa ficaria mais facilmente legível se você chamasse esse relé de "horta". Da mesma forma poderia chamar o relé no pino 30 de "bomba", em vez do mais difícil ainda "rele2_CH1". Tudo isso lá em cima, na seção de definições.

 

Olha como ficaria mais fácil até para dar manutenção no programa:

 

Lá em cima, em vez de

 

//declara as variaveis de execucao dos pinos que acionarao os reles.

int rele1_CH1 = 22;

int rele2_CH1 = 30;

 

ficaria assim:

 

//declara as variaveis de execucao dos pinos que acionarao os reles.

int horta = 22;

int bomba = 30;

 

Um pouco abaixo...

 

//define os pinos dos relés como "saída"

pinMode(horta, OUTPUT);

pinMode(bomba, OUTPUT);

 

E finalmente no loop principal...

 

digitalWrite(horta, HIGH); //liga horta debaixo

lcd.setCursor(0,3);

lcd.print("S1N: ");

lcd.print("Hortas ");

delay(5000);

digitalWrite(bomba, HIGH); //liga bomba e horta externa

delay(480000);

digitalWrite(horta, LOW); //desliga horta debaixo

delay(5000);

digitalWrite(bomba, LOW); //desliga bomba e horta externa

delay(5000);

 

Isso te pouparia de uma tradução. Você leria "horta" diretamente em vez de ler "rele1_CH1" e traduzir isso para "horta".

 

 

2 - Ordenamento das instruções. Também pensando na facilidade de entendimento do fonte por pessoas, já que máquina não entende nada exceto zeros e uns (e olhe lá, hein? rs...), quem sabe se você escrevesse assim?

 

lcd.setCursor(0,3);

lcd.print("S1N: ");

lcd.print("Hortas ");

 

digitalWrite(horta, HIGH); //liga horta debaixo

delay(5000);

digitalWrite(bomba, HIGH); //liga bomba e horta externa

delay(480000);

digitalWrite(horta, LOW); //desliga horta debaixo

delay(5000);

digitalWrite(bomba, LOW); //desliga bomba e horta externa

delay(5000);

 

Ou seja, primeiro você trataria o display para, em seguida, tratar dos relés.

 

Tomei esse trecho do seu fonte por uma curiosidade:

 

Primeiro você manda a solenóide da horta abrir sua torneirinha. Em seguida aciona a bomba que faz a água jorrar por essa torneirinha e deixa jorrando água por 8 minutos.  Em seguida, com a bomba ainda ligada, você manda essa solenóide fechar essa torneira. E espera 5 segundos para desligar a bomba. Durante esses 5 segundos tanto a bomba quanto a torneirinhas não serão estressadas, não serão obrigadas a realizar um trabalho que poderia ser poupado se, antes de fechar a torneira, você desligasse a bomba? Ou, se for necessário, talvez até desligar a bomba, esperar esses 5 segundos para água toda escorrer e só então mandar a solenóide fechar a torneira?

 

 

E como foi a primeira questão que você trouxe

Em 17/11/2021 às 09:35, Alexandre Mariz Paiva disse:

O problema é que quando o sistema inicia a irrigação ele "congela" todos os outros processos, o que imagino ser por conta dos delays entre cada acionamento das solenóides.

 

pergunto: o comando dado à solenóide tanto para abrir quanto para fechar não é executado imediatamente? A solenóide leva um tempo, depois do comando, para abrir e outro para fechar ou ela o faz de repente?

 

Ou, de outra forma, para que os delays que marquei em vermelho abaixo?

 

digitalWrite(rele1_CH1, HIGH); //liga horta debaixo

lcd.setCursor(0,3);

lcd.print("S1: ");

lcd.print("Hortas ");

delay(5000);

digitalWrite(rele2_CH1, HIGH); //liga bomba e horta externa

delay(240000);

digitalWrite(rele1_CH1, LOW); //desliga horta debaixo

delay(5000);

digitalWrite(rele2_CH1, LOW); //desliga bomba e horta externa

delay(5000);

 

E lembre-se: código fonte tem que ter lógica cartesiana, orientada para processamento, mas foi inventado para ser entendido por pessoas. Se não, a gente escrevia tudo em assembler (linguagem de baixo nível para programadores de alto nível, rs...) ou em linguagem de máquina direto (zeros e uns). Já pensou o trabalhão para escrever assim, e o pior, para entender depois? E prá falar com a Alexa, já pensou? rs...

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

18 horas atrás, Alexandre Mariz Paiva disse:

Minha pergunta agora é: o teste é válido somente com o acionamento dos relés sem carga, ou é necessário instalar os LEDs para testar?

Não é necessário.

A inclusão dos leds no lugar das solenoides tem o objetivo de você ter uma visualização do estado lógico da alguma porta na saída do microcontrolador. 

 

18 horas atrás, Alexandre Mariz Paiva disse:

E, se for válido da maneira como fiz, isso comprovaria a interferência eletromagnética?

Sim.

 

18 horas atrás, Alexandre Mariz Paiva disse:

E ainda, se realmente essa interferência existe, tem alguma maneira de bloquea-la/filtra-la?

Comece respondendo às questões do @Thiago Miotto na postagem #18.

MOR_AL

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Bom dia pessoal.

Vamos lá:

@Thiago Miotto o sistema todo está sendo alimentado por uma única fonte, já que estou usando um módulo relé 12v e um de 5v. Mas o principal motivo mesmo é que não sabia que isso poderia ser um problema e ajudar a causar interferência eletromagnética.

Vou fazer a separação para testar se irá resolver ou começar a resolver. 

Aviso aqui depois dos testes, mas já te agradeço antecipadamente.

 

@MOR obrigado pelas respostas, e como respondi acima para o @Thiago Miotto, vou fazer a separação da alimentação com fontes individuais e testar.

 

@rmlazzari58

13 horas atrás, rmlazzari58 disse:

E se você me permite algumas observações, vou colar aqui um trecho do seu fonte sem as tags < e > que é para poder tratar esse trecho com bolds, highligths e cores.

Com certeza permito, pois vocês aqui estão me ajudando muito e nenhuma ajuda é demais.

Realmente deixar o código mais claro torna mais fácil a leitura e eventuais manutenções. Vou fazer ajustes com base nos seus exemplos para melhorar esse código, logo que tiver com o problema da interferência solucionado.

 

13 horas atrás, rmlazzari58 disse:

Primeiro você manda a solenóide da horta abrir sua torneirinha. Em seguida aciona a bomba que faz a água jorrar por essa torneirinha e deixa jorrando água por 8 minutos.  Em seguida, com a bomba ainda ligada, você manda essa solenóide fechar essa torneira. E espera 5 segundos para desligar a bomba. Durante esses 5 segundos tanto a bomba quanto a torneirinhas não serão estressadas, não serão obrigadas a realizar um trabalho que poderia ser poupado se, antes de fechar a torneira, você desligasse a bomba? Ou, se for necessário, talvez até desligar a bomba, esperar esses 5 segundos para água toda escorrer e só então mandar a solenóide fechar a torneira?

Nesse caso, tenho duas hortas sendo irrigadas pela bomba: uma que está ligada diretamente com a abertura da bomba, e outra que é liberada por solenóide.

Quando desligo a solenoide da horta de baixo, a bomba fica ligada irrigando a horta principal. Aí quando desligo a bomba ela encerra toda a irrigação. Nesse caso não há problema da bomba estar girando com os "registros fechados".

Eu deixei escrito na observação (digitalWrite(bomba, LOW); //desliga bomba e horta externa), mas como você falou, talvez a escrita não esteja favorecendo o entendimento.

 

13 horas atrás, rmlazzari58 disse:

pergunto: o comando dado à solenóide tanto para abrir quanto para fechar não é executado imediatamente? A solenóide leva um tempo, depois do comando, para abrir e outro para fechar ou ela o faz de repente?

 

Eu programei para que fossem acionados com intervalos de 5s, ou seja, aciona um relé e cinco segundos depois aciona o outro. A mesma lógica para o desligamento, ou seja, após um ser desligado aguarda 5 segundos para desligar o outro.

Mas por conta das observações que você tem feito estou verificando que meu código tem comandos desnecessários para o funcionamento do processo.

Estou revisando isso também.

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Passando rapidamente percebi mais uma coisa que você provavelmente vai precisar fazer também:


Seu reservatório não precisa ser testado p/ ver se esvaziou enquanto o bomba fica ligado?

Você pode solucionar isso de 2 formas:

1-Via hardware, c/ uma regulagem de boia alta. Ou seja, o sensor de nível aponta s/ água no meio do reservatório, assim em testes você vê quanta água faz e regula para o sistema só funcionar se tiver água no depósito.

2-Via software:

 

No lugar disso:

digitalWrite(bomba, HIGH); //liga bomba e horta externa

delay(480000);

digitalWrite(horta, LOW); //desliga horta debaixo



por algo assim:
 

digitalWrite(bomba, HIGH); //liga bomba e horta externa

for (int i = 0; i <= 240; i++) {

      delay(2000);

     [testa se o reservatorio está vazio, caso estiver desligue a bomba]

}

digitalWrite(horta, LOW); //desliga horta debaixo

 



 

Link para o comentário
Compartilhar em outros sites

Boa tarde pessoal.

@Thiago Miotto ok, isso realmente vai fazer a diferença, porque é importante que não só para iniciar mas também após acionamento a bomba pare de funcionar se o reservatório esvaziar.

Minha dúvida agora é: a função (for) vai continuar executando mesmo quando os delays estiverem ativos? Como mencionei, atualmente logo após o programa acatar como verdadeiras as validações, o sistema trava nos delays até terminar.

Link para o comentário
Compartilhar em outros sites

Boa Noite

Com o delay(480000); - O software vai ficar 8 minutos (480 mil milisegundos ou 480 segundos) s/ fazer teste nenhum.

Com o for e o delay(2000) como te expliquei, ele vai testar a 240 vezes (de 2 em 2 segundos) se falta água.

você tb pode fazer menos testes e aumentar um pouco o delay se o desempenho ficar muito ruim, mais creio que não será problema, pois o teste se o reservatório está vazio é praticamente instantâneo.

Sabe o que significa as linhas do for que coloquei?

 

Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...