Невозможно выйти из цикла while

Я написал код, который позволяет двум сервоприводам работать. Последовательность работы такова: первый сервопривод должен начать вращение в течение 2 циклов, затем остановиться, а второй сервопривод должен начать вращение еще в течение 2 циклов, а затем отсоединить их оба. Я так старался остановить петлю, но она застряла внутри и не вылезала. Она продолжала вращаться сначала сначала, потом во вторую, потом снова в первую и так далее.

void loop() {

  const int totalLoopTime = 32001; // Время в миллисекундах для всего цикла (при необходимости измените)

  // Управляющие переменные
  bool enterServo1Loop = true;
  bool enterServo2Loop = false;
  int currentCycle1 = 0;
  int currentCycle2 = 0;

  // Целевые циклы
  const int cycles = 2; // Отрегулируйте это значение по мере необходимости

  // Параметры сервоуправления
  const int servoPin1 = 9;    // При необходимости отрегулируйте номера контактов
  const int servoPin2 = 6;
  const int openPosition = 45; // Отрегулируйте положение открытия сервопривода
  const int closePosition = 135;  // Отрегулируйте закрытое положение сервопривода
  const int openTime = 4000;   // Настройка времени открытия в миллисекундах
  const int closeTime = 4000;  // Настроить время закрытия в миллисекундах


 


  while (enterServo1Loop || enterServo2Loop) {

    // Сервопривод управления 1
    if (enterServo1Loop && currentCycle1 < cycles) {
      servo1.attach(servoPin1);
      servo1.write(openPosition);
      delay(openTime);
      servo1.write(closePosition);
      delay(closeTime);
      currentCycle1++;
    } else if (enterServo1Loop) { // Отсоединение после завершения циклов
      servo1.detach();
      enterServo1Loop = false;
      enterServo2Loop = true; // Запустить цикл Servo 2 после завершения Servo 1
      Serial.print("Time servo 1: ");  // Добавьте пробел после двоеточия для удобства чтения
      Serial.println(millis());
      

    }

    // Управление сервоприводом 2
    if (enterServo2Loop && currentCycle2 < cycles) {
      servo2.attach(servoPin2);
      servo2.write(openPosition);
      delay(openTime);
      servo2.write(closePosition);
      delay(closeTime);
      currentCycle2++;
    } else if (enterServo2Loop) { // Отсоединение после завершения циклов
      servo2.detach();
      enterServo2Loop = false;
      enterServo1Loop = false;
      servo1.detach();

      Serial.print("Time servo 2: ");  // Добавьте пробел после двоеточия для удобства чтения
      Serial.println(millis());
    
    }
  
   // если (миллис()>=50000) {
     // сервопривод1.detach();
       // сервопривод2.отсоединить(); }
  }

  if (millis() >= loopStartTime + totalLoopTime) {
    servo1.detach();  // Отсоединяем оба сервопривода по достижении лимита времени
    servo2.detach();
    bool enterServo1Loop = false;
    bool enterServo2Loop = false;
      Serial.print("Time last: ");  // Добавьте пробел после двоеточия для удобства чтения
      Serial.println(millis());

    return;  // Немедленно выйти из цикла
  }


  servo1.detach(); 
  servo2.detach();
} 

, 👍1


2 ответа


1

Весь ваш код находится внутри функции loop(). Эта функция — как следует из ее названия — вызывается снова и снова в цикле. Когда вы вызываете return внутри этой функции, вы покидаете функцию. Но почти сразу же функция loop() вызывается снова, начиная ваш код заново.

У вас есть два варианта:

  • Замените оператор return бесконечным циклом, который ничего не делает. Что-то вроде:

      while(true);
    
  • Переместите весь ваш код в функцию setup(). Эта функция вызывается ядром Arduino только один раз при запуске. Оставьте функцию loop() пустой.

Оба варианта фактически одинаковы: выполнение вашего кода после запуска и затем бесконечный пустой цикл. Первый вариант — это то, как люди делают это вне фреймворка Arduino. Второй вариант — это способ Arduino сделать это. Для удобства чтения я бы предложил второй вариант.

,

0

В обычном программировании на языке C точкой входа является main(). То есть main() вызывается один раз, и выполнение продолжается оттуда. Если ваша программа была переименована в main() и помещена в обычную среду программирования на языке C, у нее есть все шансы работать так, как и ожидалось.

В парадигме Arduino есть 2 точки входа. Функция setup(), которая вызывается один раз. И функция loop(), которая вызывается повторно. Предполагается, что последний метод проще для понимания начинающими программистами.

То, что вы сделали, это создали и инициализировали ваши ключевые переменные, которые отслеживают состояние вашей программы в функции Arduino loop(). Эта функция будет вызываться снова и снова включенным программным обеспечением Arduino, загружаемым каждый раз вместе с вашим программным обеспечением в процессор. Это приводит к тому, что ваши ключевые переменные будут пересоздаваться и повторно инициализироваться каждый раз при вызове функции loop().

Рассмотрите возможность переноса создания и инициализации ключевых переменных в функцию setup(). Таким образом, они будут созданы и инициализированы только один раз.

setup()
{
  // Переместите сюда ваш одноразовый код инициализации из вашего
  // существующая функция loop(),
  //
  // так:

  const int totalLoopTime = 32001; // Время в миллисекундах для всего цикла (при необходимости измените)

  // Управляющие переменные
  bool enterServo1Loop = true;
  bool enterServo2Loop = false;
  int currentCycle1 = 0;
  int currentCycle2 = 0;

  // Целевые циклы
  const int cycles = 2; // Отрегулируйте это значение по мере необходимости

  // Параметры сервоуправления
  const int servoPin1 = 9;    // При необходимости отрегулируйте номера контактов
  const int servoPin2 = 6;
  const int openPosition = 45; // Отрегулируйте положение открытия сервопривода
  const int closePosition = 135;  // Отрегулируйте закрытое положение сервопривода
  const int openTime = 4000;   // Настройка времени открытия в миллисекундах
  const int closeTime = 4000;  // Настроить время закрытия в миллисекундах
}

loop()
{
  // Оставьте оставшуюся часть кода в функции loop():

  while (enterServo1Loop || enterServo2Loop) {

   // Сервопривод управления 1
   if (enterServo1Loop && currentCycle1 < cycles) {
   // ... остальная часть вашего кода.
}
,