Flow Controller

The Homebrew Forum

Help Support The Homebrew Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.

stevela

Regular.
Joined
May 1, 2013
Messages
238
Reaction score
2
Location
Manchester
===================================================

Latest code (Working Branch): Click Here
Stable v1:Click Here

===================================================

I've decided it is time to do something about my inability to count the number of two liter flasks I empty into my HLT and try and build a flow sensor. With that in mind I've ordered a few bits and pieces cheap off eBay which have finally arrived!

SainSmart UNO R3 Starter Board (£9.99)

yvdyzWv.jpg


YF-S201 flow sensor (£4.35)

nSqnCnf.jpg


SainSmart LCD1602 (£2.64)

BxlHRtQ.jpg


Above you can see the display connected to the Arduino and running, unfortunately when I run the sample code from here to test the keypad it does not appear to pick up the select button. Modified the code as below to try and track the problem down but still get no output:

Code:
//Sample using LiquidCrystal library
#include <LiquidCrystal.h>
 
/*******************************************************
 
This program will test the LCD panel and the buttons
Mark Bramwell, July 2010
 
********************************************************/
 
// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
 
// define some values used by the panel and buttons
int lcd_key     = 0;
int adc_key_in  = 0;
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5
 
// read the buttons
int read_LCD_buttons()
{
 adc_key_in = analogRead(0);      // read the value from the sensor

 if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result

 if (adc_key_in < 50)   return btnRIGHT; 
 if (adc_key_in < 250)  return btnUP;
 if (adc_key_in < 450)  return btnDOWN;
 if (adc_key_in < 650)  return btnLEFT;
 if (adc_key_in < 850)  return btnSELECT; 

 return btnNONE;  // when all others fail, return this...
}
 
void setup()
{
 lcd.begin(16, 2);              // start the library
 lcd.setCursor(0,0);
 lcd.print("Push the buttons"); // print a simple message
}
  
void loop()
{
 lcd.setCursor(9,1);            // move cursor to second line "1" and 9 spaces over
 lcd.print(millis()/1000);      // display seconds elapsed since power-up
 
 
 lcd.setCursor(0,1);                   // move to the begining of the second line
 lcd_key = read_LCD_buttons();  // read the buttons
 lcd.print(adc_in_key);              //print out the value to see what the buttons are doing 
}

Probably just a duff LCD (for £3 shipped from China I wasn't expecting much) and for the moment the display works fine which is all I need.

Next step, find a spec sheet for the flow sensor to see how it needs to be wired up and figure out how I calculate flow from the output of the sensor.

I haven't done anything like this for a very long time so this will probably be a slow and potentially frustrating project :)
 
Cant wait to see this progress, would love to incorporate something like this into the brewery with flow controller's and motorised ball valves :)
 
probably a duff lcd, im way off being expert but have played with arduino a bit too and the sample code for these things is pretty builet proof. and if the other buttons work.. ;)

Tho last time i looked at arduino code i got an ide update warning, last time that happened a few libs changed name needing a bit of an edit but was well documented on the arduino playground site


all u need to add a button tho is a 10k resistor and he momentary contact button of your choice ;) and check out the bounce and debounce samples...



hopefully the flow sensor will 'beep' on with every quantity thru so it should be a simple count and multiply solution.

i have had similar thoughts along these lines myself tho i was thinking about pints left in a corny rather than brewing liquor.. so will probably be looking to copy your hard work down the road ;) so will be following your progress with interest..

A nice feature would be setting the desired volume out, and having it measure thru sloanoid valve automatically.

Dishwasher water inlet valves are made from foodsafe plastics and are about a fiver on ebay, the down side is they are 240v ac driven not low dcV..

have fun with it ..
 
I've managed to find some specs for the flow sensor here:

https://www.adafruit.com/products/828#Description

Looks like it is one pulse per 2.25ml so as you say should be a simple count and multiply job (Sample Code).

It did take me three or four different "sample codes" before I found one for the LCD that came close, a lot needed the library updates that you mentioned which took me a while to suss out.

Full programmed control would be wonderful (especially getting it to take into account the known dead-space in the HLT), I came across this page whilst searching for specs on the flow sensor and it looks like he started going the whole way with a 4.5v solenoid (EHCOTech DDT-ML-4.5VDC Latching 3 - 115 PSI solenoid valve). I'd just need to find an equivalent one with 1/2" BSP connection.

Anyway thats running before I can crawl right now :)

