Window opener opens window again and again due to Void loop

I am trying to whrite a sketch to open and close a greenhouse window based on temperature.

The setup is as follows:
-Arduino Uno
-6 channel relais to shut the motor on and off and to reverse polarity
(similar wiring as in this video by SimpleCircuits: https://www.youtube.com/watch?
v=BQOji4i4PEc&t=66s&index=24&list=WL )
-12V DC geared motor (3.5rpm)
-rack and pinion assembly for the sliding window (see Attachments)

Here is my code so far:

const int analogPin = A0;    // pin that the sensor is attached to
const int analogPin1 = A1;    // pin that the sensor is attached to
const int ledPin = 9;       // pin that the LED is attached to
const int ledPin1 = 8;       // pin that the LED is attached 
const int threshold = 350;   // an arbitrary threshold level that's in the range of the analog input
const int threshold1 = 145;   // an arbitrary threshold level that's in the range of the analog input

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
   pinMode(ledPin1, OUTPUT);
  // initialize serial communications:
  Serial.begin(9600);
}

void loop() {
  // read the value of the sensor:
  int analogValue = analogRead(analogPin);
  int analogValue1 = analogRead(analogPin1);

  // if the analog value is high enough, turn on the LED:
  if (analogValue > threshold) {
    digitalWrite(ledPin, HIGH);
    delay(4000);
    digitalWrite(ledPin, LOW);
  } else {
    digitalWrite(ledPin, LOW);
  }
 if (analogValue < threshold) {
    digitalWrite(ledPin1, HIGH);
    delay(4000);
    digitalWrite(ledPin1, LOW);
     } else {
       digitalWrite(ledPin1, LOW);
        }
  // Temperatur in Spannung ausrechnen
  float voltage = (analogValue1/1024.0) * 5.0;
  //Temperatur in °C ausrechnen
  float temperature = (voltage - .5) * 100;
 
  // print the analog value:
 Serial.println("Dunkelheit ADC");
  Serial.println(analogValue);
  Serial.println("Temperatur ADC");
    Serial.println(analogValue1);
   Serial.println("Temperatur in °C");
    Serial.println(temperature);
      Serial.println("--------------------------------------------------------------  10s Delay");
  delay(6000);        // delay in between reads for stability
 }
 // Je heller, desto niedriger der Dunkelheitswert
 // Je wärmer,desto höher analogValue1

Sorry for the german descriptions but the are not important for my problem.

My problem is that when I upload the sketch to the arduino first everything seems to be working properly: If the temperature reading is above the threshold, the motor runs and opens the window and vise versa. But when the temperature stays above the threshold, the window “opens” again.
This behaviour would cause failure in the final project.
I tried creating a second Void loop, but as we all now, that doesent work.
I also thaught about end switches, but I dont really know how to incorporate them into my sketch and would like to avoid the constructional challenge of attaching them in a waterproof way.
All that leaves me wondering how all those other arduino greenhouse automations work.
If it where possiple to avoid using libarys I would prefer not to use them for the sake of simplicity.

(deleted)

Does that exempt it from the loop? Thank you for your quick response.

(deleted)

To put it another way, run the motor when the temperature [u]becomes[/u] above the threshold not when it [u]is[/u] above the threshold. In other words detect the [u]change[/u] of state rather than the current state.

Look at the StateChangeDetection example in the IDE.

Having said that, you would do better to use limit switches at each end of the travel and stop the motor when it reaches either end.

Thank you for your quick and helpflul responses. However, i have still got two quesions: 1. The example sketch works with a digital input. Does the same principal also apply when using analog inputs, and, if so, which changes do I need to make to the example sketch in order to use it for an anlalog input? 2. Why does this example sketch still need a delay and how do I best avoid its interferrance with the delay for measuring and printing the analog value into the serial monitor

Arduino_Automation: 1. The example sketch works with a digital input. Does the same principal also apply when using analog inputs,

The code in your Original Post has no digital input, only an analog input.

No matter whether you are using analog or digital inputs the concept of moving something when a value changes is the same

  1. Why does this example sketch still need a delay and how do I best avoid its interferrance with the delay for measuring and printing the analog value into the serial monitor

I presume the delay() is just there to make the LEDs flash.

The demo Several Things at a Time illustrates the use of millis() to manage timing without blocking. It may help with understanding the technique.

Have a look at Using millis() for timing. A beginners guide if you need more explanation.

...R

I changed the sketch according to the state change decection example:

