Можно ли сделать несколько функций loop() с помощью Arduino Uno?

У меня проблема. Я хочу сделать машину с мотором, передними и задними фонарями. Я хочу запускать их одновременно, но в разных циклах.

Это мой код.

const int red1 = 10;
const int red2 = 11;
const int blue1 = 12;
const int blue2 = 13;
const int front1 = 3;
const int front2 = 4;
const int back1 = 5;
const int back2 = 6;
const int enablePWMPin = 9;
const int controlPinA = 8;
const int controlPinB = 7;
int buzzer = A0;

void setup() {
  pinMode(red1, OUTPUT);
  pinMode(red2, OUTPUT);
  pinMode(blue1, OUTPUT);
  pinMode(blue2, OUTPUT);
  pinMode(front1, OUTPUT);
  pinMode(front2, OUTPUT);
  pinMode(back1, OUTPUT);
  pinMode(back2, OUTPUT);
  pinMode(enablePWMPin, OUTPUT);
  pinMode(controlPinA, OUTPUT);
  pinMode(controlPinB, OUTPUT);

  digitalWrite(enablePWMPin, LOW);
  digitalWrite(front1, LOW);
  digitalWrite(front2, LOW);
  digitalWrite(back1, LOW);
  digitalWrite(back2, LOW);
  digitalWrite(red1, LOW);
  digitalWrite(red2, LOW);
  digitalWrite(blue1, LOW);
  digitalWrite(blue2, LOW);
  noTone(buzzer);
}

void loop() {
  digitalWrite(enablePWMPin, HIGH);
  digitalWrite(controlPinA, HIGH);
  digitalWrite(controlPinB, LOW);
  delay(3000);
  digitalWrite(controlPinA, LOW);
  digitalWrite(controlPinB, HIGH);
  delay(3000);
} 

void loop() {
  digitalWrite(red1, HIGH);
  digitalWrite(red2, HIGH);
  digitalWrite(blue1, LOW);
  digitalWrite(blue2, LOW);
  delay(250);
  digitalWrite(red1, LOW);
  digitalWrite(red2, LOW);
  digitalWrite(blue1, HIGH);
  digitalWrite(blue2, HIGH);
  delay(250);
}

void loop() {
  int directionA = digitalRead(controlPinA);
  int directionB = digitalRead(controlPinB);
  if (directionA == HIGH && directionB == LOW) {
    digitalWrite(front1, HIGH);
    digitalWrite(front2, HIGH);
    digitalWrite(back1, LOW);
    digitalWrite(back2, LOW);
  } else if (directionA == LOW && directionB == HIGH) {
    digitalWrite(back1, HIGH);
    digitalWrite(back2, HIGH);
    digitalWrite(front1, LOW);
    digitalWrite(front2, LOW);
  } else {
    digitalWrite(front1, LOW);
    digitalWrite(front2, LOW);
    digitalWrite(back1, LOW);
    digitalWrite(back2, LOW);
  }
}

Я использую Arduino Uno. Могу ли я запустить все функции loop() одновременно?

, 👍1

Обсуждение

Просто попытка скомпилировать его должна дать вам ответ..., @jfpoilpret

Не с Uno, но это возможно с Due, @Greenonline


5 ответов


Лучший ответ:

9

Как уже говорили другие, нет, вы не можете иметь несколько функций цикла. Что вам нужно сделать, так это изменить свой подход так, чтобы каждая вещь, которую вы пытаетесь сделать, могла быть выполнена последовательно без блокировки (т. Е. Удалить использование функции задержки). Расширяя некоторые предложения JRobert, вот как я бы сделал так, чтобы эти функции "запускались одновременно":

void loop() {

    lights1(); 
    lights2();
    motor();

}

void lights1() {

  static unsigned long lastTime = 0;
  const long interval = 3000;
  static bool state = 0;

  unsigned long now = millis();

  if ( now - lastTime > interval && state == 0) {
    state = 1;
    lastTime = now;
    digitalWrite(enablePWMPin, HIGH);
    digitalWrite(controlPinA, HIGH);
    digitalWrite(controlPinB, LOW);
  }

  if ( now - lastTime > interval && state == 1) {
    state = 0;
    lastTime = now;
    digitalWrite(controlPinA, LOW);
    digitalWrite(controlPinB, HIGH);
  }
}

void lights2() {

  static unsigned long lastTime = 0;
  const long interval = 250;
  static bool state = 0;

  unsigned long now = millis();

  if ( now - lastTime > interval && state == 0) {
    state = 1;
    lastTime = now;
    digitalWrite(red1, HIGH);
    digitalWrite(red2, HIGH);
    digitalWrite(blue1, LOW);
    digitalWrite(blue2, LOW);
  }

  if ( now - lastTime > interval && state == 1) {
    state = 0;
    lastTime = now;
    digitalWrite(red1, LOW);
    digitalWrite(red2, LOW);
    digitalWrite(blue1, HIGH);
    digitalWrite(blue2, HIGH);
  }

}

