Verständnissproblem mit loop von einem Neuen

Hallo,
ich versuche mich gerade in die Arduinowelt einzuarbeiten. Mit Hilfe des Internets und dem Buch Arduino Praxiseinstieg geht das auch ganz gut.
Jetzt aber zu meiner Frage:
Im unten angehängten Sketch läuft die loop ja immer schrittweise ab. d.h.
Wenn ich jetzt den Analogewert des Potis einlese, berechne und auf dem angeschlossenen Disply anzeige, muss ich in der vorletzten Zeile Delay auf min. 1000 setzten um was auf der Anzeige zu sehen. Was ja an und für sich kein Problem wäre, aaaber:

Parallel dazu schalte ich mit einem Sensortaster die LED am Ausgang 13. Durch die Loop wir jetzt erst der Potiwert gelesen dann berechnet und dann angezeigt. Danach kommt eben erst mit der Zeitverzögerung mein Schalter ins Spiel.

1.Wie kann man das parallel ablaufen lassen? Zwei Loops gehen ja nicht.
2. Warum braucht das DIsplay einen Deley um den Wert anzuzeigen?
Danke für eure Mithilfe.

int LED = 13;
int Sensor = 5; // Der Ausgang des Sensors wird an Pin 5 angeschlossen
int val = 0;
float poti;
int potiPin = 0;
int ledPin = 3;

void setup() {

pinMode(LED, OUTPUT);
pinMode (Sensor, INPUT);
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
Serial.print(124, BYTE); // 124 bzw. 0x7C- Befehl für Displaybeleuchtung
Serial.print (157, BYTE); // 128 (Disply off) - 157 (Display 100%)
//30 Helligkeitsstufen durch PWM
}

void loop() {
val = digitalRead (Sensor);

if (val == HIGH){
digitalWrite (LED, HIGH);}
else {
digitalWrite (LED, LOW);}
poti = analogRead(potiPin);
poti = (poti / 4.016);
Serial.print(254, BYTE);
Serial.print(128, BYTE);

Serial.print(poti);

Serial.print(254, BYTE); // 254 bzw. 0xFE Befehl für Extended LCD Command
Serial.print(192, BYTE);

Serial.print ("PWM - Wert");

delay(1);
analogWrite (ledPin, poti);

}

Hallo Hyrican99

Arduino arbeitet nicht paralell sondern eins nach dem anderen.

Du kannst Dein Problem lösen indem Du kein Delay verwendest sondern die verstrichene Zeit kontrollierst; siehe milli().

Schau Dir das Beispiel "blink without delay" an.

Grüße Uwe

Hallo Hyrican99 !

Der Arduino unterstützt auch Interrupts ( Unterbrechen das laufende Programm kurz, kontrollieren Sensoren, Tasten etc. ) und machen dann in der Schleife weiter.

Beispiele dazu sind leider dürftig. In irgendeinem Listing habe ich das letztens mit einer Tasten-Abfrage gesehen ( wenn ich nur wüste wo ).

MfG

Example
int pin = 13;
volatile int state = LOW;

void setup()
{
pinMode(pin, OUTPUT);
attachInterrupt(0, blink, CHANGE);
}

void loop()
{
digitalWrite(pin, state);
}

void blink()
{
state = !state;
}

@Gurkengraeber
Du machst komplizierte Ratschläge.

Hyrican99:
Parallel dazu schalte ich mit einem Sensortaster die LED am Ausgang 13. Durch die Loop wird jetzt erst der Potiwert gelesen dann berechnet und dann angezeigt. Danach kommt eben erst mit der Zeitverzögerung mein Schalter ins Spiel.

Mit einem analogen Wert kann man keinen Interrupt steuern.
Die Lösung ist, wie ich bereits geschrieben habe, im loop() zu kontrollieren, ob die Zeit schon abgelaufen ist und den Tastenwert zu lesen, auszuwerten und das Led zu setzen oder zu löschen. Beim nachsten Durchgang das selbe bis die Zeit abgelaufen ist.
Grüße Uwe

