Как Arduino может выполнять несколько действий параллельно, не мешая друг другу?
Я работаю со своим сыном (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);
}
@Nick Motter, 👍0
Обсуждение5 ответов
Корень такого поведения заключается в том, что когда программа запускает функцию delay(), ничто другое не может выполняться (цифровая запись, проверки, условия и т. д.), пока не истечет время delay().
Эффективным решением для этого является отказ от функции delay() и получение тех же результатов (без побочных эффектов) с помощью таймеров (например, millis()) или других способов.
Гугление "Как избежать задержки()" даст вам много информации о том, как это сделать, один пример можно найти здесь: Игровая площадка Arduino — как и почему избежать функции delay().
Удачи в этом и наслаждайтесь программированием!
Я думаю, что время может быть слишком сложным для 9-летнего ребенка, поэтому :
Я дам альтернативу:
Синхронизация двух Arduino с использованием основного или программного серийного номера. это можно использовать для обучения архитектуре клиента сервера (главный/подчиненный), где клиент настроен на более быстрое завершение цикла и ожидание синхронизации данных с сервера (главного), чтобы начать следующий.
Обратите внимание, что если вы отправляете числа через последовательный порт на другой Arduino, используйте Serial.write() (а не Serial.print(); это избавляет вас от работы с asci и char в int (неинтересно для ребенка, только проблемы)
Существует третий вариант библиотеки, которая пытается имитировать параллельную синхронизацию, но это слишком хлопотно и не является хорошей привычкой
мы нашли другой код, который помог нам избежать функций 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);
}
}
Вы можете без промедления использовать библиотеку, поддерживающую мерцание. Например, вы можете обратиться к этому примеру кода:
#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()
// ВЫПОЛНЯЕМ ЗДЕСЬ ДРУГУЮ РАБОТУ
}
Учебник доступен здесь
Есть неплохое руководство по Adafruit о том, как это реализовать (помимо уже перечисленных): https://learn.adafruit.com/multi-tasking-the-arduino-part-1
Я не согласен с данным подходом, так как он требует, чтобы все задачи опрашивались вручную и чтобы вы применяли его к каждой задаче, но сам дизайн действительно умный.
Вы также можете воспользоваться библиотекой задач Makuna (https://github.com/Makuna/Task) или попробуйте мое собственное решение: https://github.com/rdragonrydr/CoRTOS (которое спроектировано так, чтобы быть эффективным и простым в использовании). - использовать по возможности). Он все еще находится в стадии разработки (скоро будет больше оптимизаций), но определенно его можно использовать практически для всего, что я могу придумать.
- Мигните светодиодом 5 раз с помощью цикла for
- Как повторить другое действие внутри цикла?
- Выход из цикла while с помощью ИК-пульта для neopixel
- Сделать световые вспышки, пока шаговый двигатель постоянно движется.
- Arduino включение/затухание 5 светодиодов, схема действия
- Бесконечный цикл serial.readString()
- Выполнить функцию цикла из основного цикла()
- Застрял в цикле While
это может помочь... https://www.norwegiancreations.com/2017/09/arduino-tutorial-using-millis-instead-of-delay/, @jsotola
совет: отформатируйте свой код правильно, чтобы блоки кода были четко определены .... я отформатировал ваш существующий код в качестве примера .... правильное форматирование важно в блоках
if-else
и в функциональных блоках, @jsotola