If Abfrage Problem

Guten Abend liebe Community,

anbei habe ich einen Code, welcher 4 Lux Sensoren über einen TCA9548A I2C Mulitplexer am Arduino Mega ausliest. Dies funktioniert, ich möchte aber jetzt erstmal mich um die Y Achse kümmern also bitte nicht wundern warum es im code erstmal nur um zwei sensoren geht.

Jetzt zum Problem:
Ich habe ein Sonenpanel auf eine Achse gebaut, welches sich durch die Lux Sensoren zur Sonne ausrichten. Es funktioniert alles nur bleibt mein Motor nicht stehen. Er dreht von rechts nach links, und sobald das licht an einem Sensor weg geht, dreht er sich wieder in die andere Richtung. Es geht mir also nur um die If abfragen im Code. Mir ist bewusst dass das Programm nicht bei Motor stopp stehen bleibt. Ich habe versucht eine Bool Variabel einzubauen welche aktiv bleibt solang die Lux Werte sich nähern, habs nicht hinbekommen. Dann mit einer While Schleife... hab ich auch nicht hinbekommen (wobei das schon besser funktioniert hat, aber meine Lux Werte wurden nicht mit in die Schleife übernommen.

Vielen dank im Vorraus

Grüße
Stefan

Hier mein erster Code

#include <Wire.h>

#define TCA9548A_ADDRESS 0x70
#define BH1750_ADDRESS 0x23

// Pin-Definitionen für den Motor
const int ENA = 7;
const int IN1 = 5;
const int IN2 = 6;
const int IN3 = 8;
const int IN4 = 9;
const int ENB = 10;



void setup() {
  Serial.begin(9600);
  Wire.begin();
  
  // Initialisierung des Motors
  pinMode(ENA, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  pinMode(ENB, OUTPUT);
}

void loop() {
  // Kanal 0
  Wire.beginTransmission(TCA9548A_ADDRESS);
  Wire.write(1 << 0);  // Kanal 0 aktivieren
  Wire.endTransmission();
  delay(100);

  Wire.beginTransmission(BH1750_ADDRESS);
  Wire.write(0x10);  // Kontinuierliche Hochauflösungsmessung einschalten
  Wire.endTransmission();
  delay(200);

  Wire.beginTransmission(BH1750_ADDRESS);
  Wire.requestFrom(BH1750_ADDRESS, 2);
  int luxValue1 = 0;
  if (Wire.available() == 2) {
    uint16_t luxValue = Wire.read() << 8;
    luxValue |= Wire.read();
    luxValue1 = luxValue;
  }
  Wire.endTransmission();
  
  // Kanal 1
  Wire.beginTransmission(TCA9548A_ADDRESS);
  Wire.write(1 << 1);  // Kanal 1 aktivieren
  Wire.endTransmission();
  delay(100);

  Wire.beginTransmission(BH1750_ADDRESS);
  Wire.write(0x10);  // Kontinuierliche Hochauflösungsmessung einschalten
  Wire.endTransmission();
  delay(200);

  Wire.beginTransmission(BH1750_ADDRESS);
  Wire.requestFrom(BH1750_ADDRESS, 2);
  int luxValue2 = 0;
  if (Wire.available() == 2) {
    uint16_t luxValue = Wire.read() << 8;
    luxValue |= Wire.read();
    luxValue2 = luxValue;
  }
  Wire.endTransmission();

  // Entscheidung über die Motorrichtung
  if (luxValue1 > luxValue2) {
    Serial.println("Sensor 1 hat mehr Licht, der Motor dreht sich nach rechts,Panel links");
    Serial.print("Lux-Wert Sensor 1: ");
    Serial.println(luxValue1);
    Serial.print("Lux-Wert Sensor 2: ");
    Serial.println(luxValue2);
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, HIGH);
    digitalWrite(IN3, HIGH);
    digitalWrite(IN4, LOW);
    analogWrite(ENA, 150);
    analogWrite(ENB, 150);
  } else if (luxValue2 > luxValue1) {
    Serial.println("Sensor 2 hat mehr Licht, der Motor dreht sich nach links,Panel rechts");
    Serial.print("Lux-Wert Sensor 1: ");
    Serial.println(luxValue1);
    Serial.print("Lux-Wert Sensor 2");
    Serial.println(luxValue2);
    digitalWrite(IN1, HIGH);
    digitalWrite(IN2, LOW);
    digitalWrite(IN3, LOW);
    digitalWrite(IN4, HIGH);
    analogWrite(ENA, 150);
    analogWrite(ENB, 150);
}  else if (luxValue1 - luxValue2 < 200) {
    Serial.println("Beide Sensoren haben den gleichen Lichtwert, der Motor stoppt");
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, LOW);
    digitalWrite(IN3, LOW);
    digitalWrite(IN4, LOW);
}   
  
}

