Automatic water filler, exclude LCD-display and buttons from code, use Blynk instead

Hi!

I want to have an automatic water filler in my brewery.

The setup is going to be:
Motorized ball valve connected to the kitchen tap
Water flow sensor (YF-S201) measuring the amount of water from the ball valve.
A relay-board to open, and to close the ball valve when the flow meter has registered the wanted amount of water.
A pump connected to the water line, driven by the same relay output, if needed (which I don’t believe is necessary)
An arduino MEGA.

There is this other guy who has an automatic water filler set up with a small keyboard and an LCD-screen.
My question is if this is possible to achieve with just using Blynk?

I want a slider to select the wanted amount of water, a value display to show the current amount filled and two buttons; one for starting the filling process and one for stopping/resetting (in case of wrong amount input or other errors).

My coding skills are of a beginner’s…
Can someone please atleast point me in the right direction of how to “virtualize” the code?
Do I still have to use all the cases in the loop?

The code with LCD-screen and keyboard looks like this:

/* 
  water filler
*/
#include <Keypad.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
byte Loe[8] = {B00000,B00001,B01110,B10101,B10101,B01110,B10000,B00000}; //  norwegian ø 

volatile int waterpulse = 0;
int wanted = 0;
int liter = 0;
int litergam = 1;
byte transfr =0;
int watersensor = 2;

char customKey;
const byte ROWS = 4;
const byte COLS = 4;

char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','D'},
  {'C','0','F','E'}
};
byte rowPins[ROWS] = {4,5,6,7}; //rows to keyboard
byte colPins[COLS] = {8,9,10,11}; //columns for keyboard

//Init  class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS); 

void rpm ()     //interrupt function that is called when activity on pin 2. 
{ 
  waterpulse++;  //counting pulses pin 2.
                // add one every time interruption is called.  Interruption is called for each increasing pulse on pin 2.
  if (waterpulse >= 415)  //the sensor is measured at 450 pulses pr. liter. This can be adjusted to calibrate
  {liter++;
  waterpulse = 0 ;
  } 
}

void setup()
{
  pinMode(watersensor, INPUT); //set digital pin 2 as input.
  pinMode(13, OUTPUT);  //relay output
  attachInterrupt(0,rpm, RISING);
  lcd.begin(16,2); // initialize the lcd 
  lcd.backlight();
  lcd.print("Behind Bars");  // Brewery name
  lcd.setCursor(0,1);
  lcd.print("Brewery");
  delay(4000);
  lcd.createChar(1, Loe); // definition of norwegian ø 
  lcd.clear();
  lcd.print("Torfinns"); // for commercial matter
  lcd.setCursor(0,1);
  lcd.print("watermeter");
  delay(3000);
  lcd.clear();
  lcd.print("Antall liter 00");
  lcd.setCursor(0,1);
  lcd.print("Overf");
  lcd.write(1);
  lcd.print("rt ");
  lcd.setCursor(11,1);
  lcd.print(liter);
}

void loop()
{
  customKey = customKeypad.getKey();
  switch(customKey) 
  {
  case '0' ... '9': // Typing numbers
    // lcd.setCursor(0,0);
    if (transfr ==0){   //cannot change if transfer has been initiated.
      wanted = wanted * 10 + (customKey - '0');
      if(wanted>99)
        { wanted=0;}
      lcd.clear();
      lcd.print("Antall liter");
      lcd.setCursor(13,0);
      lcd.print(wanted);
      }
    break;

  case 'A': //F1 function button RESET
    transfr = 0;
    liter = 0;
    litergam = 1;
    waterpulse =0;
    lcd.setCursor(13,0);
    lcd.print("  ");
    lcd.setCursor(11,1);
    lcd.print("  ");   
    break;

  case 'B': //Function button F2 not in use
    
    break;

  case 'F':  // Stop button, stop transferring
    transfr = 0;
        
    break;

  case 'E': //Function button F4 not in use
   
    break;

  case 'C':  // Start button, start transferring the ammount typed in
    transfr = 1;
    lcd.setCursor(11,1);
    lcd.print("  ");
    //liter =0;
    //waterpulse=0;  
    break;
  }
  
  if (litergam <= liter){  //checking if liter has increased before display is updated
    lcd.setCursor(0,1);
    lcd.print("Overf");
    lcd.write(1);      // to get norwegian ø in the display.
    lcd.print("rt ");
    lcd.setCursor(11,1);
    lcd.print(liter);
    litergam ++;
    }
   
   if (liter >= wanted){
   transfr = 0;// stop transfer. ammount achieved.
   litergam=1;
   liter=0;
   }
   
  if (transfr == 1){
    digitalWrite(13, LOW);
    lcd.setCursor(15,1);
    lcd.print("P");  // a P in the display indicates pumping.
    }  //Open valve.
  else {
    digitalWrite(13, HIGH);  //close valve.
    lcd.setCursor(15,1);
    lcd.print(" ");
    }
}

