Wenn diese Bedingung vorliegt, dann mach nur 1x diese Funktion, bis sich Bedingung wieder ändern

Hallo, ich bin neu hier im Forum, habe aber schon einige Erfahrungen mit kleineren Projekten. Nun taste mich Stück für Stück in einen etwas größeren Arduinoprojekt vorran und stecke nun fest.

Grundaufgabe: Ich möchte gerne ein Blakonkraftwerk (2 Solarzellen) mit einer Sonnennachführung über entsprechenden Gestell und Linearmotoren über Arduino Uno steuern. Ich habe ein Kreuz mit 4 Fotowiderständen gebaut. Die Werte werden ausgelesen und Differenzen der Werte für Tagesverlauf und Jahresverlauf führen dazu, dass verschiedene Relais angesteuert werden, die dann 2 Linearmotoren ansteuern. Das funktioniert soweit im Versuchsaufbau gut.

Nun möchte ich gerne ein paar "Extras " einbauen. Als erstes möchte ich, wenn die Widerstandwerte von 2 Widerständen unter den Wert 80 fallen, dass ein bestimmter Ausgang low geht und ein anderer high. Diese Funktion soll den Abend entsprechend die Module von Ostausrichtung wieder auf West fahren.
Grundsätzlich haben die Linearmotoren Endschalter, es wäre praktisch egal wenn der Befehl (wenn Wert unter 80 dann) über Nacht ansteht. Aber ich glaube die Relais finden das auf Dauer nicht so schön.
Am Ende des Sktechs habe ich diese Funktion eingebaut. Dilay wird dann an die max. Fahrdauer des Linearmotors noch angepasst. Jetzt ersteinmal 4000.
Frage:
Wie bekomme ich es hin, dass wenn der Wert unter 80 fällt (auch das muss in der Praxis natürlich noch an die Vorortverhältnisse angepasst werden) die Ausgänge 12 und 13 entsprechend angestert werden? Im Moment passiert das schon, aber nach der delay(4000) Zeit wird 12 auf high und dann gleich wieder auf low gesetzt. Das ist also nicht der richtige Weg.

Info zur Relaiskarte: Damit das Relais abfällt, muss ich den Arduinoausgang auf high setzen.

Ich hoffe mein Problem konnte ich für die Profis hier vernüftig beschreiben und habe alle nötigen Detail erwähnt.

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(10, OUTPUT);
}

void loop() {

  
  // Helligkeit der beiden lichtempfindlichen Widerstände 11 und 12 für Tagesneigung

  int gelb12 = analogRead(0);
  int braun11 = analogRead(1);


  // Helligkeit der beiden lichtempfindlichebn Widerstände 21 und 22 für Jahresneigung

  int grau22 = analogRead(2);
  int blau21 = analogRead(3);
 

  // Differenz ausrechnen Widerstandswert Tagesneigung
  
  int diff1 = (gelb12 - braun11);

  // Differenz ausrechnen Widerstandswerte Jahresneigung
  
  int diff2 = (grau22 - blau21);


// Wenn braun11 und gelb12 Werte über 80 haben und
// Wenn gelb12 deutlich heller als braun11, dann Realis 1.1 anziehen und Realis 2.1 abfallen

if ((braun11 and gelb12 > 80) and diff1 > 80) {
  digitalWrite(12, HIGH);
  digitalWrite(13, LOW);
  delay(500);
}

//Wenn braun11 und gelb12 Werte über 80 haben und
// Wenn braun11 deutlich heller als gelb12, dann Realis 1.1 abfallen und Relais 2.1 anziehen


  if ((braun11 and gelb12 > 80) and diff1 < -80) {
  digitalWrite(12, LOW);
  digitalWrite(13, HIGH);
  delay(500);
}

//Wenn braun11 und gelb12 Werte über 80 haben und
// Wenn grau22 deutlich heller als blau21, dann Realis 3.1 anziehen und Realis 4.2 abfallen

  if ((braun11 and gelb12 > 80) and diff2 > 80) {
  digitalWrite(11, HIGH);
  digitalWrite(10, LOW);
  delay(500);
}

//Wenn braun11 und gelb12 Werte über 80 haben und
// Wenn blau21 deutlich heller als grau22, dann Realis 3.1 abfallen und Relais 4.2 anziehen

  if ((braun11 and gelb12 > 80) and diff2 < -80) {
  digitalWrite(11, LOW);
  digitalWrite(10, HIGH);
  delay(500);
}


// Wenn die Differenz 1 kleiner +/- 79 ist und der Wert gelb12 über 80 ist, dann beide Relais abfallen lassen

  if (diff1 <= 79 and diff1 >= -79 and gelb12 >80) {

    digitalWrite(13, HIGH);
    digitalWrite(12, HIGH);
    delay(1000);

  }

  // Wenn die Differenz 2 kleiner +/- 79 ist und der Wert blau21 über 80 ist, dann beide Relais abfallen lassen

    if (diff2 <= 79 and diff2 >= -79 and blau21 > 80) {

      digitalWrite(11, HIGH);
      digitalWrite(10, HIGH);
      delay(1000);

    }

// Wenn Wert von braun11 und gelb12 unter 80 Fällt (am Abend bei Dunkelheit), dann Relais anziehen und nach delay abfallen lassen

  if (braun11 and gelb12 < 80) {
    
    digitalWrite(12, LOW);
    digitalWrite(13, HIGH);
    delay(4000);
    digitalWrite(12, HIGH);

}


  // Die beiden Helligkeitswerte und Dufferenzen zu Testzwecken an den PC übertragen
  Serial.println(String(gelb12) + " " + String(braun11) + " " + String(diff1) + "   " + String(grau22) + " " + String(blau21) + " " + String(diff2));
  delay(200);

}