Hier der Code mit Schleife: Wie gesagt es geht mir um den Motorstopp wenn die Lux werte differenz kleiner gleich 200

#include <Wire.h>

#define TCA9548A_ADDRESS 0x70
#define BH1750_ADDRESS 0x23

// Pin-Definitionen für den Motor
const int ENA = 7;
const int IN1 = 5;
const int IN2 = 6;
const int IN3 = 8;
const int IN4 = 9;
const int ENB = 10;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  
  // Initialisierung des Motors
  pinMode(ENA, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  pinMode(ENB, OUTPUT);
}

void loop() {
  // Kanal 0
  Wire.beginTransmission(TCA9548A_ADDRESS);
  Wire.write(1 << 0);  // Kanal 0 aktivieren
  Wire.endTransmission();
  delay(100);

  Wire.beginTransmission(BH1750_ADDRESS);
  Wire.write(0x10);  // Kontinuierliche Hochauflösungsmessung einschalten
  Wire.endTransmission();
  delay(200);

  Wire.beginTransmission(BH1750_ADDRESS);
  Wire.requestFrom(BH1750_ADDRESS, 2);
  int luxValue1 = 0;
  if (Wire.available() == 2) {
    uint16_t luxValue = Wire.read() << 8;
    luxValue |= Wire.read();
    luxValue1 = luxValue;
  }
  Wire.endTransmission();
  
  // Kanal 1
  Wire.beginTransmission(TCA9548A_ADDRESS);
  Wire.write(1 << 1);  // Kanal 1 aktivieren
  Wire.endTransmission();
  delay(100);

  Wire.beginTransmission(BH1750_ADDRESS);
  Wire.write(0x10);  // Kontinuierliche Hochauflösungsmessung einschalten
  Wire.endTransmission();
  delay(200);

  Wire.beginTransmission(BH1750_ADDRESS);
  Wire.requestFrom(BH1750_ADDRESS, 2);
  int luxValue2 = 0;
  if (Wire.available() == 2) {
    uint16_t luxValue = Wire.read() << 8;
    luxValue |= Wire.read();
    luxValue2 = luxValue;
  }
  Wire.endTransmission();

while (abs(luxValue1 - luxValue2) > 200) {
  
  // Entscheidung über die Motorrichtung
  if (luxValue1 > luxValue2) {
    Serial.println("Sensor 1 hat mehr Licht, der Motor dreht sich nach rechts,Panel links");
    Serial.print("Lux-Wert Sensor 1: ");
    Serial.println(luxValue1);
    Serial.print("Lux-Wert Sensor 2: ");
    Serial.println(luxValue2);
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, HIGH);
    digitalWrite(IN3, HIGH);
    digitalWrite(IN4, LOW);
    analogWrite(ENA, 150);
    analogWrite(ENB, 150);
  } else if (luxValue2 > luxValue1) {
    Serial.println("Sensor 2 hat mehr Licht, der Motor dreht sich nach links,Panel rechts");
    Serial.print("Lux-Wert Sensor 1: ");
    Serial.println(luxValue1);
    Serial.print("Lux-Wert Sensor 2");
    Serial.println(luxValue2);
    digitalWrite(IN1, HIGH);
    digitalWrite(IN2, LOW);
    digitalWrite(IN3, LOW);
    digitalWrite(IN4, HIGH);
    analogWrite(ENA, 150);
    analogWrite(ENB, 150);
  }
}

// Der Motor stoppt
Serial.println("Beide Sensoren haben den gleichen Lichtwert, der Motor stoppt");
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
  
}

Warum macht ihr so komplizierte Beispiele, an denen man Euch was zeigen soll?

Auf alle Fälle ist Deine IF-Konstruktion in der falschen Reihenfolge.
Reine Logik:
Wenn

if (luxValue1 > luxValue2)

erfüllt ist, wird der rest nicht mehr angelaufen.
Wenn das nicht erfüllt ist, aber

