Projeto Incubadora de CO2

Saudações pessoal. Estou desenvolvendo aos poucos um software para controlar uma incubadora.

Minha ideia é setar uma temperatura (menu 2), e na tela inicial (menu 1), mostrar a temperatura e o CO2 (que não esta sendo trabalhado no momento), e futuramente novas funções serão adicionadas como Overtemp, Temperatura da porta, etc.

Consigo ver a variação de temperatura, porém o rele nao desliga quando atinge a temperatura de setpoint que programei.

Programa todo abaixo.

Utilizado um shield LCD com teclado + modulo rele serial (4 reles) + sensor DS18B20

#include <LiquidCrystal.h>                              //Biblioteca para o display LCD
#include <DallasTemperature.h>                          //Biblioteca Dallas
#include <OneWire.h>                                     //protocolo de Barramento da Dallas - Pode adicionar varios sensores a um mesmo pino
#include <SerialRelay.h>                                //Biblioteca Modulo Serial de Reles
#include <EEPROM.h>

// --- Mapeamento de Hardware ---

OneWire pino(11);                                       //Define o pino que receberá a informação
DallasTemperature barramento(&pino);                    //Objeto que define o barramento dos sensores
DeviceAddress sensor1;                                //Define Sensor 1

// --- Protótipo das Funções Auxiliares ---
void keyboardRead();                                       //Função para modificar o menu atual
void dispMenu();                                        //Função para mostrar o menu atual
void INICIO();                                   //Funçao do menu1, temperatura e co2
void relay1();                                   //função do rele 1
void TEMP();                                    //função do menu 2, setpoint de tempetura.



// --- Variáveis Globais ---
char menu = 0x01;                                       //Variável para selecionar o menu

int adc_value = 0x00;                       //armazena o valor digital do conversor AD

boolean RIGHT  = 0x00, butt01 = 0x00,       //botão e flag Right
        UP     = 0x00, butt02 = 0x00,       //botão e flag Up
        DOWN   = 0x00, butt03 = 0x00,       //botão e flag Down
        LEFT   = 0x00, butt04 = 0x00,       //botão e flag Left
        SELECT = 0x00, butt05 = 0x00;        //botão e flag Select

float temp1,T_SET=25;

const int NUMERO_MODULOS = 1; //determina a quantidade de modulos conectados (maximo de 10)
SerialRelay reles (13, 12, NUMERO_MODULOS); //definicao da pinagem de data e clock do modulo, e da quantidade de modulos

// --- Hardware do LCD ---
LiquidCrystal disp(8,  //RS no digital 8
                   9,  //EN no digital 9
                   4,  //D4 no digital 4
                   5,  //D5 no digital 5
                   6,  //D6 no digital 6
                   7); //D7 no digital 7

// --- Configurações Iniciais ---
void setup()
{
  
  disp.begin(16,2);                                      //Inicializa LCD 16 x 2
  barramento.begin();
  barramento.getAddress(sensor1,0);
  disp.setCursor(3,0);
  disp.print("TECHNOLAB");//mensagem na primeira linha
  disp.setCursor(3,1);
  disp.print("SOLUCOES");//mensagem segunda linha
  delay (5000);
  disp.clear();
 
} //end setup
// --- Loop Infinito ---
void loop()
{
   keyboardRead(); 
   dispMenu();
   relay1();
   
       if(SELECT == 0X01)                   //tecla SELECT pressionada?
    {                                       //sim
      SELECT =0x00;                          //limpa flag da tecla
    }//end if select
      if(RIGHT == 0x01)                              //tecla right pressionada?
    {                                              //sim...
      RIGHT = 0x00;                                //limpa flag da tecla
      delay(500);
      disp.clear();                                 //Posiciona cursor na coluna 1, linha 2
      menu++;                                     //Imprime mensagem
      if(menu > 0x02) menu = 0x01; 
    } //end if right

    if(UP == 0x01)                                 //tecla up pressionada?
    {                                              //sim...
      UP = 0x00;                                   //limpa flag da tecla
      delay (500);
        T_SET++;
 
       EEPROM[1] = T_SET;
        
   
    } //end if up
    
    if(DOWN == 0x01)                               //tecla down pressionada?
    {                                              //sim...
      DOWN = 0x00;                                 //limpa flag da tecla
      delay (500);
      T_SET--;
      EEPROM[1] = T_SET;
    } //end if down
    
    if(LEFT == 0x01)                               //tecla left pressionada?
    {                                              //sim...
      LEFT = 0x00;                                 //limpa flag da tecla
      delay(500);
      disp.clear();                                 //Imprime mensagem
      menu--;
      if(menu < 0x01) menu = 0x02;
    } //end IF left

}