Dieser Text wird ausgeblendet

Meinten Sie ➜

if ((braun11  > 80) and (gelb12 > 80) and (diff1 > 80) ){

??

Benutze die such Option im Forum das Thema werde öfters beschrieben, und bei manchen funktioniert sogar :wink:

Hallo, nein ich meinte die ehr den Teil am ende vor der Seriellen Abfrage

 if (braun11 and gelb12 < 80) {
    
    digitalWrite(12, LOW);
    digitalWrite(13, HIGH);
    delay(4000);
    digitalWrite(12, HIGH);

Mir ist klar, dass nach 12 LOW und 13 HIGH und delay 4000 der Ausgang12 auf high geht und dann eben sofort wieder auf low. Dann wieder delay 4000, 12 auf HIGH usw. Und genau das würde ich gerne so ändern, dass wenn braun11 und gelb12 <80 sind, 12 auf LOW, 13 auf HIGH und nach einer bestimmten Zeit, 12 wieder auf HIGH geht und dann solange HIGH bleibt, bis sich der Wert von braun11 und gelb12 >80 ändert.

lass mich umformulieren

wenn Sie schreiben:

if (braun11 and gelb12 < 80) { ...

Sie sagen, "wenn braun11 nicht null ist UND gelb12 kleiner als 80 ist, dann ..."

ist das was Sie wollen?

Hast Du Deine Schaltung so gebaut?

+ --+
     \ Relais 1
    +
    |
    +
     \ Relais 2
    + +
    | |
links rechts
  Antrieb
     |
- ---+

Ansonsten: Dein Code macht nicht, was Du willst, wenn Du

das nicht berichtigst.

Vielleicht hilft ja auch lesen, wie andere das gelöst haben. Sonnen Tracker Arduino

Bitte gewöhne Dir an, Deinen Pins beschreibende Namen zu geben und schreib nicht die Pinnummern in die Funktionen. Wenn Du einmal den Pin änderst, suchst Du Dich im Code tot.

Alte Programmiererweisheit: Der Fehler steckt nicht immer da, wo Du ihn vermutest.

Zu dieser Zeile hilft es vielleicht, mal über die Vorrangregeln für Operatoren nachzulesen.
Und natürlich - wie von Jackson schon angemerkt - ein

if ( numerischeVariable)

ist genau dann erfüllt, wenn der Wert der Variablen nicht 0 ist.

Zu dem anderen Problem:
Wenn die Bedingung erfüllt ist und erst wieder "scharf geschaltet" werden soll, wenn sie einmal nicht mehr erfüllt war, hilft ein Merker:

bool merker = false;
...
void loop() 
{
  ...
  if (bedingung)
  {
    if (!merker) 
    {
      // tu was zu tun ist
      merker = true;
    }
    // was hier nicht steht, aber die Idee dahinter ist:
    // else
    // {
    //   tu nix wenn es schon einmal getan wurde und die Bedingung seitdem immer 
    //   noch erfüllt ist (was durch den gesetzten Merker angezeigt wird)
    // }

  }
  else
  {
    // bedingung nicht (mehr) erfüllt
    merker = false;
  }
}

Hallo, das mag ja sein, aber genau deswegen bin ich genau hier um die Stelle zu finden mit Eurer Hilfe.

Vielleicht habe ich es falsch geschrieben in den Sketch. Wenn braun11 und gelb12 beide kleiner 80 sind, dann mache 1x dieses......
Ich hoffe es ist so verständlicher geschrieben?

Die Hilfe wird Dir angeboten, Du nimmst sie aber leider nicht an. Darauf wollte ich Dich hinweisen.

In #2 wurde Dir ein offensichtlicher Fehler gezeigt. Wie verhält sich Dein Programm, wenn Du diesen Fehler korrigierst?

Meinst du damit z.B. gelb12? Wenn ja, dann wollte ich das damit nicht zum Ausdruck bringen. Da ich bei meinen ersten Beitrag noch kein Bild hochladen konnte, konnte ich Euch auch nicht zeigne, dass ich die Fotowiderstände 1.1 und 1.2 für die eine Ausrichtung und 2.1 und 2.2 für die andere Ausrichtung genannt habe. Ich habe gemerkt, dass der Punkt zwischen den Zahlen nicht zur Verbesserung beigetragen hat :wink: Daher habe ich den Punkt einfach weggelassen. Also gelb12 ist nicht Pin 12.

Es ist etwas viel für Jemand Neues hier. Ich hab mir schon die Grundregeln durchgelesen, aber welche Taste hier beim schreiben was macht hab ich noch nicht verinnerlichst. Sorry dafür. Ich hab mal ziwschen den Zeilen geschrieben.

@andreasneu Hier versuchen ein paar Leute Dir klar zu machen, dass Deine IF Bedingungen sehr wahrscheinlich falsch formuliert sind. Irgendwie scheinst Du das aber nicht zu merken.

Jedenfalls gehst Du da nicht drauf ein.

Wenn du schreibst if ((braun11 and gelb12 > 80) and diff1 > 80) bedeutet das NICHT, dass die Bedingung wahr ist, wenn braun11 und gelb12 > 80 ist!

Es bedeutet, dass die Bedingung immer dann wahr ist, wenn braun11 != 0 und gelb12 > 80 ist. Das ist aber etwas anderes als Du beschreibst.

Ja.. Ja, das ist nicht das, was Sie geschrieben haben :slight_smile:

Umgangssprachlich sagt man: "Wenn x und y kleiner als 80 sind, dann ...", aber in C++ geht das so nicht, da muß man formulieren: "Wenn x kleiner 80 ist und y kleiner 80 ist, dann ..".

Die richtige Schreibweise steht in #2.

In der Frage aus #6 geht es um die Verkabelung der Motoren, die in #12 leider gänzlich fehlt. In #6 schaltet Relais 1 ein/aus und Relais 2 die Richtung. Dies ist die sicherere Variante, die Du auch verwenden solltest.

Das mit dem if haben die Kollegen wohl hinreichend erläutert

Hmmm. Da müsstest Du etwas konkreter werden wo genau es hakt.
Ich habe versucht, in allgemeiner Form aufzuschreiben, wie das aussehen kann, wenn ein Programmteil nur einmal nach Eintreten einer Bedingung ausgeführt werden soll und dann erst wieder nachdem die Bedingung nicht mehr erfüllt war.

Du müsstest jetzt nur deine Bedingung einsetzen und an die Stelle // tu was zu tun ist den Code plazieren der dann ausgeführt werden soll.
Der auskommentierte else-Zweig dient nur der Erläuterung - kannst du ignorieren.

Vielen lieben Dank, ok ich brauchte genau diese Worte/Antwort. Ich hab es in der Tat nicht verstanden, was ich wo ändern sollte oder was es sinngemäß für Folgen hat (Sonst hätte ich es ja auch nicht so in den Sketch geschrieben). Genau da steckt wohl ein Fehler. Dennoch habe ich den Teil:

 ((braun11 and gelb12 > 80) and diff1 > 80)

in

if ((braun11 > 80) and (gelb12 > 80) and (diff1 > 80) {

und bekomme an anderen Stellen Fehlermeldungen. Die habe ich zum Teil auch schon behoben. Aber mein Kopf ist für heute am Ende. Und vermutlich wird es Sinngemäß auch nicht das wiederspiegel, was ich haben möchte, aber ich habe es dennoch ausprobiert.

Ich bedanke mich das ihr den anscheinend schwierigsten Teil (der Typ vor den Monitor an der Tastatur :see_no_evil:) langsam in den Griff bekommt.

Ich melde mich wieder, wenn ich für mich, Eure Informationen verarbeitet habe und dann hoffentlich weiter gekommen bin. Nocheinmal vielen Dank an dieser Stelle an Alle die an diesen Projekt mitarbeiten und mir helfen wollen :+1:t3:

Bestimmt werde ich irgendwann den Fehler finden und beseitigen so hoffe ich :grimacing:

Freut mich, dass ich die richtigen Worte gefunden habe. In deiner geänderten IF Bedingung fehlt die schließende Klammer für das Statement:

if ((braun11 > 80) and (gelb12 > 80) and (diff1 > 80)) {

Viel Erfolg wünsche ich noch….