Skocz do zawartości

Problem z falstartem w grze


Pomocna odpowiedź

Napisano

Witam serdecznie
To mój pierwszy temat, ponieważ dopiero uczę się, proszę o łagodne potraktowanie, a przede wszystkim o pomoc/podpowiedź.
Mianowicie chcę rozbudować nw program/grę na refleks pochodzącą z:

https://www.instructables.com/Arduino-Reflex-Tester/

o wykrywanie falstartu. Ponieważ obecnie trzymając button jeszcze przed zapaleniem zielonej diody, gdy zapali się zielona dioda to czas reakcji wynosi 0,01s. Podjąłem próbę i rozbudowałem o "if" sprawdzający czy przytrzymany jest przycisk:

if (digitalRead(btnPin) == HIGH){    
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("   False start!  ");
      lcd.setCursor(0,1);
      lcd.print(" !!!!!!!!");
      digitalWrite(ledPin, LOW);
      delay(2000);
    } 

Niestety rozwiązuje to problem tylko cząstkowo i tylko gdy w momencie zapalenia zielonej diody trzymany jest button to wyświetli "False start".
Jednak wcześniej w przedziale losowym czasu random(500, 5000) czekając na zapalenie zielonej diody - jeśli klikam button to nic się nie dzieje, nie wyświetla falstartu.
Domyślam się, że to dlatego, że wszystko wstrzymuje delay(number), a mój "if" działa dopiero po wykonaniu delay(number). Czytałem, że delay() najlepiej zastąpić millis(), ale za bardzo nie wiem jak w tym przypadku zastosować 😞 a w sieci gównie są przykłady na diodach, bez przerwania procedury w chwili użycia przycisku. Którego może ja nie potrafię przystosować do mojego problemu.

Czy podpowiecie nowicjuszowi czego i jak użyć?

Poniżej cały kod:

include <Wire.h>  
#include <LiquidCrystal_I2C.h>
 
#define ledPin 8 
#define btnPin 4
 
double number;
long sTime;
 
LiquidCrystal_I2C lcd(0x27,16,2);
 
void setup() {
  Serial.begin(9600);
  lcd.begin();  
  lcd.setCursor(0,0);
  pinMode(btnPin, INPUT);
  pinMode(ledPin, OUTPUT);
}
 
void loop() { 
    number = random(500, 5000);
    lcd.print("Wait for the LED"); 
    delay(number);

   if (digitalRead(btnPin) == HIGH){     //jesli trzymany button to falstart
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("   false start! ");
      lcd.setCursor(0,1);
      lcd.print(" !!!!!!!!");
      digitalWrite(ledPin, LOW);
      delay(2000);
    } 
    lcd.clear();
    lcd.print("     PRESS!");
    digitalWrite(ledPin, HIGH);
    sTime = millis();
 
    while (digitalRead(btnPin) == LOW);
 
    lcd.clear();
    lcd.print(" Reaction time: ");
    lcd.setCursor(0,1);
    lcd.print("      ");
    lcd.print((millis() - sTime) / 1000.0);
    lcd.print(" s");
    
    delay(2000);
 
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("  Another test");
    lcd.setCursor(0, 1);
    lcd.print("  in 5 seconds");
    delay(5000);
    lcd.clear();
    digitalWrite(8, LOW);
}

 

No najlepiej millis() uzyc...pasuje tez jakos ten kod przerobic z uzyciem switch()-case naprzyklad...bo tak jak teraz to nie zadziala po prostych przerobkach (taka "wada" millis()), ale jak juz ogarniesz to strasznie sobie zycie ulatwisz😉 

A swoja droga to masz rezystor podciagajacy pin do masy? Bo jesli nie to predzej czy pozniej czekaja Cie problemy...

4 minuty temu, farmaceuta napisał:

No najlepiej millis() uzyc...pasuje tez jakos ten kod przerobic z uzyciem switch()-case naprzyklad...bo tak jak teraz to nie zadziala po prostych przerobkach (taka "wada" millis()), ale jak juz ogarniesz to strasznie sobie zycie ulatwisz😉 

A swoja droga to masz rezystor podciagajacy pin do masy? Bo jesli nie to predzej czy pozniej czekaja Cie problemy...