// --- Desenvolvimento das Funções Auxiliares ---
void keyboardRead()                                       //Modifica o menu atual
{
     adc_value = analogRead(A0);                       //Variável para leitura recebe valor AD de A0

     // --- Testa se os botões foram pressionados ---
     // Se foi pressionado, seta a respectiva flag
     if      (adc_value <  50)                    butt01 = 0x01;
     else if (adc_value > 103 && adc_value < 200) butt02 = 0x01;
     else if (adc_value > 250 && adc_value < 380) butt03 = 0x01;
     else if (adc_value > 450 && adc_value < 550) butt04 = 0x01;
     else if (adc_value > 600 && adc_value <780) butt05 = 0x01;
     
    

     // --- Testa se os botões foram liberados ---
     //
     if (adc_value > 50 && butt01)             //Botão right solto e flag butt01 setada?
     {                                         //Sim...
         butt01 = 0x00;                        //Limpa flag butt01
         RIGHT  = 0x01;                        //Seta flag right
         
     } //end right
     if (adc_value > 200 && butt02)            //Botão up solto e flag butt02 setada?
     {                                         //Sim...
         butt02 = 0x00;                        //Limpa flag butt02
         UP     = 0x01;                        //Seta flag up
      
     } //end up
     if (adc_value > 380 && butt03)            //Botão down solto e flag butt03 setada?
     {                                         //Sim...
         butt03 = 0x00;                        //Limpa flag butt03
         DOWN   = 0x01;                        //Seta flag down
       
     } //end down
     if (adc_value > 550 && butt04)            //Botão left solto e flag butt04 setada?
     {                                         //Sim...
         butt04 = 0x00;                        //Limpa flag butt04
         LEFT   = 0x01;                        //Seta flag left
       
     } //end left
     if (adc_value > 780 && butt05)            //Botão left solto e flag butt04 setada?
     {                                         //Sim...
         butt05 = 0x00;                        //Limpa flag butt04
         SELECT   = 0x01;                        //Seta flag left
       
     } //end SELECT


} //end keyboardRead
/*---------------------------------------------------------------------------------------------*/
void dispMenu()                                         //Mostra o menu atual
{
    switch(menu)                                        //Controle da variável menu
    {
       case 0x01:                                       //Caso 1
             INICIO();                                 //Chama a tela inciail que mostra nivel de CO2 e temperatura atual
             
             break;                                     //break
       case 0x02:                                       //Caso 2
             TEMP();                                   //Chama a função de setpoint de temperatura
             break;
             
    }}
/*-----------------------------------------------------------------------------------------------------*/
void INICIO()                                        //TELA INICIAL (MENU1)
{
  barramento.requestTemperatures();// realiza leitura do sensor de temperatura
  float temp1 = barramento.getTempC(sensor1);
   delay(1000);
  disp.setCursor(0,0);
  disp.print("TEMP:");//mensagem na primeira linha
  disp.print(temp1);//valor lido no sensor de temperatura interno
  disp.write(B11011111);//SIMBOLO DE GRAUS
  disp.print("C"); //Celsius
  disp.setCursor(0,1);
  disp.print("CO2:  ");//Mensagem segunda linha
 // disp.print(valorCO2);// valor lido no sensor de CO2
  disp.write(B00100101);//SIMBOLO DE %

} //end telaInicial
/*---------------------------------------------------------------------------------------------*/
void TEMP()                                        //SETPOINT TEMPERATURA(menu2)
{
  disp.setCursor(2,0);
  disp.print("TEMPERATURA");//mensagem na primeira linha
  disp.setCursor(5,1);
  disp.print(T_SET);//Mostra a temperatura media na segunda linha
  disp.write(B11011111);//SIMBOLO DE GRAUS
  disp.print("C"); //Celsius
  if(EEPROM[0] !=25){
    EEPROM[0]= 25;
    EEPROM[1]= T_SET;
  }
  else {
    T_SET = EEPROM[1];
  }
}