else if (luxValue2 > luxValue1)

geht das noch.
Aber wenn der auch erfüllt ist, kommst Du da

  else if (luxValue1 - luxValue2 < 200)

nie hin.
Nie!

Daher erst auf den kleinsten Unterschied prüfen - in Deinem Fall die 200 - und dann erst auf die anderen; Die sind ja dann größer.

Im Übrigen: Was passiert, wenn luxValue1 4 ist und luxValue2 500?
:slight_smile:

Vielen Dank für deine schnelle Nachricht,

ich habe dies versucht aber nun bleibe ich in der ersten If abfrage (Motor Stop) oder zweiten (Panel nach rechts drehen) hängen. Die dritte abfrage zum links fahren geht nicht....

Ich geh mal davon aus, das Du das simulierst - und eigentlich egal ist, ob das Panel sich bewegt oder nicht.

Dann reicht Dir auch folgender Code zum probieren:
ungetestet! Kompiliert aber.

#include <Wire.h>

#define TCA9548A_ADDRESS 0x70
#define BH1750_ADDRESS 0x23

unsigned int luxValue1 = 0;
unsigned int luxValue2 = 0;

void setup()
{
  Serial.begin(9600);
  Serial.println(F("Start..."));
}

void loop()
{
  getLichtsensorik();
  setActor();
  delay(100);
}

void setActor()
{
  if ((max(luxValue1, luxValue2)) - (min(luxValue1, luxValue2) ) < 200)
  {
    Serial.println(F("Antrieb Stopp"));
  }
  else if (luxValue1 > luxValue2)
  {
    Serial.println(F("Value1 > Value2"));
  }
  else
  {
    Serial.println(F("Value2 < Value1"));
  }
}

void getLichtsensorik()
{
  // Kanal 0
  Wire.beginTransmission(TCA9548A_ADDRESS);
  Wire.write(1 << 0);  // Kanal 0 aktivieren
  Wire.endTransmission();
  delay(100);
  Wire.beginTransmission(BH1750_ADDRESS);
  Wire.write(0x10);  // Kontinuierliche Hochauflösungsmessung einschalten
  Wire.endTransmission();
  delay(200);
  Wire.beginTransmission(BH1750_ADDRESS);
  Wire.requestFrom(BH1750_ADDRESS, 2);
  if (Wire.available() == 2)
  {
    uint16_t luxValue = Wire.read() << 8;
    luxValue |= Wire.read();
    luxValue1 = luxValue;
  }
  Wire.endTransmission();
  // Kanal 1
  Wire.beginTransmission(TCA9548A_ADDRESS);
  Wire.write(1 << 1);  // Kanal 1 aktivieren
  Wire.endTransmission();
  delay(100);
  Wire.beginTransmission(BH1750_ADDRESS);
  Wire.write(0x10);  // Kontinuierliche Hochauflösungsmessung einschalten
  Wire.endTransmission();
  delay(200);
  Wire.beginTransmission(BH1750_ADDRESS);
  Wire.requestFrom(BH1750_ADDRESS, 2);
  if (Wire.available() == 2)
  {
    uint16_t luxValue = Wire.read() << 8;
    luxValue |= Wire.read();
    luxValue2 = luxValue;
  }
  Wire.endTransmission();
}

Schaffen deine "Lux Sensoren" das ganze Licht von Sonne untergegangen, bis volle Sonne zu unterscheiden? Mein Problem war, dass ich entweder nur von Dunkel, bis Sonne hinter leichten Schleierwolken unterscheiden konnte, oder von Sonne hinter leichten Schleierwolcken, bis absolut volle Sonne. Ich habe es inzwischen hinbekommen, das Tageslicht in einem Wert von 0 - 8190 darzustellen in allen 4 Richtungen zu messen. Also echt die ganze Spanne, die das Tageslicht zu bieten hat, von dunkel bis volle Sonne auf dem Sensor.

Franz

#include <Wire.h>

#define TCA9548A_ADDRESS 0x70
#define BH1750_ADDRESS 0x23

// Pin-Definitionen für den Motor
const int ENA = 7;
const int IN1 = 5;
const int IN2 = 6;
const int IN3 = 8;
const int IN4 = 9;
const int ENB = 10;



