Schüler brauchen hilfe für schulprojekt (kommen nicht mit taster zurecht) usw

hallöchen,
meine Technik gruppe in der Schule kommt beim programmieren nicht weiter (wir benutzen arduino IDE).
wir wollen ein "pferderennen" erstellen : Zwei Taster und zwei Reihen aus z.B. je 5 LEDs, die eine Pferderennbahn darstellen. Jeder Spieler hat einen Taster und eine Reihe LEDs. Auf ein Startzeichen hin, drücken die Spieler so schnell wie möglich wiederholt ihren Taster. Nach z.B. jedem 20ten Druck leuchtet eine weitere LED ihrer Reihe auf der Rennbahn auf. Der Spieler, bei dem zuerst alle 5 LEDs leuchten, hat gewonnen. Dann ertönt eine "Sieger"-Melodie. Es geht also darum, am schnellsten den Taster wiederholt zu drücken

unser bisheriger Code sieht so aus:

const int Taster_01 = 13;
const int Taster_02 = 12;
const int Lautsprecher = 1;
const int LED_01 [] = {11, 10, 9, 8, 7};
const int LED_02 [] = {6, 5, 4, 3, 2};
const unsigned int Startmelodie_Hoehe [] = {349, 349, 440, 391, 493,};
const unsigned int Startmelodie_Laenge [] = {400, 600, 200, 200, 800};
int var;
int Rueckgabe_01 = 0;
int Rueckgabe_02 = 0;

void setup() {
pinMode (Taster_01, INPUT);
pinMode (Taster_02, INPUT);
pinMode (Lautsprecher, OUTPUT);
for (int i = 0; i = 4; i++) {
pinMode (LED_01 [i], OUTPUT);
pinMode (LED_02 [i], OUTPUT);
}
}

void loop() {
while (digitalRead (Taster_01) + digitalRead (Taster_02) == 0) {
Startmelodie ();
}

Rueckgabe_01 = (digitalRead(Taster_01) * 1);
Rueckgabe_02 = (digitalRead(Taster_02) * 2);

switch (Rueckgabe_01) {
case 10:
digitalWrite (LED_01[0], HIGH);
break;
case 20:
digitalWrite (LED_01[1], HIGH);
break;
case 30:
digitalWrite (LED_01[2], HIGH);
break;
case 40:
digitalWrite (LED_01[3], HIGH);
break;
case 50:
digitalWrite (LED_01[4], HIGH);
break;
}
switch (Rueckgabe_02) {
case 20:
digitalWrite (LED_02[0], HIGH);
break;
case 40:
digitalWrite (LED_02[1], HIGH);
break;
case 60:
digitalWrite (LED_02[2], HIGH);
break;
case 80:
digitalWrite (LED_02[3], HIGH);
break;
case 100:
digitalWrite (LED_02[4], HIGH);
break;
}
}

void Startmelodie () {
while (var < 1) {
for (int Counter = 0; Counter < 4; Counter++) {
tone ( Lautsprecher, Startmelodie_Hoehe [Counter], Startmelodie_Laenge [Counter]);
delay (Startmelodie_Laenge [Counter] * 2);
}
var++;
}
}

wir wissen berspielsweise nicht, wie wir den Taster richtig auf HIGH und auf LOW stellen. habt ihr tipps wie der richtige code aussehen könnte?

Das macht der Taster, wenn man ihn drückt oder losläßt. Aber das wollt ihr vermutlich garnicht wissen?

Probiert doch erst einmal die IDE Beispiele für Buttons aus, dann wißt ihr wie Taster richtig angeschlossen und abgefragt werden.

Wie schon vorgeschlagen, schaut euch die Button Beispiele in der IDE an wenn ihr das habt gleich noch das Blink without delay beispiel und dann lest euch in das Thema Taster entprellen ein. Wenn das soweit klar ist, fangt klein an und macht ertmal eine LED und einen button, wo die LED nach 20x drücken das leuchten anfängt. Dann nehmt ihr einen zweiten button und eine zweite LED und baut das ganze simultan auf, dort kommt dann "blink without delay" zum einsatz. Und wenn das alles funktioniert, ist es ein leichtes das ganze um beliebig viele LEDs zu erweitern.

Aber fangt erstmal klein an, dann ist der Frust am anfang auch nicht so hoch, ganz im Gegenteil mit jedem Schritt der geschafft ist, steigt auch die Motivation und die Lernkurve ist viel höher.

Da wären dann natürlich noch verschiedene Grenzen zu überwinden, wenn es mehr als 2..3 * ( 5 LED + 1 Taster) werden. Aber auch dann gibt es Möglichkeiten.

Lernziel Arduino ist:

  1. Höllisch kompliziert, bis einfachste Sachen (Taster erfassen) gehen.
  2. Es geht erstaunlich viel, wenn man es richtig macht.
  3. Das Zusammenspiel mit der richtigen Hardware ist wichtig.