Hallo Uwe !

Analogwerte lassen sich bestimmt auch per Interrupt auslesen.

MfG

Das Auslesen ist nicht das Problem;
Du mußt den Interrupt per Analogwert triggern, das ist das Problem.
Grüße Uwe

Hallo Uwe !

Du musst doch nur wissen, ob sich der Status des Analog-Input-Pins geändert hat.

MfG

Und wenn das analoge Signal sich z.B. von 3,4V auf 4,3 V ändert, was dann?
Grüße Uwe

uwefed:
Und wenn das analoge Signal sich z.B. von 3,4V auf 4,3 V ändert, was dann?

Es geht um den Schalter der auch während des delay() funktionieren soll, nicht um die analoge Eingabe (oder?! bin auch gerade verunsichert)

sui:
Es geht um den Schalter der auch während des delay() funktionieren soll, nicht um die analoge Eingabe (oder?! bin auch gerade verunsichert)

Ja es geht um den Schalter.
Will aber Gurkengraeber verständlich machen, daß das mit dem Interrupt nicht so einfach ist und millis() die beste Lösung ist.
Grüße Uwe

Korregiert mich wenn ich falsch liege aber so währe es doch machbar:

...
Interval = 1000;
oldMillies = millies();

void loop(){
  taster abfragen
  Poti abfragen
  mach damit was
  if (millies() > oldMillies + Interval){
    Displayausgabe
    oldmillies = millies();
  }
}

So würden die Daten zwar durchgehend ausgelesen und verarbeitet aber das langsame Display wird nur jede Sekunde aktualisiert.
Wenn das so richtig ist ist das ja ziemlich simpel und kaum mehr code.

Gruß
Thorsten

MueThoS:
Korregiert mich wenn ich falsch liege aber so währe es doch machbar:

...

Interval = 1000;
oldMillies = millies();

void loop(){
  taster abfragen
  Poti abfragen
  mach damit was
  if (millies() > oldMillies + Interval){
    Displayausgabe
    oldmillies = millies();
  }
}



So würden die Daten zwar durchgehend ausgelesen und verarbeitet aber das langsame Display wird nur jede Sekunde aktualisiert.
Wenn das so richtig ist ist das ja ziemlich simpel und kaum mehr code.

Gruß
Thorsten

Sollte so einwandfrei funktionieren.
Nur die Abfrage würde ich eher so durchführen:

  if (millies() - oldMillies > Interval)

Das vermeidet Probleme beim Überlauf von millies(). Zudem wäre noch anzumerken, dass oldMillies unbedingt als unsigned long deklariert werden sollte.

MaFu:
Sollte so einwandfrei funktionieren.
Nur die Abfrage würde ich eher so durchführen:

  if (millies() - oldMillies > Interval)

Das vermeidet Probleme beim Überlauf von millies(). Zudem wäre noch anzumerken, dass oldMillies unbedingt als unsigned long deklariert werden sollte.

Das Problem "Überlauf" wollte ich eh nochmal erfragen:
Kommt es da nicht auch zu verschiebungen?

Angenommen:
millies geht bis 15
intervall ist 5
angenommen der letze intervall liegt genau bei 14 dann ist old millies bei 14
dann müßte doch millies bis 20 gehen können damit millies - oldmillies = 6 ist und dementsprechen > 5 interval
oder anders:
wenn oldmillies durch den überlauf erheblich größer ist wie millies kommen minus werte raus und demnach dauert es auf jeden fall länger da millies erstmal wieder oldmillies einholen muß.

Oder denke ich falsch.

MueThoS:

MaFu:
Sollte so einwandfrei funktionieren.
Nur die Abfrage würde ich eher so durchführen:

  if (millies() - oldMillies > Interval)

Das vermeidet Probleme beim Überlauf von millies(). Zudem wäre noch anzumerken, dass oldMillies unbedingt als unsigned long deklariert werden sollte.

