/* http://www.geeetech.com/wiki/index.php/Serial_I2C_1602_16%C3%972_Character_LCD_Module connections: Vcc - +5V GND - 0V SDA - A4 SCL - A5 the blue box is a potentiometer Spinning the potentimeter clockwise is to increase contrast ,spinning unclockwise is to decrease it */ #include #include LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display int repeats = 10; // number of times to read value int sums[2][2] = {{0, 0}, {0, 0}}; // running totals of readings accessed as sums[output][analog0] and sums[output][analog1] int m = 35; // values found from slope of graph int c = 102; boolean output = 0; int sat[2]; //results of saturation calculation int average; //average of two saturation calcs int change; //difference between up & down readings void setup() { pinMode(13, OUTPUT); pinMode(12, OUTPUT); analogReference(DEFAULT); lcd.init(); // initialize the lcd //Serial.begin(9600); //not needed except for diagnostics } void loop() { makeoutputs(); //set the output levels on D12 & 13 and change boolean state takereadings(output); //take readings from analog 0 & 1 and add to sums //printreadings(); //diagnostic only findsat(output); //calculate saturation for up and down if (!output) //every other time .. { if (stable()) { showsat();} else {showchange(change); } } //delay(100); } //present the outputs and change to use opposite state next time. void makeoutputs () { digitalWrite(13, output); output = !output; digitalWrite(12, output); delay(100); //allow time to settle before taking readings } // take "repeats" readings over a period of around 0.5 sec and add them up void takereadings(int b) { sums[b][0] = 0; sums[b][1] = 0; for (int j = 0; j < repeats; j++) { sums[b][0] += analogRead(0); sums[b][1] += analogRead(1); delay(53); // choose a short delay that does not add to multiple of 20msec. } } //"saturation" is found from slope of log conductance curve between limiting values - see spreadsheet. //y = mx + c gives y = -(0.0185 * reading) + 95 // to use integer arithmetic we change y = mx + c to y = - ( x/m ) + c void findsat(int b) { int difference = abs(sums[b][0] - sums[b][1]); // note the difference will always be positive sat[b] = - difference / m; sat[b] += c; // prevent readings of more than 100% or less than zero % if (sat[b] < 0) { sat[b] = 0; } else if (sat[b] > 100) { sat[b] = 100; } //correction "fiddle factor" because the relation between resistance and saturation is not linear sat[b]*=sat[b]; sat[b]=sat[b]/100; } //compare two sets of readings to see if its stable boolean stable() { boolean v = 0; change = abs (sat[0] - sat[1]); average = (sat[0] + sat[1]) / 2; // if change is less than 10% of full scale then its stable if (change <= 15) { v = 1; } return v; } void showsat() { lcd.clear(); lcd.backlight(); //turn backlight on - in case its off lcd.setCursor ( 0, 0 ); // set to col:row - eg 1,8 is 8 chars in on of lower line lcd.print("Soil saturation"); lcd.setCursor ( 6, 1 ); // set to centre of lower line lcd.print(average); lcd.print("%"); } void showchange(int r) { lcd.clear(); lcd.backlight(); //turn backlight on - in case its off lcd.setCursor ( 0, 0 ); // set to col:row - eg 1,8 is 8 chars in on of lower line lcd.print("Not stable .."); lcd.setCursor ( 6, 1 ); // set to centre of lower line lcd.print(r); } /* void printreadings(){ Serial.print("Sum[0][0] :"); Serial.print(sums[0][0]); Serial.print(" Sum[0][1] :"); Serial.println(sums[0][1]); //Serial.print("Sum[1][0] :"); //Serial.print(sums[1][0]); //Serial.print(" Sum[1][1] :"); //Serial.println(sums[1][1]); } */