Как считывать данные с трехкнопочного ввода?

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

Вот мой код:

int ledPin = 12;         
int buttonPin1 = 7;     
int buttonPin2 = 6; 
int buttonPin3 = 5;    

void setup() {
  Serial.begin(9600);          
  Serial.println("Setup start"); 
  pinMode(ledPin, OUTPUT);     
  pinMode(buttonPin1, INPUT_PULLUP); 
  pinMode(buttonPin2, INPUT_PULLUP); 
  pinMode(buttonPin3, INPUT_PULLUP);  
  randomSeed(analogRead(A0)); 
  Serial.println("Setup complete"); 
}

void loop() {
  Serial.println("Game start"); 
  digitalWrite(ledPin, HIGH);  
  delay(2000);                 
  delay(random(1000, 3000));  
  digitalWrite(ledPin, LOW);  
  Serial.println("LED off, waiting for button press"); 

  unsigned long start_time = millis(); 
  int winner = 0;
 
  while (winner == 0) { 
    winner = check_buttons();
  }

  unsigned long end_time = millis();  
  unsigned long total_time = end_time - start_time;  

  Serial.print("Player ");
  Serial.print(winner);
  Serial.println(" wins!");
  Serial.print("It took ");
  Serial.print(total_time);
  Serial.println(" ms to press the button.");

  delay(5000);  
}

int check_buttons() {
  int player1 = digitalRead(buttonPin1);
  int player2 = digitalRead(buttonPin2);
  int player3 = digitalRead(buttonPin3);

  if (player1 == LOW) {
    return 1;  
  } else if  (player2 == LOW) {
    return 2; 
  } else if (player3 == LOW) {
    return 3;  
  } else {
    return 0;  
  } 
}

, 👍0

Обсуждение

пока (второй == 0) ...?, @Juraj

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

«_Я хотел бы иметь возможность считывать все три кнопки, близкие к нулю_»: Что это значит?, @Edgar Bonet

А что, если все три игрока не нажмут на свои кнопки? В телевикторине люди часто сдаются, если кто-то другой нажал кнопку первым., @Nick Gammon


1 ответ


0

Вам понадобится переменная end_time для каждого игрока, либо как отдельная переменная для каждого игрока, либо используйте массив. Определите как глобальную:

unsigned long end_time_player1;
unsigned long end_time_player2;
unsigned long end_time_player3;

или

unsigned long end_time_player[3];

Затем в check_buttons() вам нужно будет записать соответствующее end_time, вот так

  if (player1 == LOW) {
    end_time_player[0] = millis();
    //end_time_player1 = millis();
    return 1;  
  } else if  (player2 == LOW) {
    end_time_player[1] = millis();
    //end_time_player2 = millis();
    return 2; 
  }else if (player3 == LOW) {
    end_time_player[2] = millis();
    //end_time_player3 = millis();
    return 3;  
  } else {
    return 0;  
  } 

Очевидно, что если используется массив, то индекс массива на единицу меньше номера игрока.


Массив, вероятно, более элегантен и расширяем, поэтому для четырех игроков:

const int kNumPlayers=4
unsigned long end_time_player[kNumPlayers];

Если вы используете массивы (как для времени, так и для кнопок (а также для игроков)), вы также можете превратить серию операторов if в цикл for с помощью kNumPlayers:

int buttonPin[kNumPlayers] = {7, 6, 5};

...

int check_buttons() {
  int player[kNumPlayers];

  for (n=0; n < kNumPLayers; n++) {
     player[0] = digitalRead(buttonPin[n]);
     if (player[0] == LOW) {
        end_time_player[n] = millis();
        return n+1;  
     } else {
        return 0;  
     }  
  } 
}

или, проще говоря, вообще отказаться от локальной переменной player

int buttonPin[kNumPlayers] = {7, 6, 5};

...

int check_buttons() {
  for (n=0; n < kNumPlayers; n++) {
     if (digitalRead(buttonPin[n]) == LOW) {
        end_time_player[n] = millis();
        return n+1; 
     } else {
        return 0;  
     }  
  } 
}

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

,

Да, а если кнопку не нажмет третий игрок? Или второй?, @Nick Gammon

Тогда дисплей в loop() не покажет значение для этого игрока или отобразит "n/a". Цикл while больше не должен будет ждать только одного победителя, а будет ждать *тайм-аут* (скажем, одну секунду, может быть, две). Если игрок не нажал кнопку в течение этого времени, то можно смело предположить, что он умер от скуки..! :-) Да, должен признать, что в loop() требуются некоторые необходимые изменения логики, которые я упустил из виду... хотя, справедливости ради, я оставил это на усмотрение автора, так как вопрос *казалось* был сосредоточен на чтении, а не на отображении., @Greenonline