Ja gut für 10 LEDs und zwei Taster werden 12 Digital Pins benötigt. Plus nochmal einen für den Buzzer sind 13. Sollte so ein Uno schon hergeben. Und wenns dann doch mehr werden sollte kann man entweder Schieberegister verwenden oder auf einen Mega wechseln. Und wenn die Leds nicht den ganzen Raum ausleuchten sollen, sollte auch die Stromaufnahme bei > 10 Leds kein Problem darstellen.

Aber der Einwand von dir ist schon berechtigt.
Aber bis der Punkt erreicht ist an dem es nicht mehr weiter geht, sind wir noch nicht.

Hallo nwtsch07

Heute ist Montag und da bin ich immer der Spielverderber.

Vor der Programmierung startet ihr am Besten mit dem Studium des EVA-Prinzips, das die Aufgabestellung strukturiert.

Hier eine Kurzform:
Eingabe: Taster einlesen, entprellen und bewerten.
Verarbeitung: Zähler++ und Zähler=Zähler mod 12.
Ausgabe: Leds ansteuern.

Das kann man für eine "Pferderennbahn" programmieren und testen.
Und nun kann man überlegen, ob man mit COPY/PASTA den zweiten Knopf zum Spiel hinzufügt, oder aus einer "Pferderennbahn" ein Objekt erzeugt wird, das wiederum zweimal instanziert wird.

Da du der Projektleiter bist kannst du die Teilprojekte, EINGABE, VERARBEITUNG, AUSGABE, an das Team verteilen und so zusätzlich so ein bißl Projektmanagement und Projektarbeiten üben.

Ich wünsche einen geschmeidigen Tag und viel Spass beim Programmieren in C++.

Hallo,
dazu benötigt jeder Taster einen Zähler der immer dann um eins erhöht wird wenn seinen Zustand von ungedrückt auf gedrückt geändert wird.
Ich denke Ih fangt mal mit sowas für eine Taster an und lasst Euch den Zählerstand auf dem Monitor mit serial.print () anzeigen.

Dann solltet Ihr noch überlegen wie und wann der aktuelle Spielstand wieder zurück gesetzt wird und die LEDs wieder ausgehen.

Heinz
Nachtrag
@paulpaulson ich hatte bei meinem Post noch nicht alles gelesen , ist also ein bisschen doppelt jetzt.

Hallo,

die Bounce 2 Lib bringt alles mit was ihr für Tasterauswertungen benötigt. Geht die Bsp. durch und programmiert euch die Taster damit so das nur auf erneuten Tastendruck hin reagiert wird. Nicht auf gedrückt halten o.ä..

Wenn das funktioniert wird damit je Taster ein Zählerstand geändert der wiederum je nach Zählerstand die Leds steuert. Völlig simple Sache. :wink:

1 Like

Bevor ihr anfangt Euch in Drittcode einzulesen ein gut gemeinter Tipp: Einige Grundlagen logisch erarbeiten.

Taster haben mehrere Möglichkeiten des Anschlußes.
Eine Variante ist mit externem Widerstand und dann dort auch noch je nach Wunsch auf GND oder VCC.
Die andere Variante ist mit dem internen PULLUP zu arbeiten; Da sagts der Name schon, der ist fest mit VCC verbunden.
Dementsprechend ist auch mit der Logik umzugehen.
Geht der Widerstand nach VCC ist auf GND, mithin auf LOW, die Taste bei einem NO-Kontakt gedrückt.

Bei den Ausgängen habt ihr Euch verhauen:

Eigentlich sollte der Compiler das bemerken und Euch warnen, das das nicht funktioniert.
Da i nicht von allein 4 wird, wird also nix erreicht.
Da ihr 5 leds habt, könnte ein i <= 4 evtl. sinnvoll sein.

Allerdings würde ich das ganz anders lösen und mich trotzdem an Eurem Ansatz orientieren.

// Forensketch  Pferderennen
// https://forum.arduino.cc/t/schuler-brauchen-hilfe-fur-schulprojekt-kommen-nicht-mit-taster-zurecht-usw/1137055
/*
  Leider hat der TO sich 24 Stunden nicht mehr blicken lassen - damit ist die Reise hier zu Ende
  Der Codeansatz sollte aber nicht ganz umsonst gewesen sein.
  Für checkButton hatte ich noch eine dritte Idee, die die Zeiten gedrückt und ungedrückt berücksichtigt
  - Aber nicht mehr weiterverfolgt.
  Wer möchte kann ja drin rum machen. Es ist ungetestet, kompiliert aber
*/

constexpr byte spieler {2};
constexpr byte taster[spieler] {13, 12};
constexpr byte ledNums {5};
constexpr byte led[spieler][ledNums] {{11, 10, 9, 8, 7}, {6, 5, 4, 3, 2}};
byte zaehler[spieler] {0, 0};
constexpr byte teiler {20};              // Anzahl Anschläge je LED

constexpr bool gedrueckt = LOW;          // Hier wird festgelegt, auf welchen Pegel die Taste ausgelegt ist

constexpr byte Lautsprecher = A1;        // geändert

const unsigned int Startmelodie_Hoehe [] = {349, 349, 440, 391, 493,};
const unsigned int Startmelodie_Laenge [] = {400, 600, 200, 200, 800};
int var;

