PlatformIO Community

Time(0) always returns 0

/*
Autor: Ilhomjon Matjokubow
Programm: main.cpp
Zweck: Reaktionsspiel
*/

/*
############################################################
WICHTIG!!! Checkliste für Button Class:
  + BOUNCE_TIME muss definiert sein CHECK
  + Button btn1 (pinNr, isLowActive, bounceTime) muss definiert sein CHECK
  + btn1.begin() muss im setup() initialisiert sein CHECK
  + init7Seg() muss im setup() initialisiert sein CHECK
  + btn1.update muss im loop() sein CHECK

  Folgende Zustände gibt es:
  + btn1.isPressed()
  + btn1.hasPressed()
  + btn1.hasClicked()
############################################################
*/

/*
Aufgabe: Reaktionsspiel
Details:
  Entwickle ein einfaches Reaktionsspiel für zwei Teilnehmer.
  Das Spiel soll über 10 Runden gehen.
  Das Spiel soll die durchschnittliche Reaktionszeit für jeden Spieler anzeigen und wie viele Runden er gewonnen hat.
  Das Spiel soll mit dem mittleren Button gestartet werden (Button 2) und nach 2-4 Sekunden (zufällige Zeit) die erste Runde starten, bzw. (automatisch, ohne mittleren Button) die nächste Runde starten.
  Sobald die oberste LED aufleuchtet, sollen die Spieler so schnell wie möglich auf ihre Taste (Button 1 und 3) drücken.
  Wenn ein Spieler zu früh seinen Button drückt, hat er automatisch die Runde verloren. Diese Runde zählt dann nicht zu seiner durchschnittlichen Reaktionszeit.
  Wenn ein Spieler nicht innerhalb von drei Sekunden reagiert, soll automatisch die nächste Runde beginnen. Seine Reaktionszeit für diese Runde sind dann drei Sekunden. (Beachte, dass wenn beide Spieler nicht drücken, ist die Runde für beide Spieler verloren.
  Am Ende des Spiels sollen für jeden Spieler die Anzahl der Siege, die durchschnittliche, die minimale und die maximale Reaktionszeit angezeigt werden. Durch Drücken des mittleren Buttons (Button 2) soll ein neues Spiel gestartet werden.
  Bitte überlege dir ein sinnvolles Menü und ein sinnvolles Userinterface im Seriellen Monitor.
  Im Programm darf kein delay() verwendet werden (Zeitmessungen mit millis()! )
  Verwende die gemeinsam entwickelte Button-Klasse.

TODO:
  3 Buttons initialisiert CHECK
  1 LED initialisert CHECK
  random funktion
  Zu früh/Zu spät implementieren
  Durchschnittliche Reaktionszeit anzeigen
  Rundenzähler implementieren
  Minimale/Maximale Reaktionszeit anzeigen
  Siege anzeigen
  Menü + UI im Serial Monitor

  Aufgabenstellung:
    LEDs für eine gewisse Zeit leuchten lassen und auf button warten
*/
#include <Arduino.h>
#include "MFShield_Pins.h"
#include "Button.h"
#include <time.h>

//Bounce time wird definiert
#define BOUNCE_TIME 2

//Buttons werden definiert
Button btn1 (BUTTON1, true, BOUNCE_TIME);
Button btn2 (BUTTON2, true, BOUNCE_TIME);
Button btn3 (BUTTON3, true, BOUNCE_TIME);

enum Rounds {NONE, ROUND1, ROUND2, ROUND3, ROUND4, ROUND5, ROUND6, ROUND7, ROUND8, ROUND9, ROUND10};
Rounds rounds = NONE;

bool roundFinished = false;
unsigned int randNumber; //diese Zahl wird unsere Zufällige Zahl
unsigned long startTime, currentTime; //Zeit die seit dem Zählen vergangen ist, aktuelle Zeit
void startRound();

void setup() {
  // put your setup code here, to run once:

  init7Seg(); //7 Segment Anzeige wird deaktiviert
  pinMode(LED1, OUTPUT); //LED wird initialisiert
  //Buttons werden initialisiert
  btn1.begin(); 
  btn2.begin();
  btn3.begin();

  digitalWrite(LED1, HIGH); //LED1 wird ausgeschaltet

  Serial.begin(9600);

  randomSeed(time(0));
  randNumber = random(2000,4000);
  startTime = millis();
  Serial.println(randNumber);
  Serial.println((int)time(0));
}


