# Continuously measuring differences between values in a string

I am working on a soil moisture sensor where I want an LED to be on continuously when dry but trigger an action just one time when watered. I can make the red LED light up continuously when dry but don't know how to make the sketch light the green LED just once after being watered and then turn off. I can make it trigger continually but I just want it to do it one time and then stop. Is there a way to continuously compare the values of a single number in a string to the number that just preceded it? If I could do this, I could use the difference between the two successive numbers to solve my problem, as the really big jump in value would occur just once before stabilizing at a higher level. Dry values in my system are about 15, wet values are about 400. So a dry to wet looks like: 15,14,15,16,401,409,406,403.... and so forth.

Here's an example of what doesn't work (there is a flip flop built in to minimize electrolysis - the rest of the sketch is straightforward) This sketch turns on both red and green LED's continuously

#define voltageFlipPin1 6
#define voltageFlipPin2 7
#define sensorPin 0

int ledPin = 13; // set the pin that the LED that indicates the plant is dry
int ledPin2 = 12; // set the pin that indicates the plant has been watered
int avg1 = 0; // current state of the soilwetness
int val1 = 0;
int val2 = 0;

void setup(){ //INITIALIZE AND SET THE HARDWARE TO COMMUNICATE IN A SPECIFIC WAY
Serial.begin(9600); //BEGIN SERIAL COMMUNICATIN
pinMode(voltageFlipPin1, OUTPUT); //SET PIN 6 TO OUTPUT TO FLIP POLARITY
pinMode(voltageFlipPin2, OUTPUT); //SET PIN 7 TO OUTPUT TO FLIP POLARITY
pinMode(sensorPin, INPUT); //SET ANALOG 0 PIN TO INPUT TO ASSESS DRYNESS
pinMode(ledPin, OUTPUT); // SET PIN 13 AS OUTPUT
pinMode(ledPin2, OUTPUT); // SET PIN 12 AS OUTPUT

}
void setSensorPolarity(boolean flip){ //SETSENSORPOLARITY MEANS JUST THAT TO BOOLEAN MEANS TRUE OR FALSE
if(flip){
digitalWrite(voltageFlipPin1, HIGH); //IF ONE IS ON, SET OTHER TO OFF - SAME FOR NEXT STEP BUT OPPOSITE
digitalWrite(voltageFlipPin2, LOW);
}else{
digitalWrite(voltageFlipPin1, LOW);
digitalWrite(voltageFlipPin2, HIGH);
}
}
void loop ()

{ setSensorPolarity(true); //SETSENSORPOLARITY TO THE "TRUE" STATE, DELAY 50 MSEC, TAKE A READING
delay(50);
delay (50);
setSensorPolarity(false); //SETSENSORPOLARITY TO THE "FALSE" STATE, DELAY 50 MSEC, TAKE A READING
int val2 = 1023 - analogRead(sensorPin);

void reportLevels(int val1,int val2);
int avg1 = (val1 + val2) / 2;
String msg1 = "avg1: "; //SEND THE AVG1 TO THE MESSAGE STRING
msg1 += avg1; //INCREMENT IT BY 1
Serial.println(msg1); //PRINT THE STRING TO THE SERIAL MONITOR }

if (avg1 < 30) //IF THE RESISTANCE IS HIGH TURN THE RED LED TO HIGH
digitalWrite(ledPin, HIGH); //
else {
digitalWrite(ledPin, LOW); } //IF NOT, SET IT TO LOW

if (avg1 > 30) { //IF THE RESISTANCE IS LOW SET THE GREEN LED TO HIGH
digitalWrite(ledPin2, HIGH); }
else {
digitalWrite(ledPin2, LOW); } //IF NOT, SET IT TO LOW

}

I would use a threshold, say about half way between dry and wet: 207. Call anything below the threshold dry and anythig higher wet. Now you just have to look for a change from dry to not-dry:

``````const int WetThreshold = (400+15)/2;
void loop() {
static boolean previouslyDry = true;
boolean nowDry = wetness < WetThreshold;
if (previouslyDry && !nowDry) {
//light the green LED
}
prevouslyDry = nowDry;
}
``````
``````void loop  ()