this is totally doable with blynk, in fact it is a lot like how I started. I had an lcd display, etc…when I found blynk, i ditched all that and used the blynk app. I will try and have a look at your code when i get some time, as I will be adding this same functionality to my project anyway, in the interim, see if you can make sense of some of the things I have done…

basically just put the control code into functions (example: void PumpControl() ) then call the functions with the SimpleTimer routine.

1 Like

Do you have a functioning Mega + wifi at this time? I just picked up the flow sensor you mentioned, should be here in a couple days, i can test some code when it gets here. The wifi is a bit tricky if you haven’t done it before.

I’m looking through your code now, and trying to understand :slight_smile:
I’m currently using the MEGA with com2tcp while I’m waiting for my ESP8266 :stuck_out_tongue:
I will also look into calling functions with the SimpleTimer :smiley:

1 Like

ok, started the project…very rough right now, just found some code online and started to add blynk stuff to it. maybe this will get you started. it would help if I had the flow sensor. :slight_smile: i will continue to work on it too. right now the code just displays data on lcd widget (data is 0 as there is no sensor yet) it also writes the same flow data to the value display widget (just to give you some ideas on how that works too) the slider just sets a variable in the code, and then writes back to the display widget for debuggin, just so I can see it change. Haven’t started the buttons code yet. but basically will just toggle relay on and off…lots of stuff commented out for now, don’t write to serial output with blynk, it doesn’t really like that.

also this was tested on an UNO, all my Mega are tied up at the moment.

/*
Liquid flow rate sensor -DIYhacking.com Arvind Sanjeev

Measure the liquid/water flow rate using this code. 
Connect Vcc and Gnd of sensor to arduino, and the 
signal line to arduino digital pin 2.
added blynk functionality 3/18/2016 Brian Thomas
 
 */
//add blynk stuff 
//#define BLYNK_DEBUG // Optional, this enables lots of prints
//#define BLYNK_PRINT Serial //this causes buffer overflow as it competes with the console serial out
#include <ESP8266_HardSer.h>
#include <BlynkSimpleShieldEsp8266_HardSer.h> 
#include <SimpleTimer.h>
const char* ssid = "xxx";
const char* password = "xxxx";
WidgetLED led1(31); //StartLED in blynk app virtual pin 31
WidgetLED led2(30);//StopLED in blynk app virtual pin 31
//WidgetLCD lcd0(V0); //top lcd widget in blynk app on virtual pin 0
WidgetLCD lcd1(V1); //middle lcd widget in blynk app on virtual pin 1
//WidgetLCD lcd2(V2); //bottom lcd widget in blynk app on virtual pin 2
// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "xxxxxxxx";
#define EspSerial Serial
ESP8266 wifi(EspSerial);
SimpleTimer timer;




byte statusLed    = 13; //led built in to Uno

byte sensorInterrupt = 0;  // 0 = digital pin 2
byte sensorPin       = 2;

// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 4.5;

volatile byte pulseCount;  

