Использование одной и той же переменной между операторами if в loop()

Интересно, есть ли хороший способ использовать одно и то же значение переменной между двумя разными операторами if в цикле().

В разделе серводвигателя кода я хочу использовать значение из первого if-оператора RewardTime в следующем if-операторе RewardTime. До сих пор я не могу найти способ сделать это. (Поскольку сейчас между этими переменными нет связи, время вознаграждения остается равным 0).

Я был бы признателен за определенное руководство в этом вопросе.

#include <Servo.h> // Библиотека, необходимая для серводвигателя (обязательно скачайте, если ее нет в библиотеке)
#include <Button.h> // Библиотека, необходимая для микропереключателя (обязательно скачайте, если ее нет в библиотеке)

// ПАРАМЕТРЫ
// СКОПИРУЙТЕ ЭТИ ЗНАЧЕНИЯ В КОД ОБРАБОТКИ ВРУЧНУЮ
// Пояснение: Для предотвращения возможного переполнения Arduino-обработки. Не нужно слишком много информационного потока между Arduino и Обработкой. 
const float Scale = 1 * 1000; // миллисекунды
const float Base = 1 * 1000; // миллисекунды

Servo Servo1;
int servoPin = 9; // Объявить вывод сервопривода
Button button(7); // Объявить вывод микропереключателя (может варьироваться от настройки к настройке)

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); // установите время дебоунса равным 100 миллисекундам.
}

void loop(){
   // МИКРОПЕРЕКЛЮЧАТЕЛЬ
   // Получить время начала и смещения, когда птица прилетает и покидает насест
   button.loop();
   if(button.isPressed())
    Serial.println(1);
   if(button.isReleased())
    Serial.println(0);

   // СЕРВОДВИГАТЕЛЬ
   // Получить время, когда кормушка закрыта (присутствует пища) и раскрыта (отсутствует пища)
    unsigned long currentMillis = millis();
    while (Serial.available() > 0) {
    unsigned long currentMillis = millis();
   if (Serial.read() == '\n') { //Когда есть песня
     //Serial.println(2); // Еда раскрыта
     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 градусов
    unsigned long secondCurrentMillis = millis();
    if (secondCurrentMillis - previousMillis > RewardTime) { // ИСПОЛЬЗУЙТЕ ВЫШЕУПОМЯНУТОЕ RewardTime ЗДЕСЬ
      switching = true;
      previousMillis = secondCurrentMillis;
      if (State == LOW)
        State = HIGH;
      else
        State = LOW;
    }
  }
  if(State == LOW && switching == true){
    Servo1.write(90); // 90 градусов
    switching = false;
    //Serial.println(3); // Еда покрыта
    }
}

, 👍2


2 ответа


1

Сделайте переменную глобальной, таким образом, выведите ее за пределы функции цикла; кроме того, вам больше не нужно ключевое слово static.

float RewardTime = 0;

Чем внутри вашего первого оператора if, удалите ключевые слова static float:

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

Некоторые другие советы:

  • обычно локальные переменные не начинаются с заглавной буквы (поэтому rewardTime похож на большинство соглашений о кодировании).
  • Всегда используйте скобки.

    if (Состояние == НИЗКОЕ) Состояние = ВЫСОКОЕ; ещё Состояние = НИЗКОЕ;

Изменение на:

  if (State == LOW)
  {
    State = HIGH;
  }
  else
  {
    State = LOW;
  }
  • Однако, чтобы сделать его более простым, используйте тернарный оператор, вы можете изменить его на:

    Состояние = (Состояние == НИЗКОЕ ? ВЫСОКИЙ : НИЗКИЙ);

Что значит: если какое-то условие ? Сделай это : Еще сделай это;

,

HIGH / LOW и true / false идентичны, поэтому State = ! Состояние;достаточно., @DataFiddler

@DataFiddler Но вы не должны зависеть от значений внутри библиотеки. Предположим, в будущем они изменят значения на 20 и 30 вместо true/false. Если API Arduino предназначался для логического значения, они должны были использовать логический тип., @Michel Keijzers

если они когда-нибудь изменят определение ВЫСОКОГО и НИЗКОГО, я перестану использовать Arduino. Они даже не решаются изменить тип возврата digitalRead, что является хорошим решением., @DataFiddler

@DataFiddler ... хорошая мысль, и я полностью согласен, что это сломает многие скетчи. Но они действительно должны использовать логическое значение в качестве типа входного аргумента, или перечисление EPinState (LOW, HIGH), или что-то в этом роде., @Michel Keijzers

Этот вопросительный знак называется оператором Элвиса для людей, которые не знают, он похож на if else, но с некоторым компилятором это может быть быстрее (это происходит на intel, например, с инструкцией cmov)., @alessandromrc

@alessandromrc Я думаю, что оператор Элвиса действительно является более неформальным именем (спасибо за добавление). Кстати, я думаю, что это вообще не очень хорошая идея писать по соображениям производительности, если это не известно заранее или когда это необходимо (впоследствии), он просто читается легче (если он помещается в одной строке в основном)., @Michel Keijzers


1

Поскольку вы определили его в первом операторе if, он является только "in-scope" или определен в этом блоке. Чтобы сделать его видимым для обоих операторов if, определите его в следующем внешнем блоке, содержащем оба оператора if - в данном случае где-то между void loop(){ и if (Serial.read()...

,