// These constants won't change:
const int analogPin = A0;    // pin that the sensor is attached to
const int analogPin1 = A1;    // pin that the sensor is attached to
const int ledPin = 9;       // pin that the LED is attached to
const int ledPin1 = 8;       // pin that the LED is attached 
const int threshold = 350;   // an arbitrary threshold level that's in the range of the analog input
const int threshold1 = 145;   // an arbitrary threshold level that's in the range of the analog input

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
   pinMode(ledPin1, OUTPUT);
  // initialize serial communications:
  Serial.begin(9600);
}

void loop() {
  // read the value of the potentiometer:
  int analogValue = analogRead(analogPin);
  int analogValue1 = analogRead(analogPin1);

  // if the analog value is high enough, turn on the LED:
  if (analogValue > threshold) {
    if (lastAnalogValue<threshold){
    digitalWrite(ledPin, HIGH);
    delay(4000);
    digitalWrite(ledPin, LOW);
    }
  } else {
    digitalWrite(ledPin, LOW);
  }
 if (analogValue < threshold) {
  if (lastAnalogValue>threshold){
    digitalWrite(ledPin1, HIGH);
    delay(4000);
    digitalWrite(ledPin1, LOW);
  }
     } else {
       digitalWrite(ledPin1, LOW);
        }
  // Temperatur in Spannung ausrechnen
  float voltage = (analogValue1/1024.0) * 5.0;
  //Temperatur in °C ausrechnen
  float temperature = (voltage - .5) * 100;
 
  // print the analog value:
 Serial.println("Dunkelheit ADC");
  Serial.println(analogValue);
  Serial.println("Temperatur ADC");
    Serial.println(analogValue1);
   Serial.println("Temperatur in °C");
    Serial.println(temperature);
      Serial.println("--------------------------------------------------------------  10s Delay");
  delay(10000);        // delay in between reads for stability
  lastAnalogValue=analogValue;
 }
 // Je heller, desto niedriger ist der Dunkelheit- Wert
 // Je wärmer,desto höher analogValue1

But I am getting a compiling error due to the folling line:
lastAnalogValue=analogValue;
The error says:
“‘lastAnalogValue’ was not declared in this scope”.
So I checked the example sketch in order to find out what I did wrong.
The line missing in my sketch seems to be the following:
int lastButtonState = 0; // previous state of the button
However, as my sensor value is not digital, I am not sure what to replace the 0 with.

I am not sure what to replace the 0 with.

Just use 0

Arduino_Automation: The error says: "'lastAnalogValue' was not declared in this scope". So I checked the example sketch in order to find out what I did wrong. The line missing in my sketch seems to be the following: int lastButtonState = 0; // previous state of the button However, as my sensor value is not digital, I am not sure what to replace the 0 with.

You are getting the error because you are trying to use a variable called lastAnalogValue which you have not defined at the top of your program. In C++ all variable must be defined before they can be used.

I can't see the line

int lastButtonState = 0;

anywhere in your program so I don't understand why you are asking about it.

You need to add this line at the top of your program after the line const int threshold1 = 145;

int lastAnalogValue = 0;

You may wish to replace the 0 with one of your threshold values.

...R

So, thanks to your help I fixed the comliling error using just the line from the example.
I also changed my sketch so that the temperature value and threshold are in °C.
So it now looks like this:

// These constants won't change:
const int analogPin = A0;    // pin that the sensor is attached to
const int analogPin1 = A1;    // pin that the sensor is attached to
const int ledPin = 9;       // pin that the LED is attached to
const int ledPin1 = 8;       // pin that the LED is attached 
const int threshold = 20;   // Temperatur threshold
const int threshold1 = 145;   // an arbitrary threshold level that's in the range of the analog input

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
   pinMode(ledPin1, OUTPUT);
  // initialize serial communications:
  Serial.begin(9600);
}

void loop() {
  // read the value of the potentiometer:
  int analogValue = analogRead(analogPin);
  int analogValue1 = analogRead(analogPin1);
  int lastAnalogValue = 0;     // previous state of the button
  //Temperatur in Spannung umrechnen
  float voltage = (analogValue1/1024.0) * 5.0;
  //Temperatur in °C ausrechnen
  float temperature = (voltage - .5) * 100;

  // if the analog value is high enough, turn on the LED:
  if (temperature > threshold) {
    if (lastAnalogValue<threshold){
    digitalWrite(ledPin, HIGH);
       Serial.println("Fenster öffnet");
    delay(4000);
    digitalWrite(ledPin, LOW);
   }
  } else {
    digitalWrite(ledPin, LOW);
     Serial.println("Fenster öffnet nicht");
  }
 if (temperature < threshold) {
  if (lastAnalogValue>threshold){
    digitalWrite(ledPin1, HIGH);
       Serial.println("Fenster schließt");
    delay(4000);
    digitalWrite(ledPin1, LOW);
  }
     } else {
       digitalWrite(ledPin1, LOW);
        Serial.println("Fenster schließt nicht");
        }
  // print the analog value:
 Serial.println("Dunkelheit ADC");
  Serial.println(analogValue);
  Serial.println("Temperatur ADC");
    Serial.println(analogValue1);
   Serial.println("Temperatur in °C");
    Serial.println(temperature);
      Serial.println("--------------------------------------------------------------  10s Delay");
  delay(10000);        // delay in between reads for stability
  lastAnalogValue=temperature;
 }
 // Je heller, desto niedriger ist der Dunkelheit- Wert
 // Je wärmer,desto höher temperature1