float flowRate;
unsigned int flowMilliLitres;
unsigned long totalMilliLitres;
unsigned long oldTime;
unsigned long TargetVolume; //target volume amount set by blynk slider
void setup()
{
  // Set ESP8266 baud rate
  EspSerial.begin(115200);
  // Initialize a serial connection for reporting values to the host
  Serial.begin(115200);
  Blynk.begin(auth, wifi, ssid, password); //start blynk

  while (Blynk.connect() == false) {
    // Wait until blynk connected
  } 
  // Set up the status LED line as an output
  pinMode(statusLed, OUTPUT);
  digitalWrite(statusLed, HIGH);  // We have an active-low LED attached
  
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);

  pulseCount        = 0;
  flowRate          = 0.0;
  flowMilliLitres   = 0;
  totalMilliLitres  = 0;
  oldTime           = 0;

  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);

  timer.setInterval(1000, WorkRoutine); //this is the blynk timer to run the jobs
  
}

/**
 * Main program loop
 */
void loop()
{
Blynk.run();
timer.run();  
}
void WorkRoutine(){
if((millis() - oldTime) > 1000)    // Only process counters once per second
  { 
    // Disable the interrupt while calculating flow rate and sending the value to
    // the host
    detachInterrupt(sensorInterrupt);
        
    // Because this loop may not complete in exactly 1 second intervals we calculate
    // the number of milliseconds that have passed since the last execution and use
    // that to scale the output. We also apply the calibrationFactor to scale the output
    // based on the number of pulses per second per units of measure (litres/minute in
    // this case) coming from the sensor.
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
    
    // Note the time this processing pass was executed. Note that because we've
    // disabled interrupts the millis() function won't actually be incrementing right
    // at this point, but it will still return the value it was set to just before
    // interrupts went away.
    oldTime = millis();
    
    // Divide the flow rate in litres/minute by 60 to determine how many litres have
    // passed through the sensor in this 1 second interval, then multiply by 1000 to
    // convert to millilitres.
    flowMilliLitres = (flowRate / 60) * 1000;
    
    // Add the millilitres passed in this second to the cumulative total
    totalMilliLitres += flowMilliLitres;
      
    unsigned int frac;
    
    // Print the flow rate for this second in litres / minute
    //Serial.print("Flow rate: ");
    //Serial.print(int(flowRate));  // Print the integer part of the variable
    //Serial.print(".");             // Print the decimal point
    //lcd0.clear(); //Use it to clear the LCD Widget in blynk app
   // lcd0.print(0, 0, "Flow rate: "); // use: (position X: 0-15, position Y: 0-1, "Message you want to print")
    //lcd0.print(0,1, int(flowRate));  // Print the integer part of the variable
    //lcd0.print(3, 1, "."); 
    // Determine the fractional part. The 10 multiplier gives us 1 decimal place.
    frac = (flowRate - int(flowRate)) * 10;
    //Serial.print(frac, DEC) ;      // Print the fractional part of the variable
    //lcd0.print(7, 1, "frac, DEC");
    //Serial.print("L/min");
    //lcd0.print(11, 1, "L/min");
    // Print the number of litres flowed in this second
    //Serial.print("Current Liquid Flowing: ");             // Output separator
    //lcd1.clear(); //Use it to clear the LCD Widget in blynk app
    lcd1.print(0, 0, "Liquid Flowing:        ");
    //Serial.print(flowMilliLitres);
    lcd1.print(1, 1, "                    ");
    lcd1.print(1, 1, flowMilliLitres);
    //Serial.print("mL/Sec");
    lcd1.print(8, 1, "mL/Sec");
   
    Blynk.virtualWrite(2, flowRate); 
    // Print the cumulative total of litres flowed since starting
    //Serial.print("  Output Liquid Quantity: ");             // Output separator
    //lcd2.clear(); //Use it to clear the LCD Widget in blynk app
    //lcd2.print(0, 1, "  Output Liquid Quantity: ");
    //Serial.print(totalMilliLitres);
    //lcd2.print(0, 1, totalMilliLitres);
    //Serial.println("mL"); 
    //lcd2.print(0, 1, "mL"); 

    // Reset the pulse counter so we can start incrementing again
    pulseCount = 0;
    
    // Enable the interrupt again now that we've finished sending output
    attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
  }
  
}
BLYNK_WRITE(V5) { //this block runs when you adjust the blynk app slider for volume
TargetVolume = param.asInt(); //    / 4.02
Blynk.virtualWrite (13, TargetVolume); //write debug data to virtual pin 13
}

void StartButton(){
  
}

void StopButton(){

}

