Как Arduino может выполнять несколько действий параллельно, не мешая друг другу?

led loop

Я работаю со своим сыном (9 лет), и мы прекрасно проводим время, учимся. Но у нас возникла проблема, и нам нужна ваша помощь.

У нас есть два отдельных цикла, которые мы хотим запустить, не мешая друг другу. В настоящее время у нас есть два светодиода, которые мигают в последовательности со встроенными задержками, чтобы держать их включенными/выключенными.

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

Проблема в том, что схема фотоэлемента отстает на 1/2 секунды из-за световой последовательности от другой петли.

Как это исправить?

// это фотоэлемент и светодиодная программа declans

const int photoCell    =  0;  // переменная фотоэлемента
const int ledLightButt = 11;  // Назначение переменной светодиода

int lightCal;                 // не знаю, что это
int lightVal;                 // это чтение с фотоэлемента, я думаю


void setup() {
    pinMode(13, OUTPUT);
    pinMode(12, OUTPUT);

    pinMode(ledLightButt, OUTPUT);
    lightCal = analogRead(photoCell);
}

void loop() {

    lightVal = analogRead(photoCell);

    if (lightVal < lightCal - 50) {
        digitalWrite(ledLightButt, HIGH);
    }
    else {
        digitalWrite(ledLightButt, LOW);
    }

    digitalWrite(13, HIGH);
    digitalWrite(12, LOW);
    delay(250);

    digitalWrite(13, LOW);
    digitalWrite(12, HIGH);
    delay(250);

}

, 👍0

Обсуждение

это может помочь... https://www.norwegiancreations.com/2017/09/arduino-tutorial-using-millis-instead-of-delay/, @jsotola

совет: отформатируйте свой код правильно, чтобы блоки кода были четко определены .... я отформатировал ваш существующий код в качестве примера .... правильное форматирование важно в блоках if-else и в функциональных блоках, @jsotola


5 ответов


2

Корень такого поведения заключается в том, что когда программа запускает функцию delay(), ничто другое не может выполняться (цифровая запись, проверки, условия и т. д.), пока не истечет время delay().

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

Гугление "Как избежать задержки()" даст вам много информации о том, как это сделать, один пример можно найти здесь: Игровая площадка Arduino — как и почему избежать функции delay().

Удачи в этом и наслаждайтесь программированием!

,

0

Я думаю, что время может быть слишком сложным для 9-летнего ребенка, поэтому :
Я дам альтернативу: Синхронизация двух Arduino с использованием основного или программного серийного номера. это можно использовать для обучения архитектуре клиента сервера (главный/подчиненный), где клиент настроен на более быстрое завершение цикла и ожидание синхронизации данных с сервера (главного), чтобы начать следующий.

Обратите внимание, что если вы отправляете числа через последовательный порт на другой Arduino, используйте Serial.write() (а не Serial.print(); это избавляет вас от работы с asci и char в int (неинтересно для ребенка, только проблемы)

Существует третий вариант библиотеки, которая пытается имитировать параллельную синхронизацию, но это слишком хлопотно и не является хорошей привычкой

,

1

мы нашли другой код, который помог нам избежать функций delay(). Теперь мы можем использовать метку времени «Millis» для запуска наших мигающих огней И иметь еще один оператор if, запускающий фотоэлемент & третий светодиод.

Прогресс! Спасибо за предложения! Вот код, и он отлично работает, чтобы включать и выключать светодиод в зависимости от фотоэлемента, а другие светодиоды мигают сами по себе.

const int photoCell =0;
const int ledPin = 13;
const int led2Pin = 12;
const int led3Pin = 11;
int lightCal;
int lightVal;
int ledState = LOW;
int led2State = HIGH;
long previousMillis = 0;
long interval = 250;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
  pinMode(led3Pin, OUTPUT);
  lightCal=analogRead(photoCell);
}

void loop() {
unsigned long currentMillis = millis();
lightVal = analogRead(photoCell);

if(currentMillis - previousMillis >= interval) 
{
  previousMillis = currentMillis;
  if (ledState == LOW)
  ledState = HIGH;
  else
  ledState = LOW;
  if (ledState == LOW)
  led2State = HIGH;
  else
  led2State = LOW;

  digitalWrite(ledPin, ledState);
  digitalWrite(led2Pin, led2State);
}
if (lightVal < lightCal - 50)
{
  digitalWrite(led3Pin, HIGH);
}
else {
  digitalWrite(led3Pin, LOW);
}
}
,

0

Вы можете без промедления использовать библиотеку, поддерживающую мерцание. Например, вы можете обратиться к этому примеру кода:

#include <ezOutput.h> // библиотека ezOutput

ezOutput led1(7);  // создаем объект ezOutput, который подключается к контакту 7;
ezOutput led2(8);  // создаем объект ezOutput, который подключается к контакту 8;
ezOutput led3(9);  // создаем объект ezOutput, который подключается к контакту 9;

void setup() {
  led1.blink(500, 250);       // 500 мс ВКЛ, 250 мс ВЫКЛ. начать немедленно
  led2.blink(250, 250, 1000); // 250 мс ВКЛ, 250 мс ВЫКЛ. начать через 1000 миллисекунд
  led2.blink(100, 100, 2000); // 100 миллисекунд ВКЛ, 100 миллисекунд ВЫКЛ. начать через 2000 миллисекунд
}

void loop() {
  led1.loop(); // ДОЛЖЕН вызывать функцию led1.loop() в loop()
  led2.loop(); // ДОЛЖЕН вызывать функцию led2.loop() в loop()
  led3.loop(); // ДОЛЖЕН вызывать функцию led3.loop() в loop()

  // ВЫПОЛНЯЕМ ЗДЕСЬ ДРУГУЮ РАБОТУ

}

Учебник доступен здесь

,

0

Есть неплохое руководство по Adafruit о том, как это реализовать (помимо уже перечисленных): https://learn.adafruit.com/multi-tasking-the-arduino-part-1

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

Вы также можете воспользоваться библиотекой задач Makuna (https://github.com/Makuna/Task) или попробуйте мое собственное решение: https://github.com/rdragonrydr/CoRTOS (которое спроектировано так, чтобы быть эффективным и простым в использовании). - использовать по возможности). Он все еще находится в стадии разработки (скоро будет больше оптимизаций), но определенно его можно использовать практически для всего, что я могу придумать.

,