Weit weg kann ich nicht mehr wirklich sein..... ich da noch ein Problem mit der Trefferabfrage.....
Leider macht er´s nicht so wie´s sein soll. Die Punkte sollen nur gezählt werden wenn ein Treffer registriert wurde UND die dazugehörige Diode leuchtet. Von der Theorie her müssten die Dioden doch aufgrund der Arrays gleich zugeordnet sein, wie die Punkte zu den Zielen.....
// 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] {3, 4, 5, 6, 7};
// 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;
// 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(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() {
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)) && (true == (LED_PINS, index))) {
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);
}
}
Alternativ (Danke Kai-R)
Wokwi