The only problem is that the window still “opens” again.
Looking at my sketch I realized that if I have two if- statements, I also need two else statements.
But how do I implement them, given that they are completeley seperated from the two if- statements with {} ?

Update:
I “solved” the Problem that I thaugt I had, only to see that it was not the problem.
I used “&&” instead of two if- statements:

// These constants won't change:
const int analogPin = A0;    // pin that the sensor is attached to
const int analogPin1 = A1;    // pin that the sensor is attached to
const int ledPin = 9;       // pin that the LED is attached to
const int ledPin1 = 8;       // pin that the LED is attached 
const int threshold = 20;   // Temperatur threshold
const int threshold1 = 145;   // an arbitrary threshold level that's in the range of the analog input

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
   pinMode(ledPin1, OUTPUT);
  // initialize serial communications:
  Serial.begin(9600);
}

void loop() {
  // read the value of the potentiometer:
  int analogValue = analogRead(analogPin);
  int analogValue1 = analogRead(analogPin1);
  int lastAnalogValue = 0;     // previous state of the button
  //Temperatur in Spannung umrechnen
  float voltage = (analogValue1/1024.0) * 5.0;
  //Temperatur in °C ausrechnen
  float temperature = (voltage - .5) * 100;

  // if the analog value is high enough, turn on the LED:
  if (temperature > threshold && lastAnalogValue<threshold){ 
    digitalWrite(ledPin, HIGH);
       Serial.println("Fenster öffnet");
    delay(4000);
    digitalWrite(ledPin, LOW);
   }else {
    digitalWrite(ledPin, LOW);
     Serial.println("Fenster öffnet nicht");

  }
 if (temperature < threshold && lastAnalogValue>threshold) {
   digitalWrite(ledPin1, HIGH);
       Serial.println("Fenster schließt");
    delay(4000);
    digitalWrite(ledPin1, LOW);
  
     } else {
       digitalWrite(ledPin1, LOW);
        Serial.println("Fenster schließt nicht");
        }
  // print the analog value:
 Serial.println("Dunkelheit ADC");
  Serial.println(analogValue);
  Serial.println("Temperatur ADC");
    Serial.println(analogValue1);
   Serial.println("Temperatur in °C");
    Serial.println(temperature);
      Serial.println("--------------------------------------------------------------  10s Delay");
  delay(10000);        // delay in between reads for stability
  lastAnalogValue=temperature;
 }
 
 // Je heller, desto niedriger ist der Dunkelheit- Wert
 // Je wärmer,desto höher temperature

So, at that point, I not only dont know how to solve the problem, I dont even know what is the problem.
Because, at least to me, the sketch seems to be logically correct.

See if this works better (or worse) :slight_smile:

// These constants won't change:
const int analogPin = A0;    // pin that the sensor is attached to
const int analogPin1 = A1;    // pin that the sensor is attached to
const int ledPin = 9;       // pin that the LED is attached to
const int ledPin1 = 8;       // pin that the LED is attached
const int threshold = 20;   // Temperatur threshold
const int threshold1 = 145;   // an arbitrary threshold level that's in the range of the analog input
bool windowOpen = false;

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
   pinMode(ledPin1, OUTPUT);
  // initialize serial communications:
  Serial.begin(9600);
}

