Как постоянно прослушивать кнопки ввода в Arduino? - PullRequest
0 голосов
/ 20 января 2020

Я пытаюсь создать работающую физическую симуляцию пересечения траффи c света. Я хочу непрерывно прослушивать показания кнопок (кнопки пешеходов, чтобы загореться зеленый свет пешеходов) на протяжении всей программы, и хочу запустить другую функцию, которая будет обрабатывать огни пешеходов, если кнопки будут нажиматься во время выполнения программы. Я пробовал это с циклами while и if, но условия просто не будут работать, потому что тогда он будет читать ввод кнопки в определенный момент времени c, когда я хочу, чтобы он постоянно считывал показания по всей программе и прерывал l. oop если условие когда-либо не соответствует действительности (циклы while и do-while проверяют условие только в конце l oop, только когда я хочу, чтобы оно проверяло условие в течение l oop). Мне также нужно узнать, какая кнопка была нажата, если это возможно. Затем в зависимости от того, какая кнопка была нажата, я хочу запустить функцию pedes () или pedes2 (). Не стесняйтесь спрашивать, нуждаетесь ли вы в каких-либо пояснениях.

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

// If at any point in time during this code, a button is pushed, I want to run a function called
    pedes() or pedes2() depending on which button is pressed.

// First set of Trafiic Lights
int redT = 13 ;
int yellowT = 12;
int greenT = 11;

// First set of Pedestrian Lights
int redP = 10;
int greenP = 9;

// Second set of Traffic Lights
int redT2 = 8;
int yellowT2 = 7;
int greenT2 = 6;

// Second set of Pedestrian Lights
int redP2 = 5;
int greenP2 = 4;

// Pedestrian Buttons
int buttonT = 3;
int buttonT2 = 2;
int buttonT3 = 1;
int buttonT4 = 0;

int buttonStateT = 0;
int buttonStateT2 = 0;
int buttonStateT3 = 0;
int buttonStateT4 = 0;

// Booleans which will handle which button was pressed

void setup() {
  // First set of Trafiic Lights
  pinMode(redT, OUTPUT);
  pinMode(yellowT, OUTPUT);
  pinMode(greenT, OUTPUT);

  // First set of Pedestrian Lights
  pinMode(redP, OUTPUT);
  pinMode(greenP, OUTPUT);

  // Second set of Traffic Lights
  pinMode(redT2, OUTPUT);
  pinMode(yellowT2, OUTPUT);
  pinMode(greenT2, OUTPUT);

  // Second set of Pedestrian Lights
  pinMode(redP2, OUTPUT);
  pinMode(greenP2, OUTPUT);

  // Pedestrian Buttons
  pinMode(buttonT, INPUT);
  pinMode(buttonT2, INPUT);
  pinMode(buttonT3, INPUT);
  pinMode(buttonP4, INPUT);
}

void loop() {
    // Resetting all the traffic lights
    digitalWrite(redP, HIGH); // Turns on red pedestrian LED from 1st bunch
    digitalWrite(redP2, HIGH); // Turns on red pedestrian LED from 2nd bunch

    digitalWrite(yellowT, LOW); // Turns off yellow traffic LED from 1st bunch
    digitalWrite(yellowT2, LOW); // Turns off yellow traffic LED from 1st bunch

    digitalWrite(redT, HIGH); // Turns on red traffic LED from 1st bunch
    digitalWrite(redT2, HIGH); // Turns on red traffic LED from 2nd bunch

    delay(2000);

    digitalWrite(redT, LOW); // Turns off red traffic LED from 1st bunch
    digitalWrite(redT2, HIGH); // Turns on red traffic LED from 2nd bunch

    digitalWrite(greenT, HIGH); // Turns on green traffic LED from 1st bunch
    digitalWrite(greenT2, LOW); // Turns off green traffic LED from 2nd bunch

    delay(10000); // Pauses program for 8 seconds

    digitalWrite(greenT, LOW); // Turns off green traffic LED from 1st bunch
    digitalWrite(yellowT, HIGH); // Turns on yellow traffic LED from 1st bunch

    delay(3000); // Pauses program for 3 seconds

    digitalWrite(yellowT, LOW); // Turns off yellow traffic LED from 1st bunch
    digitalWrite(redT, HIGH); // Turns on red traffic LED from 1st bunch

    delay(2000); // Pauses program for 3 seconds

    digitalWrite(redT2, LOW); // Turns off red traffic LED from 2nd bunch
    digitalWrite(greenT2, HIGH); // Turns on green traffic LED from 2nd bunch

    delay(6000); // Pauses program for 8 seconds

    digitalWrite(greenT2, LOW); // Turns off green traffic LED from 2nd bunch
    digitalWrite(yellowT2, HIGH); // Turns on yellow traffic LED from 2nd bunch

    delay(3000); // Pauses program for 3 seconds

    digitalWrite(yellowT2, LOW); // Turns off yellow traffic LED from 2nd bunch
    digitalWrite(redT2, HIGH); // Turns on red traffic LED from 2nd bunch

    delay(2000); // Pauses program for 3 seconds
  }