void loop() {
  //Buttons werden auf ihren Status geupdated
  btn1.update();
  btn2.update();
  btn3.update();

  /*Serial.println(startTime);
  Serial.print("CurrentTime: ");
  Serial.println(currentTime);*/

  if (btn2.hasClicked())
  {
    rounds = ROUND1;
  }
  

  //go through all 10 rounds
  switch (rounds)
  {
  case ROUND1:
    startRound();
    if (roundFinished == true)
    {
      break;
      rounds = ROUND2;
    }

  case ROUND2:
    startRound();
    if (roundFinished == true)
    {
      break;
      rounds = ROUND3;
    }

  case ROUND3:
    startRound();
    if (roundFinished == true)
    {
      break;
      rounds = ROUND4;
    }

  case ROUND4:
    startRound();
    if (roundFinished == true)
    {
      break;
      rounds = ROUND5;
    }

  case ROUND5:
    startRound();
    if (roundFinished == true)
    {
      break;
      rounds = ROUND6;
    }

    case ROUND6:
    startRound();
    if (roundFinished == true)
    {
      break;
      rounds = ROUND7;
    }

  case ROUND7:
    startRound();
    if (roundFinished == true)
    {
      break;
      rounds = ROUND8;
    }

  case ROUND8:
    startRound();
    if (roundFinished == true)
    {
      break;
      rounds = ROUND9;
    }

  case ROUND9:
    startRound();
    if (roundFinished == true)
    {
      break;
      rounds = ROUND10;
    }

  case ROUND10:
    startRound();
    if (roundFinished == true)
    {
      break;
      //TODO: Print Ergebnis
    }
  
  default:
    break;
  }
}

void startRound() {
  roundFinished = false;
  currentTime = millis();
  //Serial.println(startTime);
  /*Serial.print("CurrentTime: ");
  Serial.println(currentTime);*/

  if (currentTime - startTime >= randNumber)
  {
    digitalWrite(LED1, LOW);
  }

  if (btn1.hasClicked())
  {
    digitalWrite(LED1, HIGH);
  }
  
  roundFinished = true;
}
#include <time.h>

void setup() {
    Serial.begin(9600);
}

void loop() {
    Serial.println(time(0));
    delay(500);
}

gives the following:

12:04:36.358 -> 0
12:04:36.857 -> 0
12:04:37.355 -> 0
12:04:37.854 -> 0
12:04:38.352 -> 0
12:04:38.851 -> 0
12:04:39.348 -> 0
12:04:39.847 -> 0
12:04:40.345 -> 0
12:04:40.844 -> 0
...

So it looks like the result will be zero, as the Arduino doesn’t have a real time clock, nor does it have any other “clock” facilities. Is millis() no good? Failing that, I have seen some code that reads one of the analogue pins and as long as that pin is floating, pretty random results occur. For xample:

void setup() {
  Serial.begin(9600);

}

void loop() {
  Serial.println(analogRead(0));
  delay(500);
}

This gives the following output:

12:12:15.765 -> 435
12:12:16.263 -> 419
12:12:16.795 -> 407
12:12:17.293 -> 399
12:12:17.791 -> 392
12:12:18.289 -> 410
12:12:18.787 -> 390
12:12:19.286 -> 382
12:12:19.784 -> 379
12:12:20.282 -> 368
12:12:20.780 -> 381
12:12:21.278 -> 362
12:12:21.777 -> 364
12:12:22.275 -> 384

It changes if you move your hands closer to the board, or even touch it.

HTH

Cheers,
Norm.

1 Like

AVR GCC toolchain (+ framework code) doesn’t give you a working time out of the box, see avr-libc: <time.h>: Time

There is no ‘platform standard’ method to obtain the current time, time zone, or daylight savings ‘rules’ in the AVR environment. Therefore the application must initialize the time system with this information. The functions set_zone(), set_dst(), and set_system_time() are provided for initialization. Once initialized, system time is maintained by calling the function system_tick() at one second intervals.

See randomSeed() - Arduino Reference for initializing the RNG.