heh tylko ja właśnie nie za bardzo wiem jak w moim przypadku użyć millis() 😞 ale poszperam przykłady z switch()-case i może mnie oświeci

tak, rezystor 10k od tact-switcha podłaczony do GND 🙂

Chodzi o coś w stylu:

    lcd.print("Wait for the LED"); 
    
    unsinged long waitUntil = millis() + random(500, 5000); //czas końcowy = teraz + losowa liczba milisekund
    while (millis() < waitUntil) {
        if (digitalRead(btnPin) == HIGH){     //jesli trzymany button to falstart
            lcd.clear();
            lcd.setCursor(0,0);
            lcd.print("   false start! ");
            lcd.setCursor(0,1);
            lcd.print(" !!!!!!!!");
            digitalWrite(ledPin, LOW);
            delay(2000);
            
            return;
        } 
    }

 

  • Lubię! 1
  • Pomogłeś! 1
  

include <Wire.h>  
#include <LiquidCrystal_I2C.h>
 
#define ledPin 8 
#define btnPin 4
 
int number;
long sTime;
 
LiquidCrystal_I2C lcd(0x27,16,2);
 
void setup() {
  Serial.begin(9600);
  lcd.begin();  
  lcd.setCursor(0,0);
  pinMode(btnPin, INPUT);
  pinMode(ledPin, OUTPUT);
}
 
void loop() { 
  delay(2000);
    number = random(500, 5000);
    lcd.clear();
    lcd.print("Wait for the LED"); 
    
 while(number) {
   if (digitalRead(btnPin) == HIGH){     //jesli trzymany button to falstart
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("   false start! ");
      lcd.setCursor(0,1);
      lcd.print(" !!!!!!!!");
      digitalWrite(ledPin, LOW);
      return;
    } 
   number--;
   delay(1);
   }
    lcd.clear();
    lcd.print("     PRESS!");
    digitalWrite(ledPin, HIGH);
    sTime = millis();
 
    while (digitalRead(btnPin) == LOW);
 
    lcd.clear();
    lcd.print(" Reaction time: ");
    lcd.setCursor(0,1);
    lcd.print("      ");
    lcd.print((millis() - sTime) / 1000.0);
    lcd.print(" s");
    
    delay(2000);
 
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("  Another test");
    lcd.setCursor(0, 1);
    lcd.print("  in 5 seconds");
    delay(5000);
    lcd.clear();
    digitalWrite(8, LOW);
}
 

 Dostane pewnie opierdziel za takie wynalazki skoro byla mowa o millis() i o tym jakim zlem jest delay()...ale co tam😜

E tam - delay jest po to żeby z niego korzystać tam gdzie trzeba. A opierdziel to sam sobie dasz jak przeanalizujesz co się stanie, jeśli uruchomisz to na ESP32 i przytrzymasz klawisz na jakieś dwie sekundy 😉

(edytowany)

blokujesz program na czas kiedy przycisk jest wciśnięty, można to zrobić lepiej dzięki funkcji millis(); i maszynie stanów, choć pewnie arduino ma już jakąś funkcję debounce

Edytowano przez _LM_
15 minut temu, etet100 napisał:

Na pewnym etapie wiedzy jest to jak jak najbardziej tak.

Nigdzie nie pisałem że konstrukcja jest "nie tak" - jedynie że należy jej unikać (niezależnie od etapu wiedzy). Podobnie zresztą jak delay - do czegoś służy, tylko trzeba stosować umiejętnie. O goto już przez grzeczność nie wspomnę...

Każdy początkujący w końcu dojdzie do tego momentu, kiedy będzie chciał robić kilka rzeczy jednoczesnie i wtedy zdaje sobie sprawę, że na funkcji delay tego nie zrobi. To jest dla niektórych dość trudny moment, jak nie programować liniowo. 

Moim zdaniem niema na co czekać tylko od razu stosować takie rozwiązania. Niewiele jest kursów internetowych które od razu pokazują jak nie blokować programu wszechobecnymi delayami, a tłumaczą czym jest i do czego służy timer programowy i maszyna stanów. Tak samo z bibliotekami np: od adafruit - czujnik który mógłby zrobić pomiar i konwersję w kilkanaście ms, robi to znacznie dłużej bo program wiecznie na coś czeka. 

  • Lubię! 1

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...