Ordered some cables to hook up this sensor which should arrive on Friday.
 
couldnt read code on the didy screen earlier..

Code:
if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result

if (adc_key_in < 50)   return btnRIGHT; 
if (adc_key_in < 250)  return btnUP;
if (adc_key_in < 450)  return btnDOWN;
if (adc_key_in < 650)  return btnLEFT;
if (adc_key_in < 850)  return btnSELECT;


there is the condition 850 < adc_key_in < 1000, not catered for

try
Code:
if (adc_key_in < 1000)  return btnSELECT;
**edit HA <=1000 or <1001 even Whoops!

might help getting the select button recognised??

im rusty but this looks like 5 buttons on one pin using different resistance to determine which one pressed if so its again detailed in arduino playground.. i used the simpler 1 pin per button for my buttons but wast tight on usable pins at all

to debug further drop the setting to btnnone and output whatever the adc_key_in is, use the lcd as a mini watch window :)

also as i have made an ebay punt on solanoid valves i can steer u away from these as the actual bore is a pin prick, it would take a day to run 10l thru these
http://www.ebay.co.uk/itm/New-DC-12V-3W ... 460a9e4efe
 
Fil said:
to debug further drop the setting to btnnone and output whatever the adc_key_in is, use the lcd as a mini watch window :)

Hi Fil,

I've cut the code down to the following to just get the pure values and see what is happening:

Code:
#include <LiquidCrystal.h>
 
// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
 
// define some values used by the panel and buttons
int lcd_key     = 0;
int adc_key_in  = 0;
 
// read the buttons
int read_LCD_buttons()
{
 adc_key_in = analogRead(0);   
 return adc_key_in;
}
 
void setup()
{
 lcd.begin(16, 2);              // start the library
 lcd.setCursor(0,0);
}
  
void loop()
{
 lcd.setCursor(0,0);            // move cursor to second line "1" and 9 spaces over
 lcd.print(millis()/1000);      // display seconds elapsed since power-up
 lcd.setCursor(0,1);            // move to the begining of the second line
 lcd_key = read_LCD_buttons();  // read the buttons
 lcd.print(lcd_key);            // DEBUG PRINT KEY VALUE
}

With this I get the following values:

Code:
NONE = 1023
UP = 2193
DOWN = 4973
LEFT = 7653
RIGHT = 0023
SELECT = NO CHANGE FROM 1023
RESET  = PROGRAM RESET

So I still think I'm on the path of either duff LCD or the wrong model as after looking at Sainsmarts site they appear to have two models:

http://www.sainsmart.com/sainsmart-1602 ... a1280.html

and

http://www.sainsmart.com/sainsmart-keyp ... no-r3.html

looking at the contrast control it looks like mine is the earlier model so may just not work on the R3. I'll look at picking up a new shield once I'm in need of 5 buttons which I can't see happening for a while.
 
Right after some tweaking I have it up and running doing the following:

1. Power on display boot logo
2. Display the set volume (target_volume) and current volume (current_volume)
3. Allow you to use the up and down keys to change the set volume to a max defined against the hltSIZE and a minimum of 0
4. Use the left and right buttons to simulate flow in 0.01 increments
5. When the target_volume matches the current_volume clear the display and show a message (this is where I would close a solenoid down the line)

Hopefully the cables will arrive tomorrow and I can see about hooking up the flow meter. Until then a few images:

x9uDdEB.jpg


2ynL8Nr.jpg


b3CgJgn.jpg


Code:
#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

int lcd_key     = 0;
int adc_key_in  = 0;
float target_volume = 0.5;
float current_volume = 0;

#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

#define hltSIZE   50                       //Size of the Hot Liquor Tun in lit

void setup()
{
  lcd.begin(16, 2);                        // start the library

  printBanner(2000);                       // show banner for 2 seconds
  
  clearLCD();
  
  printLabels();

}

void loop()
{

  while(current_volume < target_volume)
  { 
    dowork();
  }

  lcd.setCursor(0,0);
  lcd.print("  VALVE CLOSED  ");
  lcd.setCursor(0,1);
  lcd.print("   TARGET HIT   ");
  
  //TODO SOLENOID CODE
}

void clearLCD()
{
  lcd.setCursor(0,0);                      
  lcd.print("                ");
  lcd.setCursor(0,1);
  lcd.print("                ");
}

void printBanner(int bannerdelay)
{
  lcd.setCursor(0,0);                     
  lcd.print("        ^       ");
  lcd.setCursor(0,1);  
  lcd.print("  >>BrewShark>  ");
  delay(bannerdelay);
}

