2

I wonder if there is a good way to use the same variable value between two different if-statements within the loop().

Within the Servomotor section of the code, I want to use the value from the first if-statement's RewardTime within the next if-statement's RewardTime. Thus far, I cannot find a way to do it. (Since there is no communication between these variables right now, the RewardTime remains 0).

I'd appreciate a certain guidance in this matter.

#include <Servo.h> // Library required for the servomotor (Make sure to download if not in the library)
#include <Button.h> // Library required for the microswitch (Make sure to download if not in the lbrary)

// PARAMETERS
// COPY THESE VALUES IN PROCESSING CODE MANUALLY
// Explanation: To prevent possible Arduino-Processing overflow. Do not want too much information flow between Arduino and Processing. 
const float Scale = 1 * 1000; // milliseconds
const float Base = 1 * 1000; // milliseconds

Servo Servo1;
int servoPin = 9; // Declare the Servo pin
Button button(7); // Declare the microswitch pin (Can be varied from setup to setup)

unsigned long previousMillis = 0;
bool switching = false;
int State = LOW; 

char BirdSings = 0;
//static float RewardTime = 0;

void setup() {
   Servo1.attach(servoPin);
   analogWrite(9, 0);
   Serial.begin(9600);
   button.setDebounceTime(100); // set debounce time to 100 milliseconds
}

void loop(){
   // MICROSWITCH
   // Get onset and offset times of when the bird arrives and leaves the perch
   button.loop();
   if(button.isPressed())
    Serial.println(1);
   if(button.isReleased())
    Serial.println(0);

   // SERVOMOTOR
   // Get times when the feeder is covered (food present) and uncovered (food not present)
    unsigned long currentMillis = millis();
    while (Serial.available() > 0) {
    unsigned long currentMillis = millis();
   if (Serial.read() == '\n') { // When there is a song
     //Serial.println(2); // Food is uncovered
     previousMillis = currentMillis; // 0 becomes the current milli 
     static float RewardTime = (Serial.parseFloat() * Scale) + Base; // CALCULATE THE RewardTime HERE
     Serial.println(RewardTime);
     if (State == LOW)
      State = HIGH;
     else
      State = LOW;
    }
   }

  if (State == HIGH && switching == false){
    Servo1.write(0); // 0 degree
    unsigned long secondCurrentMillis = millis();
    if (secondCurrentMillis - previousMillis > RewardTime) { // USE THE ABOVE RewardTime HERE
      switching = true;
      previousMillis = secondCurrentMillis;
      if (State == LOW)
        State = HIGH;
      else
        State = LOW;
    }
  }
  if(State == LOW && switching == true){
    Servo1.write(90); // 90 degrees
    switching = false;
    //Serial.println(3); // Food is covered
    }
}

2 Answers 2

1

Make the variable global, thus put it outside the loop function; also you don't need the static keyword anymore.

float RewardTime = 0;

Than inside your first if statement, remove the static float keywords:

RewardTime = (Serial.parseFloat() * Scale) + Base;

Some other tips:

  • normally local variables do not start with a capital (so rewardTime is like most coding conventions)
  • Always use brackets.

    if (State == LOW) State = HIGH; else State = LOW;

Change to:

  if (State == LOW)
  {
    State = HIGH;
  }
  else
  {
    State = LOW;
  }
  • However, to make it more simpler, use the ternary operator, you can change it to:

    State = (State == LOW ? HIGH : LOW);

Which means: if some condition ? Do this : Else do this;

6
  • HIGH / LOW and true / false are identical, so State = ! State;is sufficient. Dec 20, 2019 at 12:21
  • @DataFiddler But you shouldn't be dependent on the values inside a library. Suppose in future they will change the values to 20 and 30 instead of true/false. If the Arduino API intended a Boolean they should have used a Boolean type. Dec 20, 2019 at 12:32
  • 1
    if they ever change change the definition of HIGH and LOW, I will stop using Arduino. They even don't dare to change the return type of digitalRead, which is a good decision. Dec 20, 2019 at 12:42
  • @DataFiddler … good point, and I fully agree it would break many sketches. But they really should use a Boolean as input argument type, or an enumeration EPinState (LOW, HIGH) or something like that. Dec 20, 2019 at 12:44
  • 1
    That question mark is called Elvis operator for the people that doesn't know, it's similar as an if else but with some compiler it could be faster (This happens on intel for example with the cmov instruction) Jun 13, 2021 at 1:06
1

Since you defined it within the first if statement, it is only "in-scope" or defined within that block. To make it visible to both if statements, define it in the next outer block that contains both if statements - in this case, somewhere between void loop(){ and if (Serial.read()...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.