Игра на память ардуино
Итак, у меня есть проект, который заключается в создании простой игры на память с использованием Arduino, где светодиоды должны мигать по определенному шаблону, а игрок должен имитировать тот же шаблон. но, к сожалению, у меня такие проблемы с кодом Я хочу сделать оператор if, чтобы проверить, была ли нажата кнопка или нет, если да, то он продолжает проверять вторую кнопку, и если это не был красный светодиод (что означает неправильно), должен включиться вот как я начал:
enter code here
const int button1 = 2; // 1-я кнопка управляет синим светодиодом
const int button2 = 3; // 2-я кнопка управляет желтым светодиодом
const int button3 = 4; // 3-я кнопка управляет зеленым светодиодом
const int button4 = 5; // 4-я кнопка управляет красным светодиодом
const int led1 = 7; // Синий светодиод
const int led2 = 8; // Желтый светодиод
const int led3 = 9; // Зеленый светодиод
const int led4 = 10; // Красный светодиод
const int correctLED = 6;
const int wrongLED = 11;
int val = 0;
// Переменные
int buttonState[] = {0,0,0,0}; // текущее состояние кнопки
int lastButtonState[] = {0,0,0,0}; // предыдущее состояние кнопки
int buttonPushCounter[] = {0,0,0,0};
void setup() {
// инициализируем входные данные:
randomSeed(analogRead(0));
pinMode(button1, INPUT);
pinMode(button2, INPUT);
pinMode(button3, INPUT);
pinMode(button4, INPUT);
// инициализируем выходы:
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
// инициализируем последовательную связь для отладки:
Serial.begin(9600);
}
}
void loop() {
digitalWrite(7, HIGH);
digitalWrite(8, HIGH);
digitalWrite(9, HIGH);
digitalWrite(10, HIGH);
digitalWrite(7, LOW);
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(7, HIGH);
delay(500);
digitalWrite(7,LOW);
delay(500);
digitalWrite(8, HIGH);
delay(500);
digitalWrite(8,LOW);
delay(500);
digitalWrite(9, HIGH);
delay(500);
digitalWrite(9,LOW);
delay(500);
digitalWrite(10, HIGH);
delay(500);
digitalWrite(10,LOW);
delay(500);
val = digitalRead(2); // читаем входное значение
if (val == HIGH) { // проверяем, высокий ли входной сигнал (кнопка отпущена)
digitalWrite(wrongLED, LOW); // выключаем светодиод
} else {
digitalWrite(wrongLED, HIGH); // включаем светодиод
}
val = digitalRead(3); // читаем входное значение
if (val == HIGH) { // проверяем, высокий ли входной сигнал (кнопка отпущена)
digitalWrite(wrongLED, LOW); // выключаем светодиод
} else {
digitalWrite(wrongLED, HIGH); // включаем светодиод
}
val = digitalRead(4); // читаем входное значение
if (val == HIGH) { // проверяем, высокий ли входной сигнал (кнопка отпущена)
digitalWrite(wrongLED, LOW); // выключаем светодиод
} else {
digitalWrite(wrongLED, HIGH); // включаем светодиод
}
val = digitalRead(5); // читаем входное значение
if (val == HIGH) { // проверяем, высокий ли входной сигнал (кнопка отпущена)
digitalWrite(wrongLED, LOW); // выключаем светодиод
} else {
digitalWrite(wrongLED, HIGH); // включаем светодиод
}
digitalWrite(correctLED, HIGH);
}
}
@user19169, 👍-1
Обсуждение3 ответа
В таких случаях вам не стоит беспокоиться о том, «нажата ли эта кнопка, а затем эта кнопка» и т. д. Подобные мысли очень «актуальны», поскольку все они касаются того, что происходит сейчас. - а не то, что происходило в прошлом.
Вам нужно думать о той последовательности нажатий кнопок, которую вы видели до сих пор, а не о том, что происходит прямо сейчас.
Предположим, у вас есть три кнопки. Присвоим каждой из них номер — скажем, это кнопки 1, 2 и 3.
И у вас есть 3 светодиода — назовем их A, B и C.
Итак, вы зажигаете и гасите светодиоды в определенном порядке, скажем BAC, и ожидаете, что кнопки будут нажиматься в том же порядке — 213.
Вы не можете все время проверять «Если нажата 2, то нажата 1, затем нажата 3», потому что, по сути, где вы находитесь в этой последовательности в любой момент времени? Вместо этого вам нужно сказать: «Нажата кнопка. Я запомню этот факт». А потом: "Три кнопки были нажаты? Да. Их номера совпадают?"
По сути, это похоже на PIN-код вашей банковской карты или пароль для вашего компьютера. Это не то, что вы нажимаете сейчас, а то, что он помнит, что вы нажимали в прошлом.
Самый простой способ сделать это — буквально присвоить кнопкам номера. Когда кнопка нажата, вы присваиваете переменной номер, представляющий эту кнопку. Затем добавьте этот номер в список номеров, которые вы недавно видели. Когда этот список станет нужной длины, вы его сравните. Точно так же, как ввод пароля.
Вы даже можете сравнить то, что у вас есть на данный момент, с частью того, что вы ожидаете отловить неправильные нажатия на раннем этапе.
Предположим, у вас есть ожидаемое значение «213», сохраненное в строке. У вас также есть пустая строка. Когда вы нажимаете кнопку, вы добавляете это число к строке - скажем, вы нажимаете «212», а затем можете добавить и сравнить строку следующим образом:
Button Input Expected
2 2 2 Correct
1 21 21 Correct
2 212 213 Incorrect - erase input content
2 2 2 Correct
1 21 21 Correct
3 213 213 Correct - next round please.
Помимо формата и дополнительных фигурных скобок, в вашем коде есть и другие проблемы, их слишком много, чтобы уместить их в комментарий.
Вы использовали светодиод1, светодиод2 и т. д. в процедуре настройки и использовали числа в функции цикла.
В начале цикла() вы включаете светодиоды вверх, а затем вниз, вы этого не увидите, потому что процессор работает быстрее, чем ваш глаз, вам нужен оператор задержки после последнего максимума и последнего минимума.
- Вы можете сделать свой код более элегантным, написав функцию, которая принимает контакт в качестве параметра и переключает высокий, а затем низкий уровень светодиода и вызывает это вместо повторения 4 строк кода.
void togglePin(int pinNumber, int interval) { digitalWrite(pin, HIGH); delay(interval); digitalWrite(pin, LOW); delay(interval); }
- Когда дело доходит до чтения значений, у вас есть блоки повторяющегося кода, опять же, это могут быть отдельные функции, которые облегчат чтение и понимание вашего кода.
Когда вы это сделаете, возможно, вам захочется немного изучить вопрос «устранения дребезга переключателей», потому что я предполагаю, что с этим у вас тоже могут возникнуть проблемы.
В вашем коде в том виде, в котором он написан, будут включены как wrongLED
, так и correctLED
. Он также будет непрерывно показывать последовательность.
Показ последовательности
Чтобы показать последовательность один раз в начале, поместите ее в функцию настройки. Подробнее о функции настройки читайте здесь: http://www.arduino.cc/en/Reference/Setup< /п>
Обнаружение нажатия кнопок
Вы хотите распознавать каждое нажатие кнопок. Для этого вам понадобится код обнаружения границ. В IDE есть встроенный в IDE пример Arduino, а информацию, описывающую функцию, можно найти здесь: http://www.arduino.cc/en/ Учебное пособие/StateChangeDetection
В дополнение к объяснению Arduino вы можете обнаружить либо нарастающий фронт (т. е. переход от LOW к HIGH), либо спадающий фронт (т. е. переход от HIGH к LOW). Лично я предпочитаю использовать следующий код для обнаружения нарастающего фронта:
if ( (lastButtonState == LOW) && (buttonState == HIGH) )
где buttonState
будет назначен digitalRead
, а lastButtonState
запишет значение buttonState
в конце функции цикла (т. е. непосредственно перед тем, как она снова прочитает состояния кнопки).
Используя глобальные массивы, вы можете написать:
buttonState[0] = digitalRead(button1);
buttonState[1] = digitalRead(button2);
buttonState[2] = digitalRead(button3);
buttonState[3] = digitalRead(button4);
if ( (lastButtonState[i] == LOW) && (buttonState[i] == HIGH) )
где i
— число от 0 до 3. Вы можете использовать цикл for для переключения между 4 доступными кнопками.
Запись нажатий кнопок
Приведенный выше пример StateChangeDetection подсчитывает количество нажатий кнопок. Вместо этого вы хотите записать 4 нажатия кнопок. Для этого создайте глобальную переменную с именем pressNumber
. Создайте его с начальным значением 0.
Создайте целочисленный массив из 4 элементов с именем userSequence.
Каждый раз, когда оператор if обнаруживает нарастающий фронт, сохраняйте номер кнопки в userSequence' в позиции
pressNumber, а затем увеличивайте
pressNumber`.
Когда pressNumber
достигает 4, пользователь ввел свое предположение.
Оценка предположения
Это происходит только после того, как пользователь ввел предположение. Начните с создания логической переменной и присвойте ей значение TRUE. Перебирайте элементы в массиве userSequence
и сравнивайте предположения пользователей с правильным ответом. Если пользователь ошибся, установите для логической переменной значение false. В конце включите красный светодиод или зеленый светодиод в зависимости от состояния логической переменной (т.е. если это правда, включите зеленый светодиод, в противном случае включите красный).
Заключительные замечания
- Как предлагает Мэтт, попробуйте рефакторинг частей кода в функции. Это делает код более читабельным и снижает его сложность.
Вы можете использовать переменные для номеров контактов кнопок и светодиодов в функциях
digitalWrite
иdigitalRead
. Например:digitalRead(button1); digitalWrite(led1);
- Как использовать SPI на Arduino?
- Как решить проблему «avrdude: stk500_recv(): programmer is not responding»?
- Как создать несколько запущенных потоков?
- Как подключиться к Arduino с помощью WiFi?
- avrdude ser_open() can't set com-state
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Я закирпичил свой Arduino Uno? Проблемы с загрузкой скетчей на плату
Сделайте себе одолжение и научитесь правильно делать отступы в коде., @Majenko
Что касается вашей проблемы: подумайте о паролях., @Majenko
Вы можете автоматически отформатировать свой код в Arduino IDE, зайдя в меню «Инструменты» и выбрав «Автоформат»., @sa_leinad
У вас слишком много закрывающих скобок., @sa_leinad
Проголосовали против, потому что вы не сказали, какая у вас проблема., @per1234