void printLabels()
{
  lcd.setCursor(0,0);
  lcd.print("Set Vol: ");
  lcd.setCursor(0,1);
  lcd.print("Cur Vol: ");
}

// read the buttons
int read_LCD_buttons()
{
  adc_key_in = analogRead(0);
  delay(100);
  if (adc_key_in > 1000) return btnNONE;
  if (adc_key_in < 50)   return btnRIGHT; 
  if (adc_key_in < 195)  return btnSELECT;
  if (adc_key_in < 380)  return btnUP;
  if (adc_key_in < 555)  return btnDOWN;
  if (adc_key_in < 790)  return btnLEFT;  

  return btnNONE;
}

void dowork()
{
  //TODO READ PULSES AND CONVERT
  
  //Print the target volume value in litres
  lcd.setCursor(10,0);
  lcd.print(target_volume,2);
  lcd.setCursor(15,0);
  lcd.print("l");

  //Print the current volume value in litres
  lcd.setCursor(10,1);            
  lcd.print(current_volume,2);
  lcd.setCursor(15,1);
  lcd.print("l");

  lcd_key = read_LCD_buttons();    // read the buttons
  

  switch (lcd_key)               // depending on which button was pushed, we perform an action
  {
  case btnRIGHT:
    {
      current_volume += 0.01;       //manually simulate flow
      break;
    }

  case btnLEFT:
    {
      current_volume -= 0.01;       //manually simulate flow
      break;
    }

  case btnUP:
    {
      if (target_volume >= hltSIZE)  //don't go larger than the size of the vessel
      {
        target_volume = hltSIZE;
        break;
      }
      else
      {
        target_volume += 0.1;
        break;
      }

      break;
    }

  case btnDOWN:
    {
      if (target_volume <= 0)      //don't go below zero
      {
        target_volume = 0;
        break; 
      }
      else
      {
        target_volume -= 0.1;
      }
      break;
    }

  case btnNONE:
    {
      break;
    }
  }

}
 
Great pogress... testing backs up your duff button/shield theory, cest la vie..

i admire your patience, i would have chopped off the flow sensor plug n tinned the wires by now ;)

next step add a pid feature to control the heating too :)
the arduno 5v voltage is upto driving a SSR for rapid element switching.
 
If I had a soldering iron I would be doing just that :) It's a shame the plug on the sensor is GSV rather than GVS as I could have plugged it straight in.

Had a quick look on ebay and can see these solenoids, 12v so I'll need a relay but 16mm bore so shouldn't have a problem with throughput.

A PID you say....interesting....
 
its a pid controller that i played arduino with, i copied and cut out the pump control added bluetooth coms ;) and hijacked the rest from Jabba;s brewery programming thread over on JBK.. pm me if u need a link..
there are at least 3 excelent designs for complete systems documented there and a lot of dumb Q's from me..

there is a single typo in jabba's code but the compiler will highlight it (arduino 1.2 ide) perhaps a couple more edits for the current ide n libs

i did have to solder a few things like resistors in line with one wire temp sensors, but mostly i used mini breadboards prototyping wires and a hot gluegun to hold the configeration together ;)

the whole thing is almost finished...
8467569979_4c8d7cfb98_n.jpg


I wasted a bit of time trying to sus out sharring the pt100 probes used for the backup sestos controllers before realising that was an electronics project beyond my abilities... so they will be surplus thermometers now,

the only probs i have to sort out still are the power and switching the control for the ssrs between my pid and the sestos backups.. the logic makes my head hurt and i keep leaving that till ive built the brew shed placed the controller and have finalised the spot for sensor plugs and switches etc based on final location.

pm me if u need a few resistors etc to follow any designs i have a few spares as u buy em in the 100s and use only a few...

Yes that valve looks ok ;) can your board handle a 12v dc supply or is it limited to 9v? im pretty sure its a 12v asus netbook block i canabalised for my psu as im also using a few 12v relays for switching..
 
Great post, had thought about using a flow meter a long time ago but it's beyond me, as is most of the coding :roll:
I love the fully automated home breweries on't web, proper hard core dedication :mrgreen: :hat:
 
Fil said:
Yes that valve looks ok ;) can your board handle a 12v dc supply or is it limited to 9v? im pretty sure its a 12v asus netbook block i canabalised for my psu as im also using a few 12v relays for switching..