{ setSensorPolarity(true);  //SETSENSORPOLARITY TO THE "TRUE" STATE, DELAY 50 MSEC, TAKE A READING
delay(50);
delay (50);
setSensorPolarity(false); //SETSENSORPOLARITY TO THE "FALSE" STATE, DELAY 50 MSEC, TAKE A READING
int val2 = 1023 - analogRead(sensorPin);

void reportLevels(int val1,int val2);
int avg1 = (val1 + val2) / 2;
String msg1 = "avg1: "; //SEND THE AVG1 TO THE MESSAGE STRING
msg1 += avg1;    //INCREMENT IT BY 1
Serial.println(msg1); //PRINT THE STRING TO THE SERIAL MONITOR }
``````

Why do you have a function prototype in the middle of loop()? That line is NOT calling a function.

THANK YOU BOTH! I SOLVED THE PROBLEM, ALBEIT IN THE SIMPLEST WAY POSSIBLE, THANKS TO YOUR INPUT JOHN. AS FOR YOUR COMMENT PAUL, THE ANSWER IS I DO NOT KNOW WHY THE FUNCTION PROTOTYPE WAS CALLED. I CUT AND PASTED THIS FROM SOMEONE ELSE'S SKETCH TO DO THE FLIP FLOP AND IT WAS PART OF THEIR PROGRAM. I AM TOO NEW TO ARDUINO AND PROGRAMMING IN GENERAL TO FULLY UNDERSTAND IT.

IN ANY EVENT, HERE IS A FRAGMENT OF THE CODE I USED AT THE END;

difference = currentwetness - lastwetness;

if (currentwetness < 30) //IF THE RESISTANCE IS HIGH (LESS THAN 30)
digitalWrite(ledPin, HIGH); // TURN THE LED TO HIGH
else {
digitalWrite(ledPin, LOW); } //IF NOT, SET IT TO LOW

if (currentwetness - lastwetness > 100) {
//
digitalWrite(wetthankyoupin, HIGH); } // TURN ON AND TRIGGER THE THANK YOU MESSAGE
else {
digitalWrite(wetthankyoupin, LOW); } //IF NOT, TURN THE MESSAGE OFF

lastwetness = currentwetness;

``````String add = "difference: ";
``````

Pissing away resources on the String class to avoid using two Serial.print() statements is stupid. Get out of that habit NOW!

My my, Paul. We are getting judgmental, aren't we? First of all, while I appreciate your feedback, there is no need to take a rude tone here. Second, I don't really give a damn about resources. It's a tiny little program for god's sake. Should I write more complex programs in the future, I will keep your advice in mind. Third, this is literally the first computer program I have ever written in my life. As such, I am rather proud of its modest ability to accomplish the intended goal. And fourth, I don't even understand what you mean by "pissing away resources on the string class". I would not mind a more detailed explanation (or reference if you don't have the time to explain it).

But regardless of your reply, and I doubt I am the first person to say this, lighten up a little!

Should I write more complex programs in the future, I will keep your advice in mind.

The problem with developing bad habits in the first place is that they are so hard to break. And, determining when you need to break them will drive you crazy. My harsh tone was intended to make you think about the bad habits you are developing.

And fourth, I don't even understand what you mean by "pissing away resources on the string class". I would not mind a more detailed explanation (or reference if you don't have the time to explain it).

The String class, not to be confused with the recommended string usage, does dynamic memory allocation. While this is fine on a PC with 16 gigabytes of memory and a robust memory management system, it doesn't work too well when there are only 2048 bytes of memory.

Every time you add a character to a String instance, the class allocates one more byte than the existing instance's length, copies the data from the old location to the new location, and then adds the new character.

If you do this often enough, you make swiss cheese of your memory, where eventually you have plenty of memory but there are no contiguous blocks large enough to be useful.

People have been writing programs in C and C++ for 40 years before the String class came along. Certainly all that code proves that text processing CAN be done without the waste of the String class.

OK. Now, we are talking. I think I understand what you are saying here. I have no desire to waste memory or build bad habits. I enjoy writing programs, but my background is limited. So, if you would, give me an example of how you would rewrite that little snippet of code to avoid resource waste. Kind of like a "bad code" "good code" comparison.

``````String add = "difference: ";
``````

Good code:

`````` Serial.print(F("difference: "));
``````

Use fewer lines. Use less SRAM. Use less flash memory.

Three out of three ain't bad.

I tried what you recommended but at first, it would not compile because add was not declared in the scope.
I removed the last line and changed the first to;

Serial.println(F("difference: "));

to return a line - which it did. The program worked functionally on the Arduino but it would not print the actual numerical value on the monitor.

Obviously, I am missing something very simple. Any suggestions?

The first 3 lines work and return a printed value on the monitor:

String msg1 = "currentwetness: "; //SEND CURRENTWETNESS TO THE MESSAGE STRING
msg1 += currentwetness; //INCREMENT IT BY 1 AT THIS SPEED
Serial.println(msg1); //PRINT THE STRING

The next 2 work but do not return a value:

difference = currentwetness - lastwetness;
Serial.println(F("difference: "));

I suspect PaulS meant to have:

``````Serial.print(F("difference: "));
Serial.println(difference);
``````

The first printing the text and the second the value you want to see.

pinMode(ledPin, OUTPUT); // SET PIN 13 AS OUTPUT

msg1 += currentwetness; //INCREMENT IT BY 1 AT THIS SPEED

and this comment can easily be wrong

Comments should (99% of time) describe WHY something is done. Than the implementation is explained.

I suspect PaulS meant to have:

Yep. It was late...

And I will try and stick to proper style guidelines in future posts.

Thank you everybody, for your assistance!

The credit should be for PaulS, I merely corrected his typo.

Acknowledged. Thank you PaulS.