Hallo!
Ich habe in der Hochschule ein Projekt bekommen, was ich auf einem Arduino Mega 2560 programmieren soll - ein Reaktionsspiel.
Grundsätzlich soll der Ablauf so aussehen:
1 Zufallszahl zwischen 1...9 wird generiert
2 digitaler Ausgang der Zufallszahl soll auf 1 gesetzt werden --> LED leuchtet [hier hätte ich gern die erste Zeit abgefragt = "t1"]
3 dann wird eine vordefinierte Reaktionszeit "tr" gewartet (Timer von "tr" --> 0)
3.1 in dieser zeit wird der richtige Eingang betätigt (Taster, wird in einer if oder while schleife abgefragt, weswegen delay() nicht verwendbar ist) --> ein zähler wird um 1 erhöht und "tr" um einen wert verringert
3.2 in dieser zeit wird nicht der richtige / gar kein Eingang betätigt;
bei ablauf von "tr" springt er aus der schleife
4 LED wird ausgeschaltet
--> wieder von vorn
ich habe keine möglichkeit gefunden einen derartigen timer einzufügen, und verstehe ehrlich gesagt die timer 0-5 auch nicht wirklich...
bzw weiß nicht wie ich die einbinden könnte.
Achtung: Da die Funktion millis() einen Wert zurückgibt, der 32 Bit breit ist, kann es je nachdem, wie man die Bedingung formuliert, nach rund 49 Tagen zu Überlaufproblemen kommen.
...
Besser:
if(millis() - millisMem < …)
allgemein verständlich ist > statt < wegen problemlosen Überlauf
if (millis() - last_millis > intervall) { ... }
Um die Hardware kümmert sich ein Kollege - die LEDs werden nicht direkt angesteuert, sondern über einen LN2803a (Stromproblem gelöst :D), und ja wir haben an den Vorwiderstand gedacht.
(Bin Elektroniker, also sowas geht!)
Aufbau: Neun LEDs und neun Taster <-- basically
Die Idee mit millis() hatte ich schon:
unsigned long t0; // start
unsigned long t1; // LED ein
unsigned long t2; // LED aus
unsigned long t3;
unsigned long t4;
unsigned long t5;
snowpanter:
Sieht jmd was falsch is und mag es mir evtl. erklären?
t0 = millis(); hat die falsche Position, bei t1 hast Du das besser gemacht.
Außerdem wird loop() ständig durchlaufen. Duch t1=0 als Anfangswert wird die zweite Bedingung immer wahr sein. Auch wenn die erste Bedingung die LED an machen möchte, wird sie danach gleich wieder aus gemacht. Lösung: Wenn LED aus, warte, dann mache sie an, sonst warte und mache sie aus.
zu Beginn habe ich alle Variablen "0" gesetzt, damit keine "Leichen" im Programm sind.
t0 soll die Startzeit des Ablaufs erfassen, unabhängig von den Schleifen --> was ist daran falsch?
t1 wird in der ersten Schleife gesetzt, und erst in der 2. Schleife verwendet --> die Zuweisung erfolgt vor der Verwendung, quasi: t1=0 ... t1=millis() ... t1 wird verwendet
wie warte ich denn?
(wo wir wieder bei dem timer sind^^
da lobe ich mit SPS - s5time ... gaaanz einfach)
Wie gesagt, die zusätzlichen Abfragen kann ich machen, aber ich bekomme keinen Timer gebaut.
Was ich da gepostet habe, hätte nach meiner Logik blinken sollen - als Test der Antworten vorher quasi.
Das ENDproblem ist das komplette Programm, aber Schritt für Schritt laufen lernen ist meine Devise
if(millis() - t0 > 500) // Abfrage d(t0) >= 500
{
digitalWrite(13, HIGH); // LED ein
t1 = millis(); // Anschaltzeit LED erfassen
}
if(millis() - t1 > 500) // Abfrage d(t1) >= 500
{
digitalWrite(13, LOW); // LED aus
}
}
funktioniert auch nicht...
ich vermute das problem ist zwischen t0 und der abfrage ob t0 500 ms größer ist als die aktuelle zeit, nur weiß ich nicht wieso.
aber ich nehme gern vorschläge an wie es funktional wird
guntherb:
aber es hilft wirklich ungemein, das mit den millis() zu verstehen.
Absolut richtig!
Möglicherweise hängt das Verständnis aber auch bei der Ablaufsteuerung. Eigentlich sollen ja mehrere Dinge in einer bestimmten Reihenfolge abgearbeitet werden. Ich habe daher mal ein chaotisches (nicht im mathematischen Sinne) Blinkprogramm gemacht:
const byte ledPin = 13;
unsigned long aktMillis, prevMillis, intervall;
byte status = 0;
void setup() {
pinMode(ledPin, OUTPUT);
}
void loop()
{
aktMillis = millis();
switch (status) {
case 0:
if (aktMillis - prevMillis >= intervall) {
prevMillis = aktMillis;
digitalWrite(ledPin, !digitalRead(ledPin));
intervall = 500;
status = 1;
}
break;
case 1:
if (aktMillis - prevMillis >= intervall) {
prevMillis = aktMillis;
digitalWrite(ledPin, !digitalRead(ledPin));
intervall = 1000;
status = 2;
}
break;
case 2:
if (aktMillis - prevMillis >= intervall) {
prevMillis = aktMillis;
digitalWrite(ledPin, !digitalRead(ledPin));
intervall = 100;
status = 0;
}
break;
}
}
Die Nachtwächter-Geschichte nicht zu verstehen, geht nicht.
Den BlinkWithoutDelay Code solltest du gefunden haben.
Grundlegende C Syntax-Kenntnisse ( wofür die vielen Semikolons ? ) scheinen auch da zu sein.
Das ganze wird einfacher, wenn du loop() nicht als Programmablauf siehst, sondern als momentane Zustandsbeschreibung, in der normalerweise nur festgestellt wird, dass gerade jetzt nichts zu tun ist.
(Der Nachtwächter braucht für seine Runde keine Zeit, jedenfalls weniger als eine Millisekunde)
Wenn du denkst, BlinkWithoutDelay hast du verstanden, aber agmues Abwandlung ist unklar, kannst du ja mal deine Verständnis-Unklarheiten beschreiben.
Wenn du erklären kannst, was die erste Zeile von deiner Funktion loop() t0=0;
bedeutet, wird uns eventuell klar, was dein Problem ist.
Wenn wir uns einig sind, dass sie sinnlos aber nicht störend ist, mach sie trotzdem weg
Nebenbei:
Was eher verwirrt ist, dass du von Timern redest, aber eigentlich Software-Funktionen meinst.
In µControllern sind nämlich auch Hardware-Timer vorhanden, die hier aber nicht gemeint sind.