void setup() {
  Serial.begin(9600);
  Wire.begin();

  // Initialisierung des Motors
  pinMode(ENA, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  pinMode(ENB, OUTPUT);
  analogWrite(ENA, 150);
  analogWrite(ENB, 150);
}

void loop() {
  // Kanal 0
  Wire.beginTransmission(TCA9548A_ADDRESS);
  Wire.write(1 << 0);  // Kanal 0 aktivieren
  Wire.endTransmission();
  delay(100);

  Wire.beginTransmission(BH1750_ADDRESS);
  Wire.write(0x10);  // Kontinuierliche Hochauflösungsmessung einschalten
  Wire.endTransmission();
  delay(200);

  Wire.beginTransmission(BH1750_ADDRESS);
  Wire.requestFrom(BH1750_ADDRESS, 2);
  int luxValue1 = 0;
  if (Wire.available() == 2) {
    uint16_t luxValue = Wire.read() << 8;
    luxValue |= Wire.read();
    luxValue1 = luxValue;
  }
  Wire.endTransmission();

  // Kanal 1
  Wire.beginTransmission(TCA9548A_ADDRESS);
  Wire.write(1 << 1);  // Kanal 1 aktivieren
  Wire.endTransmission();
  delay(100);

  Wire.beginTransmission(BH1750_ADDRESS);
  Wire.write(0x10);  // Kontinuierliche Hochauflösungsmessung einschalten
  Wire.endTransmission();
  delay(200);

  Wire.beginTransmission(BH1750_ADDRESS);
  Wire.requestFrom(BH1750_ADDRESS, 2);
  int luxValue2 = 0;
  if (Wire.available() == 2) {
    uint16_t luxValue = Wire.read() << 8;
    luxValue |= Wire.read();
    luxValue2 = luxValue;
  }
  Wire.endTransmission();

  // Entscheidung über die Motorrichtung
  if (abs(luxValue1 - luxValue2) < 200) {
    Serial.println("Beide Sensoren haben den gleichen Lichtwert, der Motor stoppt");
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, LOW);
    digitalWrite(IN3, LOW);
    digitalWrite(IN4, LOW);
  }
  else {
    if (luxValue1 > luxValue2) {
      Serial.println("Sensor 1 hat mehr Licht, der Motor dreht sich nach rechts,Panel links");
      Serial.print("Lux-Wert Sensor 1: ");
      Serial.println(luxValue1);
      Serial.print("Lux-Wert Sensor 2: ");
      Serial.println(luxValue2);
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, HIGH);
      digitalWrite(IN3, HIGH);
      digitalWrite(IN4, LOW);
    } else if (luxValue2 > luxValue1) {
      Serial.println("Sensor 2 hat mehr Licht, der Motor dreht sich nach links,Panel rechts");
      Serial.print("Lux-Wert Sensor 1: ");
      Serial.println(luxValue1);
      Serial.print("Lux-Wert Sensor 2");
      Serial.println(luxValue2);
      digitalWrite(IN1, HIGH);
      digitalWrite(IN2, LOW);
      digitalWrite(IN3, LOW);
      digitalWrite(IN4, HIGH);
    }
  }
}

Hallo stefanthebest

Nimm eine Uhr zum Ausrichten des Sonnenpanels.

Guten Tag, meine lieben Damen, Herren und Diverse.....

Lange musste ich überlegen, ob ich zu dem Thread überhaupt was sage...
:japanese_ogre: :japanese_ogre:

Ich finde den Hang zu ausufernden if Konstruktionen immer wieder faszinierend.
Selber bevorzuge ich eher Modularisierung, Kapselung usw.

Für dieses Problem habe ich mir den C++20 <=> Operator und einen Fenster Komparator zum Vorbild genommen.

Naja...
Vielleicht kann ja eine(r) was damit anfangen

#include <Streaming.h> // die Lib findest du selber ;-)
Print &cout = Serial; // cout Emulation für "Arme"


void rechtslauf()
{
   // Hier motor rechts
   cout << F("Motor rechts ") << endl;
}

void linksslauf()
{
   // Hier motor links
   cout << F("Motor links ") << endl;
}

void motorhalt()
{
   // Hier motor halt
   cout << F("Motor halt ") << endl;
   delay(2000); 

}


int starShipOperator(int lvalue, int rvalue, int fenster) // ersatzstoff
{
  return abs(lvalue-rvalue)<fenster?0:lvalue<rvalue?-1:1;
}



