Моделирование светофора: небольшое сомнение
Я пытаюсь смоделировать светофор с кнопкой для пешеходов, нажатие на которую останавливает движение на некоторое время. Вот условия, которые я пытаюсь выполнить,
Один зеленый светодиод (на контакте 10) загорелся на 3 секунды (первый загоревшийся светодиод). - Затем один оранжевый светодиод (на контакте 11) загорается на 1 секунду - Затем, наконец, один красный светодиод (на выводе 12) загорелся на 3 секунды.
Двухцветный свет (пешеходный) - Пешеходный светофор постоянно горит красным цветом (красный светодиод на выводе 9) и становится зеленым (светодиод на выводе 8) только после нажатия кнопки (на выводе 2).
При нажатии кнопки Если кнопка нажата, когда на светофоре автомобиля горит зеленый свет, оранжевый свет загорается на 1 секунду, затем автомобиль свет загорается красным на 5 секунд, в течение которых горит зеленый пешеходный свет зеленый.
После этих 5 секунд пешеходный светофор снова загорается красным, и возобновляется нормальное функционирование (автомобильный светофор снова загорается зеленым)
А вот мой код для того же самого,
int status=0; //mode:состояние контакта кнопки
int buttonpin=2;//контакт, связанный с кнопкой
void setup(){
pinMode(10,OUTPUT); //Зеленый светодиод на pin10
pinMode(11,OUTPUT); //Оранжевый светодиод на вывод 11
pinMode(12,OUTPUT); //Красный светодиод на вывод 12
pinMode(9,OUTPUT); // Пешеходный красный на контакте 9
pinMode(8,OUTPUT); //Пешеходный зеленый на выводе 8
}
void loop(){
digitalWrite(9,HIGH);//Включен красный свет для пешеходов
status=digitalRead(buttonpin);
if (status==HIGH){
digitalWrite(9,LOW); //красный для пешеходов выключен
digitalWrite(8,HIGH); //Включен зеленый для пешеходов
digitalWrite(11,HIGH);//загорается оранжевый
delay(1000);//задержка в 1 секунду
digitalWrite(11,LOW);//оранжевый выключен);
digitalWrite(12,HIGH);//красный начинает
delay(5000);//5 секунд задержки
digitalWrite(12,LOW);
digitalWrite(9,HIGH);
}
else{
digitalWrite(10,HIGH);//загорается зеленый
delay(3000);//3 секунды задержки
digitalWrite(10,LOW);//зеленый отключается
digitalWrite(11,HIGH);//загорается оранжевый
delay(1000);//задержка в 1 секунду
digitalWrite(11,LOW);//оранжевый выключен);
digitalWrite(12,HIGH);//красный начинает
delay(3000);
digitalWrite(12,LOW);//красный выключается
}
}
Проблема в том, что кнопка для пешеходов срабатывает только в том случае, если она уже нажата в момент включения зеленого сигнала светофора (из-за цикла if в коде), но как только зеленый сигнал светофора уже горит, скажем, 1,5 секунды, она не сработает, поскольку проверка условия цикла if уже была пройдена. Как мне исправить свой код, чтобы последовательность «При нажатии кнопки», описанная выше, работала в любое время, когда зеленый светодиод горит ВЫСОКИМ светом?
Прилагается схема, если необходимо.
Отредактированный код:
#include <TimerOne.h>
int status=0; //mode:state of button pin
int buttonpin=2;//контакт, связанный с кнопкой
void setup(){
pinMode(10,OUTPUT);
pinMode(11,OUTPUT);
pinMode(12,OUTPUT);
pinMode(9,OUTPUT);
pinMode(8,OUTPUT);
Timer1.initialize(100000);
Timer1.attachInterrupt( buttonCheck );
}
void loop(){
digitalWrite(9,HIGH);
status=digitalRead(buttonpin);
digitalWrite(10,HIGH);//загорается зеленый
delay(3000);//3 секунды задержки
digitalWrite(10,LOW);//зеленый отключается
digitalWrite(11,HIGH);//загорается оранжевый
delay(1000);//задержка в 1 секунду
digitalWrite(11,LOW);//оранжевый выключен);
digitalWrite(12,HIGH);//красный начинает
delay(3000);
digitalWrite(12,LOW);//красный выключается
}
void buttonCheck(){
if (status==HIGH){
digitalWrite(9,LOW);
digitalWrite(8,HIGH);
digitalWrite(11,HIGH);//загорается оранжевый
delay(1000);//задержка в 1 секунду
digitalWrite(11,LOW);//оранжевый выключен);
digitalWrite(12,HIGH);//красный начинает
delay(5000);//5 секунд задержки
digitalWrite(12,LOW);
digitalWrite(9,HIGH);
return;
}
}
Это сработает?
@Kv07, 👍-1
Обсуждение1 ответ
Лучший ответ:
Причина проблемы в том, как вы реализовали delay()
в своем эскизе. Это правда, что delay()
следует избегать в 99,9% случаев, но у него есть свои применения.
Если вы начнете с примера BlinkWithoutDelay, который поставляется с Arduino IDE, а затем добавите переменную-счетчик и оператор switch, вы легко сможете заставить работать «часть» ваших требований, связанную со светофорами.
Добавить функционал пешеходной кнопки с использованием неблокирующего кода сложнее (для меня это сложнее), но это проблема, легко решаемая с помощью delay()
.
Но что, если вы когда-нибудь захотите, чтобы ваш эскиз делал больше? Что произойдет, если вы добавите в него еще одну кнопку? delay()
— это «блокирующий» код, поэтому его использование, вероятно, снова «укусит» вас, если вы попытаетесь добавить функциональность в этот эскиз.
const byte buttonPin = 2;
byte secondsCounter = 0;
byte trafficLightState = 0;
unsigned long oneSecond = 1000;
unsigned long previousMillis = 0;
void setup(){
pinMode(10, OUTPUT); // Зеленый светодиод на вывод 10
pinMode(11, OUTPUT); // Оранжевый светодиод на вывод 11
pinMode(12, OUTPUT); // Красный светодиод на вывод 12
pinMode(9, OUTPUT); // Пешеходный красный на контакте 9
pinMode(8, OUTPUT); // Зеленый для пешеходов на выводе 8
// Я использовал провод от GND к "buttonPin" в качестве переключателя.
pinMode(buttonPin, INPUT_PULLUP);
Serial.begin(9600);
}
void loop(){
// Получить текущее время.
unsigned long currentMillis = millis();
// Если кнопка нажата, когда на светофоре горит зеленый свет,
// оранжевый свет горит 1 секунду, затем фары автомобиля выключаются
// красный в течение 5 секунд, в течение которых горит зеленый свет для пешеходов.
if(trafficLightState == 0 && digitalRead(buttonPin) == LOW){
digitalWrite(10, LOW);
digitalWrite(11, HIGH);
digitalWrite(12, LOW);
digitalWrite(9, HIGH);
digitalWrite(8, LOW);
Serial.println("Button Pressed. Orange light ON for 1 second, Pedestrian red ON.");
delay(1000);
digitalWrite(11, LOW);
digitalWrite(12, HIGH);
digitalWrite(9, LOW);
digitalWrite(8, HIGH);
Serial.println("Red light ON for 5 seconds, Pedestrian green ON.");
delay(5000);
digitalWrite(11, HIGH);
digitalWrite(12, LOW);
digitalWrite(9, HIGH);
digitalWrite(8, LOW);
Serial.println("Pedestrian red ON.");
trafficLightState = 0;
secondsCounter = 0;
currentMillis = millis();
}
// Обновлять состояние светофора каждую секунду.
if(oneSecondTimer(oneSecond, currentMillis) == 1){
secondsCounter += 1;
if(secondsCounter > 7){secondsCounter = 1;}
// Зеленый свет светофора.
if(secondsCounter == 1){
trafficLightState = 0;
Serial.println("Green traffic light ON for 3 seconds");
}
// Оранжевый светофор.
else if(secondsCounter == 4){
trafficLightState = 1;
Serial.println("Orange traffic light ON for 1 second");
}
// Красный свет светофора.
else if(secondsCounter == 5){
trafficLightState = 2;
Serial.println("Red traffic light ON for 3 seconds");
}
}
// Включайте/выключайте светофоры по мере необходимости.
switch(trafficLightState){
// Включить зеленый свет светофора и красный свет для пешеходов.
case 0:
digitalWrite(10, HIGH);
digitalWrite(11, LOW);
digitalWrite(12, LOW);
digitalWrite(9, HIGH);
digitalWrite(8, LOW);
break;
// Включить оранжевый сигнал светофора и красный сигнал для пешеходов.
case 1:
digitalWrite(10, LOW);
digitalWrite(11, HIGH);
digitalWrite(12, LOW);
digitalWrite(9, HIGH);
digitalWrite(8, LOW);
break;
// Включи красный свет светофора, пешеходный красный свет.
case 2:
digitalWrite(10, LOW);
digitalWrite(11, LOW);
digitalWrite(12, HIGH);
// Зеленый свет для пешеходов ВКЛЮЧЕН ТОЛЬКО если кнопка была
// нажал, когда на светофоре горел зеленый свет.
// digitalWrite(9, НИЗКИЙ);
// digitalWrite(8, HIGH);
break;
}
}
byte oneSecondTimer(unsigned long delayTime, unsigned long currentMillis){
if(currentMillis - previousMillis >= delayTime){previousMillis = currentMillis;return 1;}
else{return 0;}
}
этот код не работает так, как была указана проблема., @Kv07
Что он делает по-другому?, @VE7JRO
В вашем исходном скетче и новом, который вы добавили с помощью TimerOne, вы включаете зеленый свет для пешеходов при первом нажатии кнопки, а затем оставляете его включенным до перезагрузки Arduino. Я не видел этого в списке ваших требований. Вы уверены, что хотите сделать именно это? Включить зеленый свет для пешеходов независимо от цвета светофора?, @VE7JRO
Моя цель заключается в том, что когда светофор горит зеленым, если нажата кнопка пешехода, то выполняется следующая последовательность: При нажатии кнопки Если кнопка нажата, когда на светофоре автомобиля горит зеленый свет, оранжевый свет загорается на 1 секунду, затем огни автомобиля становятся красными на 5 секунд, в течение которых зеленый свет пешехода остается зеленым. Затем свет пешехода снова становится красным, и светофор возобновляет свою обычную функциональность. Это проблема в моем (и вашем) коде., @Kv07
Что происходит, когда вы нажимаете кнопку, когда светофор горит зеленым, используя мой эскиз? Корректны ли выходные данные в последовательном мониторе? Еще одна вещь, которую нужно проверить, — это убедиться, что кнопка и светодиоды подключены правильно., @VE7JRO
Ну, я запустил ваш код пару дней назад на Tinkercad, я не помню точный вывод, который дал ваш код, но точно помню, что это было не то, что я хотел. Я считаю, что проводка была сделана правильно, вам стоит попробовать ваш код на Tinkercad тоже., @Kv07
Я попробовал это на Uno, и все сработало отлично., @VE7JRO
- Питание светодиодной ленты - Сколько ампер?
- Несколько условий оператора if
- Светодиоды: разница между общим анодом и общим катодом
- Светодиод L продолжает гореть
- Улучшенное циклическое переключение цветов RGB.
- Плавное мигание светодиодов
- Остановить мигание светодиодов
- FastLED - Как управлять определенными светодиодами
Перестройте свой код, исключив все эти вызовы
delay()
(использование delay не является хорошей идеей почти во всех ситуациях). Вместо этого используйте неблокирующий код с функциейmillis()
. Обратитесь к примеруBlinkWithoutDelay
в Arduino IDE для этого. Также будет полезно узнать, как закодировать конечный автомат (звучит сложнее, чем есть на самом деле). В сети есть множество руководств по этому вопросу., @chrislХотя я согласен, что полностью неблокирующий код лучше, для этой цели можно сказать, что у вас есть «поток», который вы хотите «прервать», поэтому взгляните на «прерывания по контактам»., @Paul
вам нужен конечный автомат для управления этой моделью поведения, @dandavis
@Paul Я использовал прерывания в своем коде и отредактировал ответ. Это сработает?, @Kv07