Nice looking project there Fil, I'm definitely going to have a PID in the brewery setup at some point not sure if I will integrate it into this or not yet keeping it simple to start with :)

The specs for the SainSmart R3 show input voltage as 7 - 12v so should be fine.

Any recommendations on 12v relays?

Vossy1 said:
Great post, had thought about using a flow meter a long time ago but it's beyond me, as is most of the coding :roll:
I love the fully automated home breweries on't web, proper hard core dedication :mrgreen: :hat:

Thanks Vossy, a lot of the code is beyond me as well but that is what cutting and pasting is for :) The idea is when this is finished anyone who wants to make one can just copy and paste the code and as long as the cables are hooked up everything should just work.

Today's update, the cables have arrived and I have hooked up the flow sensor, unfortunately because of the cables I'm using this means the shield wouldn't fit on the board so I've cabled that off to the side for now:

oUMwcZ3.jpg


I don't think I need all the pins connected but it was quicker than reading the spec sheet and seeing which ones were :)

Once I copied and pasted the code from the Adafruit example into the right places and putting the ground and sensor wire in the right place (I mean they are labelled how did I make that mistake!) blowing into the flow meter now nicely increments the current_volume value.

Code so far:

Code:
#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

int lcd_key     = 0;
int adc_key_in  = 0;
float target_volume = 0.5;
float current_volume = 0;

#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

#define hltSIZE   50                  	//Size of the Hot Liquor Tun in litres

#define FLOWSENSORPIN 2


volatile uint16_t pulses = 0;		 // count how many pulses


volatile uint8_t lastflowpinstate; 	 // track the state of the pulse pin


volatile uint32_t lastflowratetimer = 0; // you can try to keep time of how long it is between pulses


volatile float flowrate;		 // and use that to calculate a flow rate

// Interrupt is called once a millisecond, looks for any pulses from the sensor
SIGNAL(TIMER0_COMPA_vect) {
  uint8_t x = digitalRead(FLOWSENSORPIN);
  
  if (x == lastflowpinstate) {
    lastflowratetimer++;
    return; // nothing changed!
  }
  
  if (x == HIGH) {
    //low to high transition!
    pulses++;
  }
  lastflowpinstate = x;
  flowrate = 1000.0;
  flowrate /= lastflowratetimer; // in hertz
  lastflowratetimer = 0;
}

void useInterrupt(boolean v) {
  if (v) {
    // Timer0 is already used for millis() - we'll just interrupt somewhere
    // in the middle and call the "Compare A" function above
    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
  } else {
    // do not call the interrupt function COMPA anymore
    TIMSK0 &= ~_BV(OCIE0A);
  }
}

void setup()
{
    
  Serial.begin(9600);
  Serial.print("Flow sensor test!");
  
  lcd.begin(16, 2);                        // start the library

  printBanner(2000);                       // show banner for 2 seconds
  
  clearLCD();
  
  printLabels();
  
  pinMode(FLOWSENSORPIN, INPUT);
  digitalWrite(FLOWSENSORPIN, HIGH);
  lastflowpinstate = digitalRead(FLOWSENSORPIN);
  useInterrupt(true);

}

void loop()
{

  while(current_volume < target_volume)
  { 
    dowork();
  }

  lcd.setCursor(0,0);
  lcd.print("  VALVE CLOSED  ");
  lcd.setCursor(0,1);
  lcd.print("   TARGET HIT   ");
  
  //TODO SOLENOID CODE
}

void clearLCD()
{
  lcd.setCursor(0,0);                      
  lcd.print("                ");
  lcd.setCursor(0,1);
  lcd.print("                ");
}

void printBanner(int bannerdelay)
{
  lcd.setCursor(0,0);                     
  lcd.print("        ^       ");
  lcd.setCursor(0,1);  
  lcd.print("  >=BrewShark>  ");
  delay(bannerdelay);
}

void printLabels()
{
  lcd.setCursor(0,0);
  lcd.print("Set Vol: ");
  lcd.setCursor(0,1);
  lcd.print("Cur Vol: ");
}

// read the buttons
int read_LCD_buttons()
{
  adc_key_in = analogRead(0);
  if (adc_key_in > 1000) return btnNONE;
  if (adc_key_in < 50)   return btnRIGHT; 
  if (adc_key_in < 195)  return btnSELECT;
  if (adc_key_in < 380)  return btnUP;
  if (adc_key_in < 555)  return btnDOWN;
  if (adc_key_in < 790)  return btnLEFT;  

  return btnNONE;
}

