System to water plants: Code troubleshooting

Hello all, could you please help me to understand my mistake? I bought a semi-commercial shield and
edited the scrip they provided. The problem seems to be in missing bracket but I’m pretty sure I closed everything. I would be happy to hear any feedback from you.

    // set all moisture sensors PIN ID
    int moisture1 = A0;
    int moisture2 = A1;
    int moisture3 = A2;
    int moisture4 = A3;

    // set water relays
    int relay1 = 3;
    int relay2 = 4;
    int relay3 = 5;
    int relay4 = 6;

    //init valve nr
    int x = 0;
    // set water pump PIN ID
    int pump = 2;


    //Safety function - closing all walves
    void closeAll() {     // turn pump & valves off just to be sure.
    Serial.println("Closing pump + valves!");
    digitalWrite(pump, LOW);
    digitalWrite(relay1, LOW);
    digitalWrite(relay2, LOW);
    digitalWrite(relay3, LOW);
    digitalWrite(relay4, LOW);
    }

    //Water dried plant
    void waterPlant(int x) {
    Serial.print("Opening: ");
    Serial.print(x);
    digitalWrite(x, HIGH);    //Open valve x ==> x will contain value of correct relay[1-4]
    delay(500);               //We wait 0.5 seconds before opening pump so we are sure relay is open.
    digitalWrite(pump, HIGH); //Open pump for 1,5 seconds
    delay(1500);
    digitalWrite(pump, LOW);  //Close pump
    delay(500);
    digitalWrite(x, LOW);
    closeAll();               //Make sure all valves are closed again.
    }




    void setup() {

    // declare relay as outputs
    pinMode(relay1, OUTPUT);
    pinMode(relay2, OUTPUT);
    pinMode(relay3, OUTPUT);
    pinMode(relay4, OUTPUT);
    pinMode(pump, OUTPUT);    // declare pump as output

    Serial.begin(9600);
    }


///////////////////////////////////////////////// MAIN /////////////////////////////////////////////////
    void loop() {

    //print sensor values
    Serial.print(F("Sensor 1: "));
    Serial.println(analogRead(moisture1));
    Serial.print(F("Sensor 2: "));
    Serial.println(analogRead(moisture2));
    Serial.print(F("Sensor 3: "));
    Serial.println(analogRead(moisture3));
    Serial.print(F("Sensor 4: "));
    Serial.println(analogRead(moisture4));
    Serial.println("Check moisture");

      //Moisture checkup function to see if plants need watering
      void checkMoisture() {
        
      if (analogRead(moisture1) <= 450) {
      waterPlant(relay1);
      }

      if (analogRead(moisture2) <= 450) {
      waterPlant(relay2);
      }

      if (analogRead(moisture3) <= 450) {
      waterPlant(relay3);
      }

      if (analogRead(moisture4) <= 450) {
      waterPlant(relay4);
      }

      closeAll()
          
      
      // wait 8 hours and repeat the process
      Serial.println("Waiting 8 hours \n ++++++++++++++ END +++++++++++++ \n"); 
      delay(28800000);
      }
    }

Error codes:
Arduino: 1.8.5 (Windows 10), Board: “Arduino/Genuino Uno”
In function ‘void loop()’:
watersys:74: error: a function-definition is not allowed here before ‘{’ token

  • void checkMoisture() {*
  • ^*
    watersys:99: error: expected ‘}’ at end of input
  • }*
  • ^*
    exit status 1
    a function-definition is not allowed here before ‘{’ token
    This report would have more information with
    “Show verbose output during compilation”
    option enabled in File → Preferences.

Thank you in advance for any hints.
Best, Tech.

There is no closing bracket for the loop function.

A very useful troubleshooting tool is to do a Tools > Auto Format in the Arduino IDE and then check the resulting indentation to see if it matches your expected program structure. I think that will make the issue quite obvious.

Another feature of the Arduino IDE is that if you place the cursor next to one bracket, a box appears around the matching bracket. In the case of the cursor being next to a closing bracket where the opening bracket is off the screen, it will display that line in a tooltip after a short delay.

Thanks for fast replies @pert and @wildbill

I already tried Autoformat and manual placing the cursor on all brackets.

I believe my last } is closing loop function.

Techion:
I already tried Autoformat

The code you posted definitely was not auto formatted.

Techion:
I believe my last } is closing loop function.

You're right, but is that how it should be? Take a close look at the code between the opening and closing brackets of loop(), remembering that you should not define a function inside of another function.