void relay1() {
    //condicao de acionamento
    if (T_SET > temp1){ //se a temperatura do sensor 1 for menor que a temperatura de setpoint
      reles.SetRelay(1, SERIAL_RELAY_ON, 1); //liga o rele 1
    }
      while (T_SET <= temp1) {      //se a temperatura do sensor 1 for maior que a temperatura de setpoint
      reles.SetRelay(1, SERIAL_RELAY_OFF, 1); //desliga o rele 1
    }
  }

Olá!

Mostre o código que está feito para poder receber ajuda mais objetiva.

Abraço.

post atualizado.
grato

Olá!

Qual a razão para a utilização desse "while"?

      while (T_SET <= temp1) {
      reles.SetRelay(1, SERIAL_RELAY_OFF, 1); 
    }

Abraço.

Se colocar a função relay1 dessa forma, o relê liga e desliga?

Colocando Serial.begin(9600); no setup, quais são os valores apresentados para T_SET e temp1?

void relay1() {
      Serial.print("T_SET: ");
      Serial.println(T_SET);
      Serial.print("temp1: ");
      Serial.print(temp1);
      reles.SetRelay(1, SERIAL_RELAY_ON, 1);
      delay(5000);
      reles.SetRelay(1, SERIAL_RELAY_OFF, 1);
      delay(5000);
  }

irei verificar, caso consiga resultado satisfatório aviso por aqui.
grato pela atenção

Bom dia, Fernando.
Quando adicionei o comando de leitura do sensor de temperatura, o rele passou a atuar.
Quando utilizei sua sugestão vi que o rele não estava interpretando a condição. Foi então que resolvi colocar a função de leitura da temperatura.

Agradeço pela ideia, pois deu uma direção. Vou desenvolver mais um pouco o programa, e em caso de duvida volto aqui novamente.

void relay1() {
    barramento.requestTemperatures();// realiza leitura do sensor de temperatura
    float temp1 = barramento.getTempC(sensor1);
      //condicao de acionamento
    if (T_SET > temp1){ //se a temperatura do sensor 1 for menor que a temperatura de setpoint
      reles.SetRelay(1, SERIAL_RELAY_ON, 1); //liga o rele 1
    }
      else {      //se a temperatura do sensor 1 for maior que a temperatura de setpoint
      reles.SetRelay(1, SERIAL_RELAY_OFF, 1); //desliga o rele 1
    }
  }

Uma outra duvida: preciso que a tecla UP e DOWN atuem da mesma maneira em outros menus.
Ela só ta incrementando e decrementando no menu TEMPERATURA, precisava que elas fizessem o mesmo no menu TEMP.PORTA e menus posteriores. Alguma sugestão?

Olá!

Fico feliz que tenha ajudado.

Seu código traz algumas complicações desnecessárias.

Por exemplo,

boolean RIGHT  = 0x00

Essa variável boleana não tem necessidade de atribuir uma valor em hexadecimal.

0x00 é 0, que é o mesmo que false.
0x01 é 1, que é o mesmo que true.

Tem pouca diferença no número de caracteres, mas para quem lê seu código é muito mais fácil de entender quando se usa false e true.

O mesmo vale para a variável menu que foi declarada como char, mas poderia ser declarada como byte e ter valores atribuídos de 0 a 255.

Quanto a sua pergunta, eu costumo fazer usando um switch case como fez na função dispMenu.

void loop()
{
  if (botaoUP() == true) // verifica se o botão UP foi pressionado
  {
    switch (menu)
    {
      case 0:
        {
           // Processa o botão UP dentro do menu 0.
          break;
        }
      case 1:
        {
          break;
        }
      case default:
        {
          break;
        }
    }
  }
  else if (botaoDown() == true) // verifica se o botão Down foi pressionado
  {
    switch (menu)
    {
      case 0:
        {
          // Processa o botão DOWN dentro do menu 0.
          break;
        }
      case 1:
        {
          break;
        }
      case default:
        {
          break;
        }
    }
  }
}

A maneira como você verifica qual botão foi pressionado me parece um tanto complicada também.
Eu procuraria uma biblioteca para simplificar as coisas.

Abraço.

1 Like

Boa tarde. Essa sugestão para os botões caiu como uma luva.
Fernando, você tem algum conhecimento de controle PI ou PID?
O controle de temperatura da câmara interna precisa ser estável e preciso. Vi alguns videos sobre, mas não consegui assimilar muito bem.

Não tenho experiência, mas essa biblioteca parece fácil de usar.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.