void dowork()
{
  READ PULSES AND CONVERT
  Serial.print("Freq: "); Serial.println(flowrate);
  Serial.print("Pulses: "); Serial.println(pulses, DEC);
  float liters = pulses;
  liters /= 7.5;
  liters /= 60.0;
  
  current_volume = liters;
  
  //Print the target volume value in litres
  lcd.setCursor(11,0);
  lcd.print(target_volume,2);
  lcd.setCursor(15,0);
  lcd.print("L");

  //Print the current volume value in litres
  lcd.setCursor(11,1);            
  lcd.print(current_volume,2);
  lcd.setCursor(15,1);
  lcd.print("L");

  lcd_key = read_LCD_buttons();    // read the buttons
  

  switch (lcd_key)               // depending on which button was pushed, we perform an action
  {
  case btnRIGHT:
    {
      current_volume += 0.01;       //manually simulate flow
      break;
    }

  case btnLEFT:
    {
      current_volume -= 0.01;       //manually simulate flow
      break;
    }

  case btnUP:
    {
      if (target_volume >= hltSIZE)  //don't go larger than the size of the vessel
      {
        target_volume = hltSIZE;
        break;
      }
      else
      {
        target_volume += 0.1;
        break;
      }

      break;
    }

  case btnDOWN:
    {
      if (target_volume <= 0)      //don't go below zero
      {
        target_volume = 0;
        break; 
      }
      else
      {
        target_volume -= 0.1;
      }
      break;
    }

  case btnNONE:
    {
      break;
    }
  }

}
 
The idea is when this is finished anyone who wants to make one can just copy and paste the code and as long as the cables are hooked up everything should just work.
For some reason I like the idea of that :lol: :cool:...another upgrade :hmm: ..how will I get that past swimbo.
 
looking good,
as for relays to drive the valve/s? the ebay budget boards from china like http://www.ebay.co.uk/itm/5V-2-channel- ... 1e7c7f68db are worth a punt imho. easy to wire too (having to look up how to wire up a naked relay would take me a while, then testing i have the right feet identified..!!)
tho will take a while to arrive..

with a 12v dc psu with sufficient amperage to drive the valve and board for the unit u can then use the board operating voltage 5v to switch the 12v psu feed to open/close the valve.. so you only need the one psu :thumb:
 
This is interesting. I've been thinking along the lines of a flow meter to fill my sankey kegs, as unlike cornies you can't see the fill level. I was thinking along the lines of syphoning from a bucket with a known quantity and stop at the marked point. But your system would be perfect and easily controlled. Thanks for sharing. I might just plagiarise it. :grin:
 
Do you have the links to the items you bought for this project? I can see price on your first post but no idea where you bought them from. Also would you recommend buying exactly what you bought or have you had a rethink/replaced any items?

Cheers

Belter




Fil said:
Dishwasher water inlet valves are made from foodsafe plastics and are about a fiver on ebay, the down side is they are 240v ac driven not low dcV..


This would be very easy to incorporate with a 12V coil relay or SSR.
 
Belter said:
Do you have the links to the items you bought for this project? I can see price on your first post but no idea where you bought them from. Also would you recommend buying exactly what you bought or have you had a rethink/replaced any items?

Not a problem everything was from eBay:

Cables for Prototyping
Flow Sensor
Arduino Board
Keypad Shield

So far the only issue I have had is with the LCD Shield select button not working, I think for the final cased version I will probably go with just a 16x2 LCD screen and separate input buttons but for prototyping this has been fine.

Hope that helps :)


Fil,

Those budget boards look ideal I'll pick a few of those up, the wait doesn't bother me as it's a background project anyway I just happen to have a couple of days off hence the burst of activity.
 
Last edited by a moderator:
I know this takes some of the fun out of this project, but this ready made unit seems to do the job. Probably slightly more expensive at £44 but looks like it would do the job. My only concern is the temperature rating for the flow meter. 80c. Fine for the HLT to mash tun, but it would have to be put in line after the cooler, (I use a counterflow cooler) to measure the flow from the boiler to FV which would be useful to measure. But it would be fine if using an immersion chiller.
 
Last edited by a moderator:
check out the 20 x 4 lcd screen, u pay a little more, but get to display way more info and if canny can use the bottom line to label your buttons on the fly thus cutting down the need for as many buttons to start with and the need to make labels for the box ;)
 
Last edited by a moderator:

Latest posts

Back
Top