True, every '{' is paired with a '}'. But you're still trying to define 'checkMoisture()' inside of 'loop()'.

wildbill:
There is no closing bracket for the loop function.

I can see one - line 99, but the problem is the "Moisture checkup function" is being declared as a function (void checkMoisture) when it is actually part of and inside void loop().

Remove line 74 completely. (comment it out for now, so the next 2 solutions don't move line numbers).

Line 92 needs a closing ";" after CloseAll()

Line 99 is a closing "}", but nothing open, delete it.

Make those changes and your sketch compiles with zero errors or warnings

@pert @gfvalvo @daba

Thanks a lot! I simply didn’t know that I cannot define functions in void loop.
I re-arranged it a bit and declared this function outside the loop. It compiles. Hopefully it will fly now :slight_smile:

Thanks for all your time and help!

The code just for the sake of any followers:

// set all moisture sensors PIN ID
int moisture1 = A0;
int moisture2 = A1;
int moisture3 = A2;
int moisture4 = A3;

// set water relays
int relay1 = 3;
int relay2 = 4;
int relay3 = 5;
int relay4 = 6;

//init valve nr
int x = 0;
// set water pump PIN ID
int pump = 2;


//Safety function - closing all walves and pump
void closeAll() {
  Serial.println("Closing pump + valves!");
  digitalWrite(pump, LOW);
  digitalWrite(relay1, LOW);
  digitalWrite(relay2, LOW);
  digitalWrite(relay3, LOW);
  digitalWrite(relay4, LOW);
}

//Water dried plant
void waterPlant(int x) {
  Serial.print("Opening: ");
  Serial.print(x);
  digitalWrite(x, HIGH);    //Open valve x ==> x will contain value of correct relay[1-4]
  delay(500);               //We wait 0.5 seconds before opening pump so we are sure relay is open.
  digitalWrite(pump, HIGH); //Open pump for 1,5 seconds
  delay(1500);
  digitalWrite(pump, LOW);  //Close pump
  delay(500);
  digitalWrite(x, LOW);
  closeAll();               //Make sure all valves are closed again.
}

//Moisture checkup function to see if plants need watering
void checkMoisture() {

  if (analogRead(moisture1) <= 450) {
    waterPlant(relay1);
  }

  if (analogRead(moisture2) <= 450) {
    waterPlant(relay2);
  }

  if (analogRead(moisture3) <= 450) {
    waterPlant(relay3);
  }

  if (analogRead(moisture4) <= 450) {
    waterPlant(relay4);
  }
}

void setup() {

  // declare relay as outputs
  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
  pinMode(relay3, OUTPUT);
  pinMode(relay4, OUTPUT);
  pinMode(pump, OUTPUT);    // declare pump as output

  Serial.begin(9600);
}


///////////////////////////////////////////////// MAIN /////////////////////////////////////////////////
void loop() {

  //print sensor values
  Serial.print(F("Sensor 1: "));
  Serial.println(analogRead(moisture1));
  Serial.print(F("Sensor 2: "));
  Serial.println(analogRead(moisture2));
  Serial.print(F("Sensor 3: "));
  Serial.println(analogRead(moisture3));
  Serial.print(F("Sensor 4: "));
  Serial.println(analogRead(moisture4));
  Serial.println("Check moisture");

  //Calling functions
  checkMoisture();
  closeAll();

  // wait 8 hours and check moisture sensors again
  Serial.println("Waiting 8 hours \n ++++++++++++++ END +++++++++++++ \n");
  delay(28800000);

}

You might want to consider taking moisture readings more frequently than every 8 hours.

One single reading could be subjected to all sorts of error due to noise, wind in the wrong direction, an "R" in the month, etc.

What I would probably do is wait 7 hours, then sample into an array[10] every 6 minutes. Use an average of the array as the "filtered" value.

In fact a better approach would be to average, say, only the middle 6 or 8 of the last 10 readings, after sorting them into magnitude order.

That way you would be automatically rejecting any spurious high or low readings.

Since you have plenty of time on your hands, a simple but inefficient "bubble-sort" would fit the bill.

Go through the array, inspecting each value against the next one, swapping them if reading[n] > reading[n+1]. Do this the same number of times as there are elements in the array, and the array would be sorted.

@daba

This is good idea! The reason of this project is that I'm frequently leaving home and all my flowers are dying. I will test this code for a bit. If it will not work as intented I follow way you pointed :slight_smile:

Thanks again for help! I