void loop() {
  // read the value of the potentiometer:
  int analogValue = analogRead(analogPin);
  int analogValue1 = analogRead(analogPin1);
  int lastAnalogValue = 0;     // previous state of the button
  //Temperatur in Spannung umrechnen
  float voltage = (analogValue1/1024.0) * 5.0;
  //Temperatur in °C ausrechnen
  float temperature = (voltage - .5) * 100;

  // if the analog value is high enough, turn on the LED:
  if (temperature > threshold && windowOpen == false){
    if (lastAnalogValue<threshold){
    digitalWrite(ledPin, HIGH);
       Serial.println("Fenster öffnet");
    delay(4000);
    windowOpen = true;
    digitalWrite(ledPin, LOW);
   }
  } else {
    digitalWrite(ledPin, LOW);
     Serial.println("Fenster öffnet nicht");
  }
 if (temperature < threshold && windowOpen == true) {
  if (lastAnalogValue>threshold){
    digitalWrite(ledPin1, HIGH);
       Serial.println("Fenster schließt");
    delay(4000);
  windowOpen = false;
    digitalWrite(ledPin1, LOW);
  }
     } else {
       digitalWrite(ledPin1, LOW);
        Serial.println("Fenster schließt nicht");
        }
  // print the analog value:
 Serial.println("Dunkelheit ADC");
  Serial.println(analogValue);
  Serial.println("Temperatur ADC");
    Serial.println(analogValue1);
   Serial.println("Temperatur in °C");
    Serial.println(temperature);
      Serial.println("--------------------------------------------------------------  10s Delay");
  delay(10000);        // delay in between reads for stability
  lastAnalogValue=temperature;
 }
 // Je heller, desto niedriger ist der Dunkelheit- Wert
 // Je wärmer,desto höher temperature1

You did not put this line where I told you to

int lastAnalogValue = 0;

The way you have it the value gets reset to 0 every time loop() repeats. Either move it to the top of the program to make it a global variable or change the present line to

static int lastAnalogValue = 0;

See how much easier it is to read your code when it is indented consistently. Use the AutoFormat tool.

// These constants won't change:
const int analogPin = A0;    // pin that the sensor is attached to
const int analogPin1 = A1;    // pin that the sensor is attached to
const int ledPin = 9;       // pin that the LED is attached to
const int ledPin1 = 8;       // pin that the LED is attached
const int threshold = 20;   // Temperatur threshold
const int threshold1 = 145;   // an arbitrary threshold level that's in the range of the analog input

void setup() {
    // initialize the LED pin as an output:
    pinMode(ledPin, OUTPUT);
    pinMode(ledPin1, OUTPUT);
    // initialize serial communications:
    Serial.begin(9600);
}

void loop() {
    // read the value of the potentiometer:
    int analogValue = analogRead(analogPin);
    int analogValue1 = analogRead(analogPin1);
    int lastAnalogValue = 0;     // previous state of the button
    //Temperatur in Spannung umrechnen
    float voltage = (analogValue1/1024.0) * 5.0;
    //Temperatur in °C ausrechnen
    float temperature = (voltage - .5) * 100;

    // if the analog value is high enough, turn on the LED:
    if (temperature > threshold && lastAnalogValue<threshold){
        digitalWrite(ledPin, HIGH);
        Serial.println("Fenster öffnet");
        delay(4000);
        digitalWrite(ledPin, LOW);
    }
    else {
        digitalWrite(ledPin, LOW);
        Serial.println("Fenster öffnet nicht");
    }
    
    if (temperature < threshold && lastAnalogValue>threshold) {
        digitalWrite(ledPin1, HIGH);
        Serial.println("Fenster schließt");
        delay(4000);
        digitalWrite(ledPin1, LOW);
 
    } 
    else {
        digitalWrite(ledPin1, LOW);
        Serial.println("Fenster schließt nicht");
    }
        // print the analog value:
    Serial.println("Dunkelheit ADC");
    Serial.println(analogValue);
    Serial.println("Temperatur ADC");
    Serial.println(analogValue1);
    Serial.println("Temperatur in °C");
    Serial.println(temperature);
    Serial.println("--------------------------------------------------------------  10s Delay");
    delay(10000);        // delay in between reads for stability
    lastAnalogValue=temperature;
 }
 
 // Je heller, desto niedriger ist der Dunkelheit- Wert
 // Je wärmer,desto höher temperature

…R

In my opinion even better with each { and } alone on its own line, although opinions vary

// These constants won't change:
const int analogPin = A0;    // pin that the sensor is attached to
const int analogPin1 = A1;    // pin that the sensor is attached to
const int ledPin = 9;       // pin that the LED is attached to
const int ledPin1 = 8;       // pin that the LED is attached
const int threshold = 20;   // Temperatur threshold
const int threshold1 = 145;   // an arbitrary threshold level that's in the range of the analog input

void setup()
{
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  pinMode(ledPin1, OUTPUT);
  // initialize serial communications:
  Serial.begin(9600);
}