void ResetButton (){
  
}
/*
Interrupt Service Routine
 */
void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}

1 Like

Wow, that was fast! Now I have something to look into during easter holiday :slight_smile:
Thank you for the help and pointers so far! Much appreciated :smiley:
Looking forward to see the progress on this one!

1 Like

I’m astonished to see such attitude in Blynk community.

Thank you all :pray:

2 Likes

I should get the sensor in a couple days (yay for Amazon Prime 2 day shipping!) I am going on holiday for a while, but like to work on this stuff when I can 't sleep, so i may make some progress… If not, then I will pick it up when I get off holiday in April. @Moelster, where are you located? I am in the USA, in the state of Ohio…

Nice :slight_smile:
I am from Norway.

I received my ESP8266 today, but forgot my computer at work before the holiday. I’ll have to wait a week before I can continue :frowning:

You mentioned that you wish to control a ball vale with a relay. To my knowledge, a relay only opens or closes a circuit and would not give you the variable flow control that you desire. Perhaps you can connect a servo to the ball valve or shop for a solenoid valve to get you the degree of control you seek?

I am thinking of using one of these for the water-filler. Afaik, this is almost the same as a solenoid? :slight_smile:

http://m.ebay.com/itm/HSH-Flo-2-Way-1-2-to-1-NPT-DC12V-Brass-Motorized-Ball-Valve-Electrical-Valve-/121822478154?nav=SEARCH&varId=420816024869

I can’t tell if that valve can be partially open or if it is all open/all closed. Before you order, you should determine if you need to actually control the psi (output volume) of the fluid (water), or if all the way open to all the way closed will suffice your needs.

It’s either fully open or closed. I think I can get it pretty accurate only by adjusting the pulses per liter on the sensor :slight_smile:
Is there a way to make the slider exceed the 9999 limit? If not, then I’ll have to convert to litres :stuck_out_tongue:
I’m upgrading to a 200L brewery, and the water filler will be limited to 9.999L at a time with the slider input in mL :smiley:
Anyways, I got my computer back now, so I’ll continue looking into your code, @bpthomas. :slight_smile:

Hello, wanted help for my project that uses the same flow sensor, are actually 3 sensors would make a monitoring the flow of 3 pumps, however when I try to make the value appear in the blynk appears only HIGH and LOW. I use an Arduino Mega and Ethernet Shield, my code is:

    float vazao; //Variável para armazenar o valor em L/min
    float media=0; //Variável para tirar a média a cada 1 minuto
    int contaPulso; //Variável para a quantidade de pulsos
    int i=0; //Variável para contagem


void setup()
{ 
  Serial.begin(9600); //Inicia a serial com um baud rate de 9600
  
  pinMode(2, INPUT);
  attachInterrupt(0, incpulso, RISING); //Configura o pino 2(Interrupção 0) para trabalhar como interrupção
  Serial.println("\n\nInicio\n\n"); //Imprime Inicio na serial
} 


void loop ()
{
  contaPulso = 0;   //Zera a variável para contar os giros por segundos
  sei();      //Habilita interrupção
  delay (1000); //Aguarda 1 segundo
  cli();      //Desabilita interrupção
  
  vazao = contaPulso / 5.5; //Converte para L/min
  media=media+vazao; //Soma a vazão para o calculo da media
  i++;
  
  Serial.print(vazao); //Imprime na serial o valor da vazão
  Serial.print(" L/min - "); //Imprime L/min
  Serial.print(i); //Imprime a contagem i (segundos)
  Serial.println("s"); //Imprime s indicando que está em segundos
  
}
 
 
void incpulso ()
{ 
  contaPulso++; //Incrementa a variável de contagem dos pulsos
}

That can’t possibly be your complete code. Where is the Blynk part? And if you add blynk like this, it’ll get you really weird results because you use the loop for executing code. Take a look at the PushData example to see how to use timers with the SimpleTimer library. It works really nice and makes for really predictable results.

Also, a little tip if you seek help on your code, make your comments in English, it makes your code so much more understandable for us (and you do comment a lot, which is really good!). It’ll give us a chance to help you better in explaining what is going good and where it’s going wrong

Thanks for the tips, really this is not the complete code, I will adjust it and go back to seek help.