проблема с использованием одной функции для мигания разными светодиодами

Я написал функцию для мигания светодиода с помощью миллиса и хочу мигать несколькими светодиодами с одной и той же функцией, но с разными интервалами задержки. Когда я вызываю эту функцию трижды, чтобы мигать 3 разными светодиодами, все светодиоды мигают с наименьшей задержкой. Насколько я понимаю, функции можно использовать повторно, если вы хотите выполнить одну и ту же задачу, но почему в этом случае это не работает? Это работает, если я переименую функцию перед ее повторным вызовом.

Неправильно ли вызывать одну функцию более одного раза для выполнения одной и той же задачи, но на разных выводах? Как бы вы вызвали функцию, не переименовывая ее?

const int redLed = 10;
const int yellowLed = 11;
const int greenLed = 12;

void setup() {
  pinMode(redLed, OUTPUT);
  pinMode(yellowLed, OUTPUT);
  pinMode(greenLed, OUTPUT);
}

void loop() {
blinkLed(redLed, 1000);
blinkLed(yellowLed, 4000);
blinkLed(greenLed, 8000);
}

void blinkLed(int led, unsigned long timePeriod) {
  static unsigned long oldTime = 0;
  unsigned long newTime = millis();
  static boolean ledState = LOW;

  if (newTime - oldTime >= timePeriod) {
    oldTime = newTime;
    ledState = !ledState;
  }
  digitalWrite(led, ledState);
}

Редактировать: я изменил функцию, чтобы она не имела общих переменных, но она просто мигает красным. почему сейчас не работает? Вот код:

const int redLed = 10;
const int yellowLed = 11;
const int greenLed = 12;

void setup() {
  pinMode(redLed, OUTPUT);
  pinMode(yellowLed, OUTPUT);
  pinMode(greenLed, OUTPUT);
}

void loop() {

  blinkLed(redLed, 1000);
  blinkLed(yellowLed, 4000);
  blinkLed(greenLed, 8000);
}

void blinkLed(int led, unsigned long timePeriod) {

  switch (led) {
    case 10:
      static unsigned long oldTime1 = 0;
      unsigned long newTime1 = millis();
      static boolean redState = LOW;

      if (newTime1 - oldTime1 >= timePeriod) {
        oldTime1 = newTime1;
        redState = !redState;
      }
      digitalWrite(led, redState);
          break;

    case 11:
      static unsigned long oldTime2 = 0;
      unsigned long newTime2 = millis();
      static boolean yellowState = LOW;


      if (newTime2 - oldTime2 >= timePeriod) {
        oldTime2 = newTime2;
        yellowState = !yellowState;
      }
      digitalWrite(led, yellowState);
          break;

    case 12:
      static unsigned long oldTime3 = 0;
      unsigned long newTime3 = millis();
      static boolean greenState = LOW;


      if (newTime3 - oldTime3 >= timePeriod) {
        oldTime3 = newTime3;
        greenState = !greenState;
      }
      digitalWrite(led, greenState);
      break;
  }
}

, 👍0


3 ответа


1

Вы хотите, чтобы светодиоды мигали одновременно.
Ваши статические переменные oldTime и ledState являются общими для трех светодиодов.
Таким образом, в вашей программе есть только ОДИН ledState, но вам нужно это состояние для каждого из них.
То же самое относится и к oldTime.

Решите эту проблему, и ваши светодиоды будут мигать должным образом.

кстати. вам не нужен ledState, так как вы можете прочитать его текущее состояние.

,

вывод светодиода определяется как ВЫХОД, так что не буду ли я читать то, что я пишу на вывод? Кроме того, как контакт, определенный как выход, одновременно работает как вход?, @Zaffresky

@Zaffresky, если вы читаете выходной контакт, вы читаете то, что вы на него написали. Но это именно то, что вам нужно, так как вы просто хотите переключить пин, @chrisl

Чтобы решить проблему с общими переменными, я изменил свою функцию, но теперь есть другие проблемы. Теперь ломаю голову, как это исправить. Может быть, самый простой способ без создания классов (нужно сначала изучить его) - просто скопировать функцию с разными именами и вызвать их., @Zaffresky

@Zaffresky, который перебивает вашу идею в код. это далеко от хороших привычек кодирования. Занятия легкие, если делать их примитивно. Взгляните на Blinker Code Маженко. Вам действительно нужно отслеживать только три состояния (по одному для каждого светодиода), и эти состояния состоят не более чем из двух переменных. Вы можете использовать struct с этими двумя переменными, если так считаете. Просто передайте его как указатель или ссылку на вашу функцию blinkLed., @Kwasmich


1

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

Вам лучше научиться создавать это как класс, который может содержать не только функцию "мигания", но и переменные, определяющие состояние для конкретного экземпляра мерцания.

Например, вот небольшая библиотека, которую я написал много лет назад в качестве демонстрации.

,

Я думал, что при каждом вызове функции новая копия переменных будет создаваться и управляться независимо от предыдущего вызова функции и предыдущих значений переменных в ней. Я ничего не знаю о классах, так что поищу, @Zaffresky

Нет, одна функция = один набор переменных. Вы можете передавать ссылки на другие локальные переменные, но это запутает. Проще использовать класс., @Majenko


0

Просто объединим предложения других людей:

void blinkLed(int led, unsigned long timePeriod) {
  static unsigned long oldTime[42];
  unsigned long newTime = millis();
  boolean ledState = digitalRead(led);

  if (newTime - oldTime[led] >= timePeriod) {
    oldTime[led] = newTime;
    ledState = !ledState;
  }
  digitalWrite(led, ledState);
}
,

Неее, вроде. это будет работать, но все же не очень хорошее решение. Всем известное магическое число 42 на самом деле не то, чем вы хотите заниматься. Лучше создать структуру или класс, который инкапсулирует: pin, timePeriod, oldTime и ledState. Затем функция будет принимать только объект состояния в качестве своего единственного аргумента., @Kwasmich

Другие люди, кроме Квасмича*, @Abel

@Abel, почему ты выбрал 42 для OldTime? И вы определяете oldTime как массив?, @Zaffresky

Преобразование единственного значения oldTime в массив — это самый простой способ масштабирования кода. В идеале 42 следует заменить на максимально пронумерованный возможный цифровой выходной контакт на заголовок Arduino или просто максимальное количество используемого порта +1, также известное как 13. Массив, потому что жертвует памятью для простоты реализации класса или карты., @Abel