enum class SPIEL {warten, start, rennen};
SPIEL spiel = SPIEL::warten;

void setup()
{
  for (byte b = 0; b < spieler; b++)
  {
    /* mit externem Widerstand beschaltet */
    pinMode(taster[b], INPUT);
    /* alternativ */
    // pinMode(taster[b], INPUT_PULLUP);
    for (byte c = 0; c < ledNums; c++)
    {
      pinMode(led[b][c], OUTPUT);
    }
  }
  pinMode (Lautsprecher, OUTPUT);
}


void loop()
{
  if (spiel != SPIEL::rennen)                         // kein aktives rennen
  {
    if (digitalRead(taster[0]) == gedrueckt &&        // Tasten Spieler 1 + 2 ausgelöst
        digitalRead(taster[1]) == gedrueckt)
    {
      spiel = SPIEL::start;                           // ;-)
    }
  }
  switch (spiel)
  {
    case SPIEL::warten:                               // einfach nix tun
      break;
    case SPIEL::start:                                // wird ausgelöst wenn beide Tasten gedrückt wurden
      for (byte b = 0; b < spieler; b++)
      {
        zaehler[b] = 100;                             // Sorgt dafür, das alle LED's leuchten
      }
      if (digitalRead(taster[0]) == !gedrueckt &&     // Es müssen beide Tasten losgelassen sein!
          digitalRead(taster[1]) == !gedrueckt)
      {
        Startmelodie ();                              //
        spielReset();                                 // lässt die LED's ausgehen
        spiel = SPIEL::rennen;                        // nächster Schritt
      }
      break;
    case SPIEL::rennen:
      for (byte b = 0; b < spieler; b++)
      {
        checkButton();
        if (zaehler[b] >= 100)
        {
          spiel = SPIEL::warten;
        }
      }
      break;
  }
  for (byte b = 0; b < spieler; b++)
  {
    auswertung(b);
  }
}
//
void Startmelodie ()
{
  while (var < 1)
  {
    for (int Counter = 0; Counter < 4; Counter++)
    {
      tone ( Lautsprecher, Startmelodie_Hoehe [Counter], Startmelodie_Laenge [Counter]);
      delay (Startmelodie_Laenge [Counter] * 2);
    }
    var++;
  }
}
// Variante 1
void checkButton()
{
  constexpr uint32_t debounceTime {25};
  static bool ausgeloest[spieler] = {false};
  static uint32_t startTime[spieler] = {0};
  for (byte b = 0; b < spieler; b++)
  {
    if (digitalRead(taster[b]) == gedrueckt)           // Taste ausgeloest
    {
      if (!ausgeloest[b])                              // vorher nicht ausgeloest
      {
        startTime[b] = millis();                       // Auslösezeit merken
        ausgeloest[b] = true;                          // ausgeloest merken
        zaehler[b]++;
      }
    }
    else                                            // taste losgelassen
    {
      if (millis() - startTime[b] > debounceTime)      // und debounce abgelaufen
      {
        ausgeloest[b] = false;
      }
    }
  }
}

// Variante 2
/*
  void checkButton()
  {
  constexpr uint32_t debounceTime {25};
  static bool ausgeloest[spieler] = {false};
  static uint32_t startTime[spieler] = {0};
  for (byte b = 0; b < spieler; b++)
  {
    if (digitalRead(taster[b]) == gedrueckt)           // Taste ausgeloest
    {
      if (!ausgeloest[b])                              // vorher nicht ausgeloest
      {
        startTime[b] = millis();                       // Auslösezeit merken
        ausgeloest[b] = true;                          // ausgeloest merken
        gezaehlt[b] = false;                           // zaehlmerker löschen
      }
      else if (!gezaehlt[b])                           // ausgelöst und noch nicht gezaehlt?
      {
        if (millis() - startTime[b] > debounceTime)    // und debounce abgelaufen
        {
          zaehler++;                                   //
          gezaehlt[b] = true;                          // merken, das gezaehlt wurde
        }
      }
    }
    else                                               // taste losgelassen
    {
      ausgeloest[b] = false;                           // Merker löschen
    }
  }
  }
*/
//
void spielReset()
{
  for (byte b = 0; b < spieler; b++)
  {
    zaehler[b] = 0;
    for (byte c = 0; c < ledNums; c++)
    {
      digitalWrite(led[b][c], LOW);
    }
  }
}
//
void auswertung(const byte line)
{
  switch (zaehler[line])
  {
    case teiler*5:
      digitalWrite(led[line][4], HIGH);
      [[fallthrough]];
    case teiler*4:
      digitalWrite(led[line][3], HIGH);
      [[fallthrough]];
    case teiler*3:
      digitalWrite(led[line][2], HIGH);
      [[fallthrough]];
    case teiler*2:
      digitalWrite(led[line][1], HIGH);
      [[fallthrough]];
    case teiler:
      digitalWrite(led[line][0], HIGH);
      break;
  }
}
2 Likes

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.