void loop()
{
  // read the value of the potentiometer:
  int analogValue = analogRead(analogPin);
  int analogValue1 = analogRead(analogPin1);
  int lastAnalogValue = 0;     // previous state of the button
  //Temperatur in Spannung umrechnen
  float voltage = (analogValue1 / 1024.0) * 5.0;
  //Temperatur in °C ausrechnen
  float temperature = (voltage - .5) * 100;
  // if the analog value is high enough, turn on the LED:
  if (temperature > threshold && lastAnalogValue < threshold)
  {
    digitalWrite(ledPin, HIGH);
    Serial.println("Fenster öffnet");
    delay(4000);
    digitalWrite(ledPin, LOW);
  }
  else
  {
    digitalWrite(ledPin, LOW);
    Serial.println("Fenster öffnet nicht");
  }
  if (temperature < threshold && lastAnalogValue > threshold)
  {
    digitalWrite(ledPin1, HIGH);
    Serial.println("Fenster schließt");
    delay(4000);
    digitalWrite(ledPin1, LOW);
  }
  else
  {
    digitalWrite(ledPin1, LOW);
    Serial.println("Fenster schließt nicht");
  }
  // print the analog value:
  Serial.println("Dunkelheit ADC");
  Serial.println(analogValue);
  Serial.println("Temperatur ADC");
  Serial.println(analogValue1);
  Serial.println("Temperatur in °C");
  Serial.println(temperature);
  Serial.println("--------------------------------------------------------------  10s Delay");
  delay(10000);        // delay in between reads for stability
  lastAnalogValue = temperature;
}

// Je heller, desto niedriger ist der Dunkelheit- Wert
// Je wärmer,desto höher temperature

I have the IDE Auto Format set up to do this and also to remove blank lines within functions.

Should I also use "const int" when putting it above the sketch?

Arduino_Automation: Should I also use "const int" when putting it above the sketch?

Only if its value is constant, which it isn't

I put it above, so that my sketch now looks like this:

// These constants won't change:
const int analogPin = A0;    // pin that the sensor is attached to
const int analogPin1 = A1;    // pin that the sensor is attached to
const int ledPin = 9;       // pin that the LED is attached to
const int ledPin1 = 8;       // pin that the LED is attached
const int threshold = 20;   // Temperatur threshold
const int threshold1 = 145;   // an arbitrary threshold level that's in the range of the analog input
int lastAnalogValue = 0;     // previous state of the button
void setup() {
    // initialize the LED pin as an output:
    pinMode(ledPin, OUTPUT);
    pinMode(ledPin1, OUTPUT);
    // initialize serial communications:
    Serial.begin(9600);
}

void loop() {
    // read the value of the potentiometer:
    int analogValue = analogRead(analogPin);
    int analogValue1 = analogRead(analogPin1);
    int lastAnalogValue = 0;     // previous state of the button
    //Temperatur in Spannung umrechnen
    float voltage = (analogValue1/1024.0) * 5.0;
    //Temperatur in °C ausrechnen
    float temperature = (voltage - .5) * 100;

    // if the analog value is high enough, turn on the LED:
    if (temperature > threshold && lastAnalogValue<threshold){
        digitalWrite(ledPin, HIGH);
        Serial.println("Fenster öffnet");
        delay(4000);
        digitalWrite(ledPin, LOW);
    }
    else {
        digitalWrite(ledPin, LOW);
        Serial.println("Fenster öffnet nicht");
    }
    
    if (temperature < threshold && lastAnalogValue>threshold) {
        digitalWrite(ledPin1, HIGH);
        Serial.println("Fenster schließt");
        delay(4000);
        digitalWrite(ledPin1, LOW);
 
    } 
    else {
        digitalWrite(ledPin1, LOW);
        Serial.println("Fenster schließt nicht");
    }
        // print the analog value:
    Serial.println("Dunkelheit ADC");
    Serial.println(analogValue);
    Serial.println("Temperatur ADC");
    Serial.println(analogValue1);
    Serial.println("Temperatur in °C");
    Serial.println(temperature);
    Serial.println("--------------------------------------------------------------  10s Delay");
    delay(10000);        // delay in between reads for stability
    lastAnalogValue=temperature;
 }
 
 // Je heller, desto niedriger ist der Dunkelheit- Wert
 // Je wärmer,desto höher temperature

But I am still having the issue of “re”-opening

Arduino_Automation:
I put it above, so that my sketch now looks like this:

You did not delete the line in loop() when you put the definition at the top so now you have two variables with the same name and, within loop(), only the local version is used.

…R

I believe @Robin2 meant for you to move the line:

int lastAnalogValue = 0;

To the top of program and delete it from where it was (line 21 now).