Monday, March 16, 2009

Simple Arduino Fluid Control

Now that I am an actual iPhone user, I should be writing up a comparison with my i9 phone, but for now, another small Arduino project will have to suffice.

Diligent readers will remember that all this started with a desire on my part of make a solar pool heater using the the Arduino. Of course, the critical part of that is to be able to control valves & pumps and move liquid around.

This is my first project to start investigating this. This includes a 12 VDC solenoid valve that I bought off of eBay (click here for details) and a simple moisture detector circuit I previously used on another project. When the system starts up, the valve is closed and pushing the button off of Pin 12 opens the solenoid valve controlled by Pin 4. When the water level reaches the moisture detector on Pin 5, then the valve closes. To restart, you can lower lower the water level and push the button again and the cycle will run over.

Here is a video of the operation (keen observers will note that this is actually a more breadboardable iDuino not a proper "Arduino"):




Yes, the green colored water is in honor of Saint Patrick's Day and to make it easier to see.

Here is the circuit diagram:



I am gradually getting better with Eagle CAD!

The software is equally simple:

/*
Solenoid control
copyright Chris Armour 2009
 */

int ValvePin = 4;                // Solenoid valve connected to pin 4
int SwPin = 12;
int buttonWas = 0; // The state of the switch (pushed = 1, not pushed = 0) last time we looked
int buttonIs = 0; // Current state of the switch
int LEDPin = 13;
int MoistPin = 5;
int val = 0;

void setup()                    // run once, when the sketch starts
{
  pinMode(ValvePin, OUTPUT);      // sets the digital pin as output
  pinMode(SwPin, INPUT);
  pinMode(LEDPin, OUTPUT);
  Serial.begin(9600);
  buttonIs = digitalRead(SwPin); //Read the initial state of the switch!
}

//===========Functions=====================//
void getButton() { 
  buttonWas = buttonIs; // Set the old state of the button to be the current state since we're creating a new current state.
  buttonIs = digitalRead(SwPin); // Read the button state
} 

void openValve(){
    digitalWrite(ValvePin, HIGH);
    digitalWrite(LEDPin,HIGH);
    Serial.println("Valve Open");
}

void closeValve(){
  digitalWrite(ValvePin, LOW);
  digitalWrite(LEDPin,LOW);
  Serial.println("Valve closed");
}
  
//=================Main Loop===================//
void loop()                     // run over and over again
{
 getButton();
  
  if((buttonIs==1)&&(buttonWas==0)) { 
    openValve();
      }
  
  val = analogRead(MoistPin);
  
  if((val > 500)){ 
    closeValve();
      }
}


Putting the Valve Open & Valve Closed commands into functions greatly simplifies the main loop, which will make it easier to extend. The only tricky part was getting the momentary pushbutton switch initialized correctly. FOr some reason, it was always starting with the valve in the open state as if the button had been pushed. This requires you put the "buttonIs = digitalRead(SwPin);" into the setup section in order to get the right values set for the intial state of the switch. This seems a bit odd to me since I would have thought that this would be taken care of by the intial declaration of the variable. It must be something about the Arduiono boot up process that accidentally sets "buttonIs" to something unexpected!

Apologies for not posting this before, but here is a link to the original moisture detector circuit with a detailed explanation -> http://www.botanicalls.com/archived_kits/twitter/. A bit dated (like this article), but lots of good details.

That it for now. The next step will be to add in a pump so that when the water level is reached and the valve shuts the pump turns on and send the water back to the reservoir. This would make this a perpetual cycle of draining and pumping.