void motor() {
  int directionA = digitalRead(controlPinA);
  int directionB = digitalRead(controlPinB);
  if (directionA == HIGH && directionB == LOW) {
    digitalWrite(front1, HIGH);
    digitalWrite(front2, HIGH);
    digitalWrite(back1, LOW);
    digitalWrite(back2, LOW);
  } else if (directionA == LOW && directionB == HIGH) {
    digitalWrite(back1, HIGH);
    digitalWrite(back2, HIGH);
    digitalWrite(front1, LOW);
    digitalWrite(front2, LOW);
  } else {
    digitalWrite(front1, LOW);
    digitalWrite(front2, LOW);
    digitalWrite(back1, LOW);
    digitalWrite(back2, LOW);
  }
}

Этот подход будет имитировать одновременный запуск всех трех функций. Каждая функция выполняется по очереди. Но поскольку задержка была удалена из функций light1/2, они будут быстро завершаться в течение периода "ожидания" вместо приостановки выполнения. Это позволит двигателю(двигателям) работать, а лампочкам мигать одновременно.

,

3

Нет, ты не можете.

Мало того, что C/C++ не имеет нескольких идентичных функций, то есть он не будет компилироваться (как предполагает комментарий jfpoilpret). Это также не соответствует идее потока программ в мире Arduino - скетчей, где у вас есть два метода на самом высоком (доступном пользователю) уровне: void setup() и void loop(). установка выполняется ровно один раз в начале вашей программы. Следующий за этим цикл зацикливается (отсюда и название) навсегда. Вам необходимо правильно реструктурировать свой код, чтобы реализовать предполагаемый поток программы, то есть вызвать свои собственные функции из цикла. Подробнее читайте на www.arduino.cc с учебниками, которые стоит изучить.

,

2

Чего вы пытаетесь достичь? Предназначены ли эти циклы для одновременного запуска (это невозможно)? Или один за другим? Вы могли бы приблизиться к "одновременному", если бы "очень быстро" было достаточно хорошо. Вам нужно будет

  • Дайте каждой функции цикла новое уникальное имя;
  • Разделите каждый из первых двух циклов на delay()s в общей сложности на 5 функций;
  • Используйте библиотеку таймеров, такую как SimpleTimer, чтобы запускать каждую из функций с нужной вам скоростью.
  • и из единственной функции loop() продолжайте вызывать функцию SimpleTimer '.run ()', чтобы все это продолжалось.

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

,

2

Я хочу запустить их одновременно, но в другом цикле.

Во-первых, вы можете делать только одну вещь за раз. Так что это исключено.

Во-вторых, запустить несколько циклов последовательно (по одному) довольно просто:

void loop1(void) {...}
void loop2(void) {...}
...

void loop(void) {
  loop1(); //запустить loop1
  loop2(); //запустить loop2
  ...
  loopn(); //запустить loopn
}

Будет ли это работать, будет зависеть от того, как вы закодировали эти циклы.

,

2

Чтобы использовать несколько циклов одновременно, вам нужна плата Arduino Due. Это единственная плата, совместимая с библиотекой #include <Scheduler.h>

См. Примеры > Библиотека планировщика > Несколько миганий

// Включить планировщик, так как мы хотим управлять несколькими задачами.
#include <Scheduler.h>

int led1 = 13;
int led2 = 12;
int led3 = 11;

void setup() {
  Serial.begin(9600);

  // Установите 3 контакта в качестве выхода
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);

  // Добавьте "loop2" и "loop3" в планирование.
  // "цикл" всегда запускается по умолчанию.
  Scheduler.startLoop(loop2);
  Scheduler.startLoop(loop3);
}

// Задача № 1: мигать светодиодом с задержкой в 1 секунду.
void loop() {
  digitalWrite(led1, HIGH);

  // ВАЖНО:
  // При выполнении нескольких задач "задержка" передает управление
  // другие задачи во время ожидания и гарантии их выполнения.
  delay(1000);

  digitalWrite(led1, LOW);
  delay(1000);
}

// Задача № 2: мигать светодиодом с задержкой 0,1 секунды.
void loop2() {
  digitalWrite(led2, HIGH);
  delay(100);
  digitalWrite(led2, LOW);
  delay(100);
}

// Задача № 3: принимать команды из последовательного порта
// '0' выключает светодиод
// '1' включает светодиод
void loop3() {
  if (Serial.available()) {
    char c = Serial.read();
    if (c=='0') {
      digitalWrite(led3, LOW);
      Serial.println("Led turned off!");
    }
    if (c=='1') {
      digitalWrite(led3, HIGH);
      Serial.println("Led turned on!");
    }
  }

  // ВАЖНО:
  // Мы должны регулярно вызывать "yield", чтобы пройти
  // управление другими задачами.
  yield();
}
,

пустота - это не глагол., @gre_gor

@gre_gor: Использование этого слова в качестве глагола может привести к аннулированию гарантии ;-), @Edgar Bonet