Das Problem "Überlauf" wollte ich eh nochmal erfragen:
Kommt es da nicht auch zu verschiebungen?

Angenommen:
millies geht bis 15
intervall ist 5
angenommen der letze intervall liegt genau bei 14 dann ist old millies bei 14
dann müßte doch millies bis 20 gehen können damit millies - oldmillies = 6 ist und dementsprechen > 5 interval
oder anders:
wenn oldmillies durch den überlauf erheblich größer ist wie millies kommen minus werte raus und demnach dauert es auf jeden fall länger da millies erstmal wieder oldmillies einholen muß.

Oder denke ich falsch.

Darum sagte ich ja, dass oldMillis als unsigned long deklariert werden muss. Die Funktion millis() liefert auch unsigned long, somit gibt es keine negativen Werte.
Durch die Konstellation millis() - oldMillis kommt immer das richtige Ergebnis raus. Wenn millis() durch den Überlauf 0 liefert und oldMillis noch auf 4294967295 steht verursacht 0 - 4294967295 ja auch einen Überlauf und liefert 1.

Ja, OK.
Das wußte ich nicht aber trotzdem meine Frage:
0 - 4294967295 ergibt dann so lange 1 bis millies() > 4294967295 ist oder nicht?
Weil so lange würde es negativ sein.
Und demnach würden wir nie wieder auf interval kommen da dann ja schon wieder ein überlauf kommt.

Millis() gibt einen Wert vom Typ unsigned long; also ohne Vorzeichen, nur positive Werte. Beim Überlauf fängt es wieder bei 0 an. Das passiert ca alle 49 Tage. Wenn die if-Bedingung richtig geschrieben ist, ist der Zeitintervall auch während eines Überlaufs richtig.
Grüße Uwe

MueThoS:
Ja, OK.
Das wußte ich nicht aber trotzdem meine Frage:
0 - 4294967295 ergibt dann so lange 1 bis millies() > 4294967295 ist oder nicht?
Weil so lange würde es negativ sein.
Und demnach würden wir nie wieder auf interval kommen da dann ja schon wieder ein überlauf kommt.

Gehen wir mal von folgendem aus:
Das Ergebiss war wahr, millis() liefert 4294967293 und oldMillis übernimmt den Wert.

oldMillis steht somit auch auf 4294967293.
Eine Millisekunde später liefert millis() den nächsthöheren Wert, also 4294967294.
Der Vergleich liefert also millis() - oldMillis = 4294967294 - 4294967293 = 1.
Noch eine Millisekunde später liefert millis() also 4294967295, millis() - oldMillis = 4294967295 - 4294967293 = 2.
Wieder eine Millisekunde später müsste millis() 4294967296 liefern. Dieser Wert passt nicht mehr in ein unsigned long, es entsteht also ein Überlauf. Da wegen dem unsigned kein negativer Wert entstehen kann, liefert millis() somit 0.
Die Vergleichsrechnung wäre demzufolge: millis() - oldMillis = 0 - 4294967293
Da wegen unsigned long keine negative Zahl entstehen kann ist das Ergebnis 3.
Beim nächsten mal wäre millis() - oldMillis = 1 - 4294967293 = 4.

Die Vergleichsergebnisse sind also fortlaufend 1, 2, 3, 4, ... obwohl dazwischen ein Überlauf stattgefunden hat.
Jetzt alles klar?

Sag doch einfach das er ganz normal rechnet und aber das - weg läßt.
Ich hatte das so verstanden das immer 1 raus kommt weil wegen fehler.
Aber wenn er natürlich ins - rechnet aber das - dann weg läßt dann hab ich das verstanden.

So,
das bedeutet:
3 Packen - 4 Packen = -1Packen = 1Packen = Feierabend....

Für die Verständlichkeit ist es sehr hilfreich, sich solche Berechnungen in binärer Schreibweise anzusehen XD