Ответы [ 3 ]

0 голосов
/ 21 января 2020

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

Лучшая привычка - использовать таймеры вместо задержек. Это позволяет вашему коду продолжать цикл без остановки, и вы можете добавить код для более частой проверки пользовательского ввода.

Вот пример того, что НЕ следует делать:

void loop() {
  digitalWrite(MY_LED,HIGH);
  delay(1000);
  digitalWrite(MY_LED,LOW);
  delay(1000);

  //This code only gets reached every 2 seconds
  //This means you may need to hold the button for up to
  //2 seconds before it will print a message
  if (digitalRead(MY_BUTTON) == LOW) {
    Serial.println("You pressed the button");
  }
}

Вы можете используйте millis (), чтобы получить количество миллисекунд с момента запуска arduino. Вот базовый c пример таймера:

bool ledState = false;
unsigned long toggledTime = 0;  //The last time we toggled the led

void loop() {

  //Calculate how much time has passed since the last time
  //we turned the LED on or off
  unsigned long timeElapsedSinceLastToggle = millis() - toggledTime;

  //If 1000ms (1s) has passed, we'll toggle the LED
  if (timeElapsedSinceLastToggle > 1000) {
    ledState = !ledState;           //Invert the state
    digitalWrite(MY_LED,ledState);  //Perform the action
    toggledTime = millis();         //Reset our timer to the current time
  }

  //This code now checks very frequently since the code above
  //never uses delay()
  if (digitalRead(MY_BUTTON) == LOW) {
    Serial.println("You pressed the button");
  }
}

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

Есть одна вещь, с которой вы должны быть осторожны в отношении таймеров. millis () - это количество миллисекунд с момента загрузки, но что происходит, когда ваш код выполняется очень долго? Millis () сбрасывается (начинается с 0) примерно через 50 дней. Для многих людей это не имеет большого значения, но стоит иметь в виду, если ваш код будет работать бесконечно долгое время.

0 голосов
/ 21 января 2020

Вместо постоянного опроса вы можете использовать прерывание на контакте кнопки и устанавливать флаг или вызывать функцию из подпрограммы прерывания.

Также убедитесь, что кнопка отменена в аппаратное или программное обеспечение.


Поскольку вы, кажется, учитесь, вот некоторые дополнительные улучшения, которые вы можете добавить в качестве упражнения:

  • Чтобы переключить свет, вы могли бы используйте прерывания по таймеру вместо задержек (вы даже можете поместить mcu в спящий режим между ними). ​​

  • Еще одним улучшением было бы создание класса TrafficLight, который содержит все логи c. Вот интересный урок . Таким образом, вы можете легко создавать несколько объектов: TrafficLight tl1(..), tl2(..); или даже массивы траффиков c источников света (например, с одинаковыми временными интервалами).

  • Затем вы можете даже создать класс Intersection, который содержит все светофоры c и логи c для этого пересечения.

0 голосов
/ 20 января 2020

Хорошо, если вы задерживаетесь на 10 секунд, вы не можете реагировать на что-то в это время.

Вы можете использовать millis () для реализации неблокирующей задержки. https://www.arduino.cc/en/tutorial/BlinkWithoutDelay

Вместо того, чтобы бездействовать и не отвечать, вы тратите свое время на проверку и реагирование на состояния кнопок и / или условия времени.

...