Controle de Fluxo de Água com Arduino – Conclusão

Neste quinto e último post da série sobre o desenvolvimento do Controle de Fluxo de Água com Arduino vamos mostrar o que foi alcançado e um pouco do código fonte desenvolvido.

Vídeo demonstrativo

Um pouco sobre o código fonte

O programa de controle foi desenvolvido na IDE do Arduino utilizando algumas bibliotecas para facilitar a vida :D.

Começando pelos includes. Foram utilizadas duas bibliotecas. A TM1637Display e a RotaryEncoder.

A primeira com o propósito de facilitar a escrita dos números nos display de 7 segmentos. A segunda biblioteca é utilizada para leitura do encoder rotatorio. Ambas foram adicionadas pelo link direto do Github que está no código fonte disponibilizado.

#include <TM1637Display.h>
#include <RotaryEncoder.h>

Eu costumo utilizar em meus projetos a ideia de maquina de estados. Para este pensei em 2 estados . O estado de espera e um estado para liberar a contagem do fluxo. Para ambos criei um #define para simplificar o uso.

#define ESPERA          0
#define LIBERA_CONTA    1

Após essas definições algumas variáveis globais foram declaradas incluindo a display, que instancia a classe TM1637Display fornecida pela biblioteca do display, e a encoder, que instancia a classe RotaryEncoder fornecida pela biblioteca do encoder rotatorio. Não entrarei em detalhes sobre as outras variáveis. Qualquer dúvida pode deixar um comentário.

Na função main foi preciso incializar os modos dos pinos e algumas configurações iniciais do display e do encoder.

void setup() {  
  Serial.begin(9600);
  
  pinMode(LED, OUTPUT);
  pinMode(BZR, OUTPUT);
  pinMode(SOLENOIDE, OUTPUT);
  pinMode(ADJ, INPUT);
  pinMode(SW, INPUT);
  
  display.setBrightness(0x0f);
  display.showNumberDec(0);

  initFlowSensor();
  
  Serial.println("INICIALIZA");
  Serial.println("ESTADO -> ESPERA"); 
}

O ideia de utilizar estados é manter o código simples e fácil de alterar ou corrigir. Consequência disto é que a função loop fica bem pequena. Ele tem apenas um switch que troca qual é o estado atual do sistema e executa uma função específica para o estado.

void loop() {
  switch (currentState) {
    case ESPERA: {
      executarEspera();
      break;
    }    
    case LIBERA_CONTA: {
      executarLiberaConta();
      break;
    }        
  }    
}

A função executarEspera é mostrada a seguir. Basicamente ela se mantém executando uma outra função, a runEncoder. No entando é nesta função que é verificado se o botão foi pressionado e caso isso ocorra o fluxo é liberado mudando a variável currentState. Um comportamento que adicionei a esta função é a liberação do fluxo enquanto o valor definido no display for zero e o botão se mantiver pressionado. Futuramente vou realizar uma refatoração deste código para que esta parte seja um novo estado e a função cumpra um único propósito.

void executarEspera() {
  adj = analogRead(ADJ);
  int pressed = digitalRead(SW);
  if (!pressed) {
      while(digitalRead(SW) == 0) {
        if (currentMls == 0) {
          freeFlow = true;
          checkFlow();
          digitalWrite (SOLENOIDE, HIGH);
          display.showNumberDec(totalMilliLitres);
        }
      }
      Serial.println("ESTADO -> LIBERA_CONTA");
      digitalWrite (SOLENOIDE, LOW);
      currentState = LIBERA_CONTA;
  }
  runEncoder();
}

A função runEncoder trata da leitura do encoder e da exibição do número no display.

void runEncoder() {
  
  static int encoderPosition = 0;  
  
  encoder.tick();  
  int newPos = encoder.getPosition();
  
  if (encoderPosition != newPos) {    
    encoderPosition = newPos;
    if (encoderPosition * -1 >= 0) {
      currentMls = -1 * encoderPosition * 10;
    } else {
      encoder.setPosition(0);
    }    
    display.showNumberDec(currentMls);
  }
}

A função executarLiberarConta executa do estado LIBERA_CONTA. É nela que, após o fluxo ser liberado, o número do display fica sendo atualizado. Caso o botão seja pressionado há um cancelamento do fluxo mesmo que não tenha finalizado para o caso de o usuário passar do ponto na escolha da quantidade.


void executarLiberaConta() {
  unsigned int delta = currentMls - totalMilliLitres;
  digitalWrite (SOLENOIDE, HIGH);
  Serial.println("LIBERA SOLENOIDE");
  while (currentMls > totalMilliLitres) {
    checkFlow();

    int parcial = currentMls - totalMilliLitres;
    if (parcial < 0) {
      parcial = 0;
    }
    display.showNumberDec(parcial);

    int pressed = digitalRead(SW);
    if (!pressed) {
        while(digitalRead(SW) == 0) {}
        currentMls = 0;
    }
  } 
  
  encoder.setPosition(0);
  currentMls = 0;
  totalMilliLitres = 0;
  display.showNumberDec(0);
  
  digitalWrite (SOLENOIDE, LOW);

  if (!freeFlow) {
    tone(BZR, 300, 500);
    delay(1000);
    tone(BZR, 300, 500);
    delay(1000);
    tone(BZR, 300, 500);
    delay(1000);
  }
  
  Serial.println("ESTADO -> ESPERA");
  freeFlow = false;
  currentState = ESPERA;
}

O código fonte completo você encontra em https://github.com/ricardoteix/purific_control.

Com este post concluo a apresentação deste projeto. Espero que você tenho gostado. Deixem suas dúvidas, dicas ou sugestões de melhoria.

1 pensou em “Controle de Fluxo de Água com Arduino – Conclusão

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.