using FPtr = void(*)();

const int hysterese = 200;
FPtr action[] {rechtslauf,motorhalt,linksslauf};

void setup() 
{
  Serial.begin(9600);
  cout << F("Start: ") << F(__FILE__) << endl;
}

void loop() 
{
  
  // hier sensoren einlesen
  int rechterSensor = random(0,4097);
  int linkerSensor  = random(0,4097);
  
  cout << linkerSensor << ',' << rechterSensor << endl;
  action[starShipOperator(linkerSensor,rechterSensor,hysterese)+1]();

}

Es gibt 2 Lösungswege:

  • Sonnenstand anhand Uhrzeit, Datum und GPS Position errechnen. Feedback Motorposition um die errechente Position anzufahren zu können.
  • Nachführung durch Sensoren die so angeordnet sind daß eine inkorrekte Ausrichtung einen oder mehrere abschattet. Keine Motorpositionsmessung notwendig.

Die Ausrichtung ist wichtig wenn die Sonne scheint , da in dieser Situation die meiste Solarstromproduktion stattfindet. Bei Schatten oder schlechten Lichtverhältnissen durch Bewölkung, oder Tiefstand der Sonne ist die Ausrichtug unwichtiger da die Stromproduktion gering ist.

Ich sehe keinen der Lösungswege perfekt bzw fehlerfrei und wüßte nich zu welchem ich raten sollte.

Grüße Uwe

Hmm...
Wenn Sensoren, dann würde ich eher zu grünen LED tendieren.
Deren Sperrschichtkapazität ist stark Licht abhängig.
Und die kosten quasi nix.

Für die Ansteuerung des Seitenwinkels für das Solarpanels wird nur die Uhrzeit benötigt.

Welche Sensoren für die Lichtmessung zu nutzen habe ich nicht überlegt.
Ein Fotowiderstand ist sicher am einfachsten zu messen einfach Spannungsteiler mit einem Festwiderstand. Auch ein Spannungsteiler mit 2 Gegenüberliegende Fotowiderstände wäre denkbar, man kann aber so nicht die absolute Helligkeit (Schatten durch zB Wolken) bestimmen .
Die Sperrschichtkapazität wüßte ich auf die schnelle nicht wie messen.
Grüße Uwe

Schwingkreis und Frequenzmessung.
Recht aufwendig.

Ladezeit messen
Aufladen entladen.
Mit Timer und dem eingebauten Komparator brauchts nur die LED und einen ca 1MOhm Widerstand

Daraus muß aber die örtliche Sonnenzeit errechnet werden da bis zu ca 22° Fehler zwischen Standartzeit und Ortszeit in Europa möglich sind (In Deutschland bedeutend weniger als die Hälfte)

Grüße Uwe

Vielen dank my_xy_projekt :raised_hands:
nun richtet sich mein Panel perfekt auf der X und Y Achse aus. nicht auf diese lösung gekommen. aber logisch das ja bei meiner version immer ein negativer Wert ausgerechnet wurde.

Jetzt noch Batterie und PWM anklemmen und appsteuerung einbinden dann ist das Projekt fertig.

1 Like

Schick! Mal wieder etwas mit Foto, damit man auch mal sieht, was so gebaut wird :smile:
Das Ding ist doch etwas größer, als ich so an Vorstellung hatte. :+1:

Na dann - wenn Dir mein Lösungsvorschlag geholfen hat: weitermachen! :wink:

1 Like

Was ja kein Problem sein sollte, schon lange nicht mehr im Forum gesehene @jurs hat mal die Berechnung (2012) hier gezeigt, in nutze die :wink: ist genau bis auf 1 Min.

Aus der Diskussion hab ich nicht gedacht das es ein so großes Pannel ist.
Scheint ziemlich stabil und ordentlich gebaut zu sein. Bravo.
Grüße Uwe

Ja, da schließe ich mich an : sieht ordentlich gebaut aus.

War das ein vorgegebenes Projekt ?
Was mich dazu auch interessieren würde: Wie ist der Netto Stromertrag im Vergleich zu einem fest stehenden Modul ? Gemessene Werte, - allerdings bräuchtest Du zum Vergleichen ein zweites Modul...

Wieso nicht selber messen?
Das kannst Du mit 2 kleinen Solarmodulen auch herausfinden und so ein Meßprojekt bauen.
Grüße Uwe