Friday, July 24, 2009

Version 2.0 of the Automated Watering System - Wireless is Working!

Well, its been a late night, but I finally got the prototype sensor station and the prototype irrigation controller communicating wirelessly. The sensor station takes a soil humidity reading and then using wireless serial communication sends the value to the controller. The controller checks the value and then turns on or off a solenoid valve. This one to one communication is pretty simple, but very cool to see in action.

Here is the code for the irrigation controller with only one pump:

/* 
 * This is a sketch for turning on a water pump
 * when a dryness threshold is met.  It uses serial
 * communication with a sensor station to check to see
 * what the current humidity level is.  It then turns on
 * a pump to water the plants.
 */
 
 int rxLed = 13;
 int redLed = 3;
 int pumpPin = 8;
 
 int inByte = -1;
 char inString[6];
 int stringPos = 0;
 
 void setup() {
   Serial.begin(9600);
   pinMode(redLed, OUTPUT);
   pinMode(pumpPin, OUTPUT);
   pinMode(rxLed, OUTPUT);
 }
 
 void loop() {
   
  if (Serial.available()) {
    // turn on RX LED whenever reading data
    digitalWrite(rxLed, HIGH);
    handleSerial();
  }
  else {
    // turn off the led when not reading data
    digitalWrite(rxLed, LOW);    
  }
}
 
 void checkPump(int sensorVal){
   if (sensorVal < 500) {
     digitalWrite(redLed, HIGH);
     digitalWrite(pumpPin, LOW);
   } else {
     digitalWrite(redLed, LOW);
     digitalWrite(pumpPin, HIGH);
   } 
 }
 
 void handleSerial() {
   inByte = Serial.read();

   // save only ASCII numeric characters (ASCII 0 - 9):
   if ((inByte >= '0') && (inByte <= '9')) {
     inString[stringPos] = inByte;
     stringPos++;
   }
   
   // if you get an * (end of message), 
   // then convert what you have to an integer:
   if (inByte == '*') {
     // convert string to number
     int humidity = atoi(inString);
     
     // see if the pump needs to be turned on
     checkPump(humidity);
     
     // put zeros in the array
     for (int c = 0; c < stringPos; c++) {
       inString[c] = 0;
     }
     
     // reset the string pointer:
     stringPos = 0;
   }
 }


And here is the code for the sensor station:

/* 
 * A Garden Sensor Station
 * Sends the moisture sensor reading via serial communication.
 */
 
 int moistureSensor = 0;
 // to show communication
 int txLed = 13;
 
 int moistureVal;
 
 void setup() {
   Serial.begin(9600);
   pinMode(txLed, OUTPUT);
 }
 
 void loop() {
   
   // Get sensor reading and send it.
   moistureVal = analogRead(moistureSensor);
   digitalWrite(txLed, HIGH);
   Serial.print(moistureVal, DEC);
   Serial.print('*'); // end of message marker
   digitalWrite(txLed, LOW);
     
   delay(2000); // wait   
 }


I see some possible benefits to having the sensor station just transmit to the irrigation controller whether or not the irrigation controller should turn on, but one of the disadvantages that I see with that is that you now have all the irrigation logic spread across all the sensor stations. So, the choice I made was to make the sensor stations "dumb" and the irrigation controller "smart". If I want to make changes to the irrigation amount, timing, sensitivity, etc. I just have to go to one micro-controller.

Next up: getting the whole thing in place and watering some real plants!

0 comments: