// Bibliotheken einbinden
#include <Wire.h> // Wire Bibliothek einbinden
#include <LiquidCrystal_I2C.h> // Vorher hinzugefügte LiquidCrystal_I2C Bibliothek einbinden
LiquidCrystal_I2C lcd(0x27, 16, 2); //Hier wird festgelegt um was für einen Display es sich handelt. In diesem Fall eines mit 16 Zeichen in 2 Zeilen und der HEX-Adresse 0x27. Für ein vierzeiliges I2C-LCD verwendet man den Code "LiquidCrystal_I2C lcd(0x27, 20, 4)"
// Pins für Targets festlegen -> 10mm Target (A1) bis 50mm Target (A5) - A0 dient zur Rückstellung der Punkte
constexpr byte TARGET_PINS[] {A1, A2, A3, A4, A5, A0};
constexpr byte NUM_TARGET_PINS {sizeof(TARGET_PINS) / sizeof(TARGET_PINS[0])};
//------------------------- ab hier Random LED´s
using uint = unsigned int;
using ulong = unsigned long;
constexpr byte LED_PINS[5] {7, 6, 5, 4, 3};
// Time im milliseconds (ms)
constexpr ulong LIGHT_DELAY_MS {3000}; // Time between two LDR measurements
class Interval {
public:
bool operator()(const ulong duration) {
if (false == isStarted) { return start(false); }
return (millis() - timeStamp >= duration) ? start(true) : retFalse();
}
private:
bool start(bool state = false) {
isStarted = !state; // Set the value to true on the first call
timeStamp = millis();
return state;
}
bool retFalse() { return false; }
private:
bool isStarted {false}; // Flag = true if the first Operator() call has been made.
ulong timeStamp {0};
};
Interval timer;
template <size_t N> void setLeds(const byte (&pins)[N], byte &lastIdx ){
byte idx;
do { // Prevents the same (random)number from being used twice in a row.
idx = random(0, N);
} while (idx == lastIdx);
digitalWrite(pins[lastIdx], LOW);
lastIdx = idx;
digitalWrite(pins[idx], HIGH);
}
//------------------------- bis hier Random LED´s
// Punkte für 10mm Target bis 50mm Target - 0 Punkte zur Rückstellung der Punkte
constexpr byte T_POINTS_VALUE[NUM_TARGET_PINS] {50, 40, 30, 20, 10, 0};
// Startpunkte auf 0
unsigned int score = 0;
int Piezo = 2;
int resetTaster = 8;
int resetStatus = 0;
// Abfrage der Pins - N enthält die Anzahl der Pins
template <size_t N> bool checkPins(const byte (&pins)[N], byte &index) {
for (; index < N; ++index) {
if (HIGH == digitalRead(pins[index])) { return true; }
}
return false;
}
uint8_t numDigits(unsigned int number) {
uint8_t digits = (number == 0) ? 1 : 0;
while (number) {
number /= 10;
++digits;
}
return digits;
}
void reset(){ // Reset wenn Treffer = 0 Punkte, Kontakt an A0
lcd.setCursor(10, 0);//Hier wird die Position des ersten Zeichens festgelegt. In diesem Fall bedeutet (0,0) das erste Zeichen in der ersten Zeile.
lcd.print(" ");
lcd.setCursor(8, 1);//Hier wird die Position des ersten Zeichens festgelegt. In diesem Fall bedeutet (0,0) das erste Zeichen in der ersten Zeile.
lcd.print(" ");
}
void setup() {
//Serial.begin(9600);
Serial.begin(19200);
for (auto pin : TARGET_PINS) {
for (auto pin : LED_PINS) { pinMode(pin, OUTPUT); }
randomSeed(A7);
pinMode(pin, INPUT);
pinMode(resetTaster, INPUT);
pinMode(Piezo, OUTPUT);
lcd.init(); //Im Setup wird der LCD gestartet
lcd.backlight(); //Hintergrundbeleuchtung einschalten (lcd.noBacklight(); schaltet die Beleuchtung aus).
lcd.setCursor(0, 0);//Hier wird die Position des ersten Zeichens festgelegt. In diesem Fall bedeutet (0,0) das erste Zeichen in der ersten Zeile.
lcd.print("Treffer :");
lcd.setCursor(0, 1);// In diesem Fall bedeutet (0,1) das erste Zeichen in der zweiten Zeile.
lcd.print("Gesamt : ");
//lcd.print(score);
}
}
void loop() {
// Taster abfragen
resetStatus = digitalRead(resetTaster);
if (resetStatus == HIGH) {
reset();
}
static unsigned int oldScore {0};
static byte currentLedIndex {0};
if (true == timer(LIGHT_DELAY_MS)) { setLeds(LED_PINS, currentLedIndex); }
byte index {0};
// Es wurde ein Treffer registriert. Je nach Index von 10mm (0) bis 50mm (4)
if ((true == checkPins(TARGET_PINS, index)) && (index == currentLedIndex)) {
digitalWrite(Piezo, HIGH);
delay(50);
digitalWrite(Piezo, LOW);
delay(250);
lcd.setCursor(10, 0);//Hier wird die Position des ersten Zeichens festgelegt. In diesem Fall bedeutet (0,0) das erste Zeichen in der ersten Zeile.
lcd.print(T_POINTS_VALUE[index]);
delay(500);
score = (T_POINTS_VALUE[index] > 5) ? score + T_POINTS_VALUE[index] : 0;
reset();
oldScore = score;
lcd.setCursor(9, 1);//Hier wird die Position des ersten Zeichens festgelegt. In diesem Fall bedeutet (0,0) das erste Zeichen in der ersten Zeile.
lcd.print(score);
}
}