Solartracker zwei Achsen, mit Lichtsensoren

Benutzeravatar
Admin
Administrator
Beiträge: 1196
Registriert: Mo 20. Apr 2020, 09:47
Wohnort: 82441 Ohlstadt
Kontaktdaten:

Re: Die Position der Sonne mit Sensoren bestimmen

Beitrag von Admin »

Ich mache mir demnächst mal ein kleines Messgerät, mit dem ich die Lichtstärke indentisch zu meinem "Sonnen-Verfolger" messen kann. Also auch mit den beiden Sensoren, einer hell, einer Abgedunkelt mit drei Lagen 100gr. Papier. Da möchte ich dann aber zweierlei Messergebnisse benutzen. Meinen Messwert hier für das SonnenVerfolger-Gerät, und den echten LumenWert, den die Lichtmessgeräte ausgeben. Bei dem Gerät, das ich mal hatte, musste man an einem Sensor drei "Fenster" davor schieben. Reines Glas, Milchglas, und wohl besonders Licht-Undurchlässiges Milchglas. Ersatzweise dafür benutze ich ja die drei Lagen Papier. :oo: Und ein brauchbares Solarpanel möchte ich mir auch mal besorgen, um damit testen zu können. Das sollte man dann auch an dem Testgerät anschießen können, um erzielte Spannungs- und Stromwerte am Messgerät darstellen zu können. Ich hätte ja nichts dagegen, auch mal ein paar Euro mit meiner Technik verdienen zu können, dann muss ich aber auch wissen, was ich tue. Da ist Halbwissen nicht soooo gefragt. :(oo):

Franz

PS: Ich habe noch ein paar Änderungen am Programm gemacht. Wegen der ewigen Zappelei im Display. Kommastellen weg und Anzeige nur ändern wenn sich der Wert +/- 2 ändert. Weil das Schreiben am Display ja auch die meiste Programmzeit verbraucht. Jetzt ist es recht ruhig am Display. Und ich habe werend der Einstellfahrt auch die Änderungen der Panal - Spannungsanzeige im Display verhindert. Also die Änderungen im Display sind Zeitlich ein Nebengeräusch in Programm. Hier das aktuelle Programm:

Code: Alles auswählen

#include <LiquidCrystal_I2C.h>
// Display Adresse 0x3F 0der 0x27
LiquidCrystal_I2C lcd(0x27, 20, 4);
#include <Adafruit_ADS1X15.h> // bindet Wire.h für I2C mit ein
Adafruit_ADS1115 ads;
Adafruit_ADS1115 ads2;
#define ADS_I2C_ADDR 0x48
#define ADS_I2C_ADDR2 0x49
//------------------------------------------------------
#include <MobaTools.h>
int Rampe = 0;
const int STEPS_REVOLUTION = 6400; //Schritte pro Umdrehung Treibereinstellung
//Stepper einrichten ( 6400 Schritte / Umdrehung - 1/4 Microstep )
MoToStepper myStepper1( STEPS_REVOLUTION, STEPDIR );  // 6400 Steps/ Umdrehung
MoToStepper myStepper2( STEPS_REVOLUTION, STEPDIR );  // 6400 Steps/ Umdrehung
// Die Enable Pin´s werden nicht benutzt, dass die Motoren auch in Ruhe gebremst werden
const byte dirPin1       = 6;
const byte stepPin1      = 7;
const byte enaPin1       = 5; // Wird hier nicht benutzt
const byte dirPin2       = 9;
const byte stepPin2      = 10;
const byte enaPin2       = 8; // Wird hier nicht benutzt
int vspeed = 0;                 //Steppergeschwindigkeit in U/min*10
//-----------------------------------------------------
byte ablauf = 3; //3 = Tagbetrieb /4 = Nachtbetrieb
const float multiplier = 0.125F; // ADS1115-Multiplikator bei einf. Verstärkung
const byte panel = A0;
int panelwert = 0;
float panelspannung = 0;
float ads_mv0 = 0;  // Sensor rechts
float ads_mv1 = 0;  // Sensor links
float ads_mv2 = 0;  // Sensor hinten
float ads_mv3 = 0;  // Sensor vorne
int adc0 = 0;
int adc1 = 0;
int adc2 = 0;
int adc3 = 0;
float ads_mv4 = 0;  // Sensor rechts
float ads_mv5 = 0;  // Sensor links
float ads_mv6 = 0;  // Sensor hinten
float ads_mv7 = 0;  // Sensor vorne
int adc4 = 0;
int adc5 = 0;
int adc6 = 0;
int adc7 = 0;
int Messung1 = 0;
int Messung2 = 0;
int Messung3 = 0;
int Messung4 = 0;
int MessAlt1 = 0;
int MessAlt2 = 0;
int MessAlt3 = 0;
int MessAlt4 = 0;
const int startposvertikal = 25;
const int startposhorizontal = 60;
byte kontrolle1 = 0;
byte kontrolle2 = 0;
byte kontrolle3 = 0;
byte kontrolle4 = 0;
int posvertikal = startposvertikal;
int poshorizontal = startposhorizontal;
const byte Servo1 = 5;
const byte Servo2 = 6;
unsigned long sekundenablauf1 = 0; // Messabstand 1 Sekunde
const unsigned long pausezeit1 = 1000;
unsigned long aktuellzeit = 0;
void setup() {
  //----------------------------------------------------
  lcd.begin();
  lcd.backlight();
  lcd.clear();
  //----------------------------------------------------
  Serial.begin(9600);
  //----------------------------------------------------
  ads.begin(ADS_I2C_ADDR, &Wire);
  ads2.begin(ADS_I2C_ADDR2, &Wire);
  // Werte 1-fach verstärken (ESP32 liefert  max. 3,3V)
  ads.setGain(GAIN_ONE);
  ads2.setGain(GAIN_ONE);
  //----------------------------------------------------
  lcd.setCursor (0, 0);            // Zeile 1
  //----------------------------------------------------
  pinMode(panel, INPUT);         // Spannung vom Panel
  //----------------------------------------------------
  sekundenablauf1 = millis();
  //-----Stepper---------------------------------------
  myStepper1.attach( stepPin1, dirPin1 );
  myStepper1.attachEnable( enaPin1, 10, HIGH );        // Enable Pin deaktivieren ( LOW=aktiv )
  myStepper1.setSpeed( 10 );
  myStepper1.setRampLen( Rampe );                       // Rampenlänge 100 Steps bei 20U/min
  myStepper2.attach( stepPin2, dirPin2 );
  myStepper2.attachEnable( enaPin2, 10, HIGH );        // Enable Pin deaktivieren ( LOW=aktiv )
  myStepper2.setSpeed( 10 );
  myStepper2.setRampLen( Rampe );                       // Rampenlänge 100 Steps bei 20U/min
  //---------------------------------------------------
}
void loop() {
  aktuellzeit = millis();
  //Jede Sekunde Spannung am Panel messen
  if (aktuellzeit - sekundenablauf1 >= pausezeit1) // Eine Sekunde abgelaufen?
  {
    if ((kontrolle1 == 1) && (kontrolle2 == 1) && (kontrolle3 == 1) && (kontrolle4 == 1))
    {
      panelwert = analogRead(panel);
      panelspannung = panelwert * 20.3 / 1024.0;
      lcd.setCursor (14, 0);            // Zeile 1
      lcd.print (panelspannung);
      if (ablauf == 3)
      {
        lcd.setCursor (0, 0);            // Zeile 1
        lcd.print (F("Panelspannung "));
      }
      if (ablauf == 4)
      {
        lcd.setCursor (0, 0);            // Zeile 1
        lcd.print (F("Nachtbetrieb  "));
      }
      sekundenablauf1 = millis();
    }
  }
  // -----Kanal 0 Messung------------------------------
  adc0 = ads.readADC_SingleEnded(0);
  ads_mv0 = ads.computeVolts(adc0) * 1000;
  // -----Kanal 1 Messung------------------------------
  adc1 = ads.readADC_SingleEnded(1);
  ads_mv1 = ads.computeVolts(adc1) * 1000;
  Messung1 = ads_mv0 + ads_mv1;
  if (((Messung1 + 2) < MessAlt1) || ((Messung1 - 2) > MessAlt1))
  {
    lcd.setCursor (8, 3);            // Zeile 4
    lcd.print ("    ");
    lcd.setCursor (8, 3);            // Zeile 4
    lcd.print (Messung1);
    MessAlt1 = Messung1;
  }
  // -----Kanal 2 Messung------------------------------
  adc2 = ads.readADC_SingleEnded(2);
  ads_mv2 = ads.computeVolts(adc2) * 1000;
  // -----Kanal 3 Messung------------------------------
  adc3 = ads.readADC_SingleEnded(3);
  ads_mv3 = ads.computeVolts(adc3) * 1000;
  Messung2 = ads_mv2 + ads_mv3;
  if (((Messung2 + 2) < MessAlt2) || ((Messung2 - 2) > MessAlt2))
  {
    lcd.setCursor (8, 1);            // Zeile 2
    lcd.print ("    ");
    lcd.setCursor (8, 1);            // Zeile 2
    lcd.print (Messung2);
    MessAlt2 = Messung2;
  }
  // -----Kanal 4 Messung------------------------------
  adc4 = ads2.readADC_SingleEnded(0);
  ads_mv4 = ads.computeVolts(adc4) * 1000;
  // -----Kanal 5 Messung------------------------------
  adc5 = ads2.readADC_SingleEnded(1);
  ads_mv5 = ads.computeVolts(adc5) * 1000;
  Messung3 = ads_mv4 + ads_mv5;
  if (((Messung3 + 2) < MessAlt3) || ((Messung3 - 2) > MessAlt3))
  {
    lcd.setCursor (0, 2);            // Zeile 3
    lcd.print (Messung3);
    MessAlt3 = Messung3;
  }
  // -----Kanal 6 Messung------------------------------
  adc6 = ads2.readADC_SingleEnded(2);
  ads_mv6 = ads.computeVolts(adc6) * 1000;
  // -----Kanal 7 Messung------------------------------
  adc7 = ads2.readADC_SingleEnded(3);
  ads_mv7 = ads.computeVolts(adc7) * 1000;
  Messung4 = ads_mv6 + ads_mv7;
  if (((Messung4 + 2) < MessAlt4) || ((Messung4 - 2) > MessAlt4))
  {
    lcd.setCursor (15, 2);            // Zeile 3
    lcd.print (Messung4);
    MessAlt4 = Messung4;
  }
  //------------Lichtquelle suchen---------------------
  if (ablauf == 3)
  {
    //--------Horizontal Kontrolle plus--------------
    if (kontrolle1 == 0)
    {
      if ((Messung2) < Messung1) // Links dunkler als rechts
      {
        if (poshorizontal > 0)
        {
          if (myStepper1.moving() == 0)
          {
            poshorizontal = poshorizontal - 1; // Fahre nach rechts
            myStepper1.doSteps( -50 );         // Stepper dreht rückwärts
            lcd.setCursor (0, 3);
            lcd.print ("    ");
            lcd.setCursor (0, 3);
            lcd.print ("H-");
            lcd.print (poshorizontal);
          }
        }
      }
      else
      {
        kontrolle1 = 1;
        /*
          Serial.println(F("Messung2 < Messung1"));
          Serial.print(Messung2);
          Serial.print("  -  ");
          Serial.println(Messung1);
        */
      }
    }
    //--------Horizontal Kontrolle minus-------------
    if (kontrolle2 == 0)
    {
      if ((Messung2) > Messung1) // Links heller als rechts
      {
        if (poshorizontal < 110)
        {
          if (myStepper1.moving() == 0)
          {
            poshorizontal = poshorizontal + 1; // Fahre nacht Links
            myStepper1.doSteps( 50 );         // Stepper dreht Vorwärts
            lcd.setCursor (0, 3);
            lcd.print ("    ");
            lcd.setCursor (0, 3);
            lcd.print ("H-");
            lcd.print (poshorizontal);
          }
        }
      }
      else
      {
        kontrolle2 = 1;
        /*
          Serial.println(F("Messung2 > Messung1"));
          Serial.print(Messung2);
          Serial.print("  -  ");
          Serial.println(Messung1);
        */
      }
    }
    //-------Vertikale Kontrolle plus----------------
    if (kontrolle3 == 0)
    {
      if ((Messung4) < Messung3)  // Hinten dunkler als vorne
      {
        if (posvertikal > 0)
        {
          if (myStepper2.moving() == 0)
          {
            posvertikal = posvertikal - 1;  // Fahre runter
            myStepper2.doSteps( 50 ); // Stepper dreht rückwärts
            lcd.setCursor (15, 3);
            lcd.print ("   ");
            lcd.setCursor (15, 3);
            lcd.print ("V-");
            lcd.print (posvertikal);
          }
        }
      }
      else
      {
        kontrolle3 = 1;
        /*
          Serial.println(F("Messung4 < Messung3"));
          Serial.print(Messung4);
          Serial.print("  -  ");
          Serial.println(Messung3);
        */
      }
    }
    //--------Vertikal Kontrolle minus---------------
    if (kontrolle4 == 0)
    {
      if ((Messung4) > Messung3) // Hinten heller als vorne
      {
        if (posvertikal < 50)
        {
          if (myStepper2.moving() == 0)
          {
            posvertikal = posvertikal + 1; // Fahre hoch
            myStepper2.doSteps( -50 ); // Stepper dreht Vorwärts
            lcd.setCursor (15, 3);
            lcd.print ("    ");
            lcd.setCursor (15, 3);
            lcd.print ("V-");
            lcd.print (posvertikal);
          }
        }
      }
      else
      {
        kontrolle4 = 1;
        /*
          Serial.println(F("Messung4 > Messung3"));
          Serial.print(Messung4);
          Serial.print("  -  ");
          Serial.println(Messung3);
        */
      }
    }
    //-------Vertikale Kontrolle Ende-----------------

    //------------Lichtquelle suchen Ende-------------
  }
  //------------Kontrolle wieder aktivieren-------------
  //--------------------auf / ab------------------------
  if (ablauf == 3)
  {
    if (kontrolle1 == 1)
    {
      if ((Messung2 + 100) <= Messung1) // Links dunkler als rechts
      {
        kontrolle1 = 0;
      }
    }
    if (kontrolle2 == 1)
    {
      if ((Messung2) >= (Messung1 + 100)) // Links heller als rechts
      {
        kontrolle2 = 0;
      }
    }
    //-----------------rechts / links-------------------
    if (kontrolle3 == 1)
    {
      if ((Messung4 + 100) <= Messung3)  // Hinten dunkler als vorne
      {
        kontrolle3 = 0;
      }
    }
    if (kontrolle4 == 1)
    {
      if ((Messung4) >= (Messung3 + 100)) // Hinten heller als vorne
      {
        kontrolle4 = 0;
      }
    }
  }
  //-----------------------------------------------------
  //--------------Kontrolle ob schon zu Dunkel-----------
  if ((Messung1 < 1000) || (Messung2 < 1000) || (Messung3 < 1000) || (Messung4 < 1000))
  {
    ablauf = 4;
  }
  else
  {
    if ((Messung1 > 1400) && (Messung2 > 1400) && (Messung3 > 1400) && (Messung4 > 1400))
    {
      ablauf = 3;
    }
  }
  //-----------------------------------------------------
  //---------In die Nachtposition fahren-----------------
  if (ablauf == 4)
  {
    kontrolle1 = 1;
    kontrolle2 = 1;
    kontrolle3 = 1;
    kontrolle4 = 1;

    //ServoVertikal.write(startposvertikal);
    //ServoHorizontal.write(startposhorizontal);
  }
  //-----------------------------------------------------
}
Benutzeravatar
Admin
Administrator
Beiträge: 1196
Registriert: Mo 20. Apr 2020, 09:47
Wohnort: 82441 Ohlstadt
Kontaktdaten:

Re: Die Position der Sonne mit Sensoren bestimmen

Beitrag von Admin »

Ich habe noch ein Problem gefunden, das mir nicht gefällt.

Ich schalte normal an einem bestimmten Punkt die Spannung ein. Wenn das Panel in die Sonne gedreht wird, verändern sich die Positionswerte. Die sind aber weg, wenn ich einen Stromausfall habe. Somit fängt die Kiste dann bei den Startpositinen an, an denen die Motoren aber nach dem Stromausfall nicht stehen. :(o): :(o): Also brauche ich eine Zentrierungsfahrt, auf beiden Motoren. Wenn die Spannung kommt, auf eine "Nullposition fahren", und dann erst nach der Sonne suchen. Also brauche ich zwei Endschalter, für jeden Motor einen, an die ich erst mal fahre um die Motoren an die Nullpos. zu fahren. Bräuchte ich zwar bei meinem Testgerät nicht, aber ich möchte dass das Ding Hard- & Sofware Technisch einwandfrei funktioniert.
Also müßen diese beiden Schalter noch dran. :O:

Ich möchte diese Zentrierungsfahrt auch nach jedem Start am Morgen, wenn das Licht wieder für den Betrieb passt, einmal machen. Das ist sinnvoll, weil sich ja Fehler im Speicher einschleichen könnten, die dann ohne diese Zentrierungsfahrt immer wieder aufaddiert werden. Wie Max schon leidlich festgestellt hat, fährt die Kiste dann irgendwann ins Nirvana und reißt die Kabel kaputt, weil die ja nicht dafür gedacht sind, dass sie aufgewickelt werden.

Ich habe mit dem Ausgleichsgewicht dafür gesorgt, dass die Platine nicht runtersaust, wenn man die Spannung wegnimmt. Und das Display macht fast keine Anzeigen, wenn das Panel bewegt wird. Dass der Arduine beim Messen und fahren nicht unnötig gebremst wird. Sieht man hier im Video. Beim Fahren wird nur die Position angezeigt, H-xxx für Horizontal und V-xxx für Vertikal. Und wenn dann die Endposition erreicht ist, dann werden alle Daten angezeigt.

Hier der aktuelle Video.
Max
Beiträge: 78
Registriert: Di 27. Sep 2022, 17:37
Kontaktdaten:

Re: Die Position der Sonne mit Sensoren bestimmen

Beitrag von Max »

Hallo Franz,

das mit dem Resetschalter ist natürlich wichtig.
Die Werkzeugmaschinen verfahren nach dem selben Prinzip,
die würden sonst auch morgens, nach dem Einschalten, nicht wissen wo sie stehen.
Dadurch hat man immer eine gleich Ausgangsposition.
Vielleicht würde ja ein Schalter genügen, wenn Du bei zuwenig Licht
auf Schalterposition fährst.
Das ganze sieht im Video schon sehr gut aus.
Gruß
Max
Benutzeravatar
Admin
Administrator
Beiträge: 1196
Registriert: Mo 20. Apr 2020, 09:47
Wohnort: 82441 Ohlstadt
Kontaktdaten:

Re: Die Position der Sonne mit Sensoren bestimmen

Beitrag von Admin »

Ja, das habe ich hier realisiert. Schaut nur nicht schön aus, weil ich da mit einem Endschalter in alle 4 Richtungen am Ende des möglichen Weges in den selben Endschalter fahre. Dieser Schalter löst einen Reset aus. Das ist ein extra vorhandener Punkt am Arduino, der auf jeden Fall das Programm stoppt, und die CPU neustartet. Aber das Programm kann trotzdem nicht neu starten, weil der Schalter ja immer noch im Reset hängt. Durch einen Druck auf den Taster, der mit dem Leuchtring auch anzeigt dass der Reset betätigt ist, kann ich den Reset unterbrechen, und den Tisch wieder "frei fahren". Dann gehts ganz normal weiter.

Franz

PS: Bei richten Werkzeugmaschinen wird natürlich der Reset noch sicherer gemacht, indem bei auslösen des Resets die komplette Spannung ausgeschalten wird. Aber ich will eben auch noch elektrisch gesteuert aus dem Notstop wieder rauskommen, was nur auf meine Weise, wir hier gebaut, geht. Würde aber für Maschinen die zum Verkauf gedacht sind, nicht zugelassen werden. Da darf "Notaus" nicht nur so heißen, sondern muss auch absolutes NOTAUS sein. :(o): :(o):
Max
Beiträge: 78
Registriert: Di 27. Sep 2022, 17:37
Kontaktdaten:

Re: Die Position der Sonne mit Sensoren bestimmen

Beitrag von Max »

Hallo Franz,
Bei richten Werkzeugmaschinen wird natürlich der Reset noch sicherer gemacht, indem bei auslösen des Resets die komplette Spannung ausgeschalten wird.
Ich meinte mit dem auf Position fahren nicht den Reset, bin halt doch schon 10 Jahre draussen,
sondern eine Art Referenzpunkt anfahren.
Einen Startpunkt anfahren für den morgigen Beginn.
Ein nicht geplantes Verstellen (z.B. Gegengewicht) der Anlage vermeidet ein Schneckentrieb mit Selbsthemmung.

Gruß
Max
Dateianhänge
P1100252.JPG
P1100252.JPG (40.38 KiB) 863 mal betrachtet
Benutzeravatar
Admin
Administrator
Beiträge: 1196
Registriert: Mo 20. Apr 2020, 09:47
Wohnort: 82441 Ohlstadt
Kontaktdaten:

Re: Die Position der Sonne mit Sensoren bestimmen

Beitrag von Admin »

Max hat geschrieben: Di 15. Nov 2022, 14:49 ....sondern eine Art Referenzpunkt anfahren.
Einen Startpunkt anfahren für den morgigen Beginn.
Ahhh ok, das ist das, was mir noch fehlt. Im Moment bin ich zu faul, beziehungsweise mache gerade an einem anderen Thema weiter. Mein X-Y Frästisch. Ich habe jetzt eine Ständer - Bohrmaschine die ich dazu verwenden kann. Die macht nur bis zu 2800 Umdrehungen, also ist ein sehr müdes Gerät, aber die tut es für´n Anfang. Das was mir eigentlich vorschwebt, kostet nochmal 350 - 400 Euronen. Das geht im Mom. nicht. :???: Also vertage ich das erst mal, und mache mal einen Notbehelf.

Das mit den beiden Referenzpunkt - Kontakten ist aber bis zum WE sicher auch gemacht.
Benutzeravatar
Admin
Administrator
Beiträge: 1196
Registriert: Mo 20. Apr 2020, 09:47
Wohnort: 82441 Ohlstadt
Kontaktdaten:

Re: Die Position der Sonne mit Sensoren bestimmen

Beitrag von Admin »

Ich arbeite gerade an meinen Referenzfahrten am Beginn des Programmes. Hall Effekt Sensoren sind bestellt, den einzigen den ich hier hatte, habe ich offenbar gekillt :lol: Habe mir 5 neue bestellt. Jetzt zum Testen ersetze ich diese Begrenzer durch Tasten :(o): :(o): Am Dienstag sollten diese neuen Hall Effekt Sensoren bei mir aufschlagen. :(V): ...die Magneten dazu habe ich fast vergessen, aber dann doch noch bestellt. :(o): :(o):

Ich denke heute Abend habe ich das System soweit klar. Im Moment stehe ich bischen am Schlauch, und kriegen meine Gedanken nicht klar. Also habe ich das Ding erst mal wieder zur Seite gestellt :(oo):.....jetzt muss ich erst mal die beiden Hall Efekt Sensoren an den Motoren einbauen. Das Programm ist dafür schon erweitert. Dann wird wieder ein Test im Freien kommen. Ich bin mir im Moment noch nicht sicher, ob ich Panelspannung doch noch für eine sichere und schnellere Erst-Positionierung einbeziehen sollte. Aber das wird sich dann zeigen.

Franz
Benutzeravatar
Admin
Administrator
Beiträge: 1196
Registriert: Mo 20. Apr 2020, 09:47
Wohnort: 82441 Ohlstadt
Kontaktdaten:

Re: Die Position der Sonne mit Sensoren bestimmen

Beitrag von Admin »

Also im Moment denke ich bin ich ganz gut. Nur habe ich meine Hall-Sensoren noch nicht, die muss ich zur Zeit immitieren. Aber dafür habe ich ja meine Hilfsmittel für die Versuchskonsolen gebaut. Einfach ein Bedienkästchen anstecken, und schon hat man Display, Poti, Tasten und LED´s zur Verfügung.
Hier im Bild ist der derzeitige Aufbau. Die beiden Tasten neben dem Poti sind meine zwei "Hall-Sensoren" für Vertikal und Horizontal :(o):
Hier mal wieder das derzeit aktuelle Programm. Natürlich muss man die Fahrwerte entsprechend anpassen, wenn man Motoren mit Getriebe verwendet, was bei den großen Panels der Fall ist. Z.B. ein Getriebe 1:100 am Nema 23 Motor. Dann muss man die Schritte, die hier im Programm 25 sind mal Hundert rechnen, also 2500. Das gilt für alle Fahrbewegungen und für die zugehörigen Kontrollzähler. Und das Display muss man dann anders organisieren, weil dann in der vierten Zeile der Platz ausgeht.

Code: Alles auswählen

#include <LiquidCrystal_I2C.h>
// Display Adresse 0x3F 0der 0x27
LiquidCrystal_I2C lcd(0x27, 20, 4);
#include <Adafruit_ADS1X15.h> // bindet Wire.h für I2C mit ein
Adafruit_ADS1115 ads;
Adafruit_ADS1115 ads2;
#define ADS_I2C_ADDR 0x48
#define ADS_I2C_ADDR2 0x49
//------------------------------------------------------
#include <MobaTools.h>
int Rampe = 10;
const int STEPS_REVOLUTION = 6400; //Schritte pro Umdrehung Treibereinstellung
//Stepper einrichten ( 6400 Schritte / Umdrehung - 1/4 Microstep )
MoToStepper myStepper1( STEPS_REVOLUTION, STEPDIR );  // 6400 Steps/ Umdrehung
MoToStepper myStepper2( STEPS_REVOLUTION, STEPDIR );  // 6400 Steps/ Umdrehung
// Die Enable Pin´s werden nicht benutzt, dass die Motoren auch in Ruhe gebremst werden
const byte dirPin1       = 6;
const byte stepPin1      = 7;
const byte enaPin1       = 5; // Wird hier nicht benutzt
const byte dirPin2       = 9;
const byte stepPin2      = 10;
const byte enaPin2       = 8; // Wird hier nicht benutzt
int vspeed = 0;                 //Steppergeschwindigkeit in U/min*10
//-----------------------------------------------------
byte ablauf = 3; //3 = Tagbetrieb /4 = Nachtbetrieb
const float multiplier = 0.125F; // ADS1115-Multiplikator bei einf. Verstärkung
const byte panel = A0;
int panelwert = 0;
float panelspannung = 0;
float ads_mv0 = 0;  // Sensor rechts
float ads_mv1 = 0;  // Sensor links
float ads_mv2 = 0;  // Sensor hinten
float ads_mv3 = 0;  // Sensor vorne
int adc0 = 0;
int adc1 = 0;
int adc2 = 0;
int adc3 = 0;
float ads_mv4 = 0;  // Sensor rechts
float ads_mv5 = 0;  // Sensor links
float ads_mv6 = 0;  // Sensor hinten
float ads_mv7 = 0;  // Sensor vorne
int adc4 = 0;
int adc5 = 0;
int adc6 = 0;
int adc7 = 0;
int Messung1 = 0;
int Messung2 = 0;
int Messung3 = 0;
int Messung4 = 0;
int MessAlt1 = 0;
int MessAlt2 = 0;
int MessAlt3 = 0;
int MessAlt4 = 0;
byte refhorizontal = 1;
const byte hallsensorH = 39;
byte refvertikal = 1;
const byte hallsensorV = 40;
byte Status = 0;
byte kontrolle1 = 0;
byte kontrolle2 = 0;
byte kontrolle3 = 0;
byte kontrolle4 = 0;
int posvertikal = 0;
int poshorizontal = 0;
const byte Servo1 = 5;
const byte Servo2 = 6;
unsigned long sekundenablauf1 = 0; // Messabstand 1 Sekunde
const unsigned long pausezeit1 = 1000;
unsigned long aktuellzeit = 0;
//==============================================================
//=========================SETUP================================
//==============================================================
void setup() {
  //----------------------------------------------------
  lcd.begin();
  lcd.backlight();
  lcd.clear();
  //----------------------------------------------------
  Serial.begin(115200);
  //----------------------------------------------------
  ads.begin(ADS_I2C_ADDR, &Wire);
  ads2.begin(ADS_I2C_ADDR2, &Wire);
  // Werte 1-fach verstärken (ESP32 liefert  max. 3,3V)
  ads.setGain(GAIN_ONE);
  ads2.setGain(GAIN_ONE);
  //----------------------------------------------------
  lcd.setCursor (0, 0);            // Zeile 1
  //----------------------------------------------------
  pinMode(panel, INPUT);         // Spannung vom Panel
  pinMode(hallsensorH, INPUT_PULLUP);
  pinMode(hallsensorV, INPUT_PULLUP);
  //----------------------------------------------------
  sekundenablauf1 = millis();
  //-----Stepper---------------------------------------
  myStepper1.attach( stepPin1, dirPin1 );
  myStepper1.attachEnable( enaPin1, 10, HIGH );  //Enable Pin deaktivieren ( LOW=aktiv )
  myStepper1.setSpeed( 10 );
  myStepper1.setRampLen( Rampe );                //Rampenlänge 100 Steps bei 20U/min
  myStepper2.attach( stepPin2, dirPin2 );
  myStepper2.attachEnable( enaPin2, 10, HIGH );  //Enable Pin deaktivieren ( LOW=aktiv )
  myStepper2.setSpeed( 10 );
  myStepper2.setRampLen( Rampe );                //Rampenlänge 100 Steps bei 20U/min
  //---------------------------------------------------
}
//==============================================================
//=========================LOOP=================================
//==============================================================
void loop() {
  aktuellzeit = millis();
  //-------------------Referenzfahrten_Horizont-----------------
  if (Status == 0)
  {
  lcd.setCursor (0, 0);            // Zeile 1
  lcd.print (F("Referenzfahrt Start "));
  Status = 1;
  }
  if (refhorizontal == 1)
  {
    myStepper1.doSteps( -10 );         // Stepper dreht vorwärts
    refhorizontal = digitalRead(hallsensorH);
    if (refhorizontal == 0)
    {
      myStepper1.stop();
      poshorizontal = 0;
    }
  }
  //---------------Referenzfahrten_Vertikal--------------------
  if (refvertikal == 1)
  {
    myStepper2.doSteps( -10 );         // Stepper dreht vorwärts
    refvertikal = digitalRead(hallsensorV);
    if (refvertikal == 0)
    {
      myStepper1.stop();
      posvertikal = 0;
    }
  }
  //===========================================================
  if ((refhorizontal == 0) && (refvertikal == 0))
  {
     if (Status == 1)
  {
  lcd.setCursor (0, 0);            // Zeile 1
  lcd.print (F("Hauptprogramm Start "));
  Status = 2;
  }
    //Jede Sekunde Spannung am Panel messen
    if (aktuellzeit - sekundenablauf1 >= pausezeit1) // Eine Sekunde abgelaufen?
    {
      panelwert = analogRead(panel);
      panelspannung = panelwert * 20.3 / 1024.0;
      /*
        Serial.print(kontrolle1);
        Serial.print(" + ");
        Serial.print(kontrolle2);
        Serial.print(" + ");
        Serial.print(kontrolle3);
        Serial.print(" + ");
        Serial.print(kontrolle4);
        Serial.print(" H=");
        Serial.print(poshorizontal);
        Serial.print(" V=");
        Serial.print(posvertikal);
        Serial.print(" M1=");
        Serial.print(Messung1);
        Serial.print(" M2=");
        Serial.print(Messung2);
        Serial.print(" M3=");
        Serial.print(Messung3);
        Serial.print(" M4=");
        Serial.println(Messung4);
      */
      if ((kontrolle1 == 1) && (kontrolle2 == 1) && (kontrolle3 == 1) && (kontrolle4 == 1))
      {
        lcd.setCursor (14, 0);            // Zeile 1
        lcd.print (panelspannung);
        if (ablauf == 3)
        {
          lcd.setCursor (0, 0);            // Zeile 1
          lcd.print (F("Panelspannung "));
        }
        if (ablauf == 4)
        {
          lcd.setCursor (0, 0);            // Zeile 1
          lcd.print (F("Nachtbetrieb  "));
        }
      }
      sekundenablauf1 = millis();
    }
    // -----Kanal 0 Messung------------------------------
    adc0 = ads.readADC_SingleEnded(0);
    ads_mv0 = ads.computeVolts(adc0) * 1000;
    // -----Kanal 1 Messung------------------------------
    adc1 = ads.readADC_SingleEnded(1);
    ads_mv1 = ads.computeVolts(adc1) * 1000;
    Messung1 = ads_mv0 + ads_mv1 + 200; // Die +200 sind Anpassung der Sensoren
    // -----Kanal 2 Messung------------------------------
    adc2 = ads.readADC_SingleEnded(2);
    ads_mv2 = ads.computeVolts(adc2) * 1000;
    // -----Kanal 3 Messung------------------------------
    adc3 = ads.readADC_SingleEnded(3);
    ads_mv3 = ads.computeVolts(adc3) * 1000;
    Messung2 = ads_mv2 + ads_mv3 + 200; // Die +200 sind Anpassung der Sensoren
    // -----Kanal 4 Messung------------------------------
    adc4 = ads2.readADC_SingleEnded(0);
    ads_mv4 = ads.computeVolts(adc4) * 1000;
    // -----Kanal 5 Messung------------------------------
    adc5 = ads2.readADC_SingleEnded(1);
    ads_mv5 = ads.computeVolts(adc5) * 1000;
    Messung3 = ads_mv4 + ads_mv5; //
    // -----Kanal 6 Messung------------------------------
    adc6 = ads2.readADC_SingleEnded(2);
    ads_mv6 = ads.computeVolts(adc6) * 1000;
    // -----Kanal 7 Messung------------------------------
    adc7 = ads2.readADC_SingleEnded(3);
    ads_mv7 = ads.computeVolts(adc7) * 1000;
    Messung4 = ads_mv6 + ads_mv7;
    //---------------------------------------------------
    //---------Fahren_Horizontal_Licht_suchen------------
    //---------------------------------------------------
    if (ablauf == 3)
    {
      //--------Horizontal Kontrolle plus--------------
      if (kontrolle1 == 0)
      {
        if (Messung2 > Messung1) // Links dunkler als rechts
        {
          if (poshorizontal < 4750)
          {
            if (myStepper1.moving() == 0)
            {
              poshorizontal = poshorizontal  + 25; // Fahre nach rechts
              myStepper1.doSteps( 25 );         // Stepper dreht -1
            }
          }
          else
          {
            kontrolle1 = 1;
          }
        }
        else
        {
          kontrolle1 = 1;
        }
      }
      //--------Horizontal Kontrolle minus-------------
      if (kontrolle2 == 0)
      {
        if ((Messung2) < Messung1) // Links heller als rechts
        {
          if (poshorizontal > 0)
          {
            if (myStepper1.moving() == 0)
            {
              poshorizontal = poshorizontal - 25; // Fahre nacht Links
              myStepper1.doSteps( -25 );         // Stepper dreht +1
            }
          }
          else
          {
            kontrolle2 = 1;
          }
        }
        else
        {
          kontrolle2 = 1;
        }
      }
      //---------------------------------------------------
      //----------Fahren_Vertikal_Licht_suchen-------------
      //---------------------------------------------------
      //-----------Vertikale Kontrolle plus----------------
      if (kontrolle3 == 0)
      {
        if ((Messung4) < Messung3)  // Hinten dunkler als vorne
        {
          if (posvertikal < 3100)
          {
            if (myStepper2.moving() == 0)
            {
              posvertikal = posvertikal + 25;  // Fahre runter
              myStepper2.doSteps( 25 ); // Stepper dreht +1
            }
          }
          else
          {
            kontrolle3 = 1;
          }
        }
        else
        {
          kontrolle3 = 1;
        }
      }
      //-------------Vertikal Kontrolle minus---------------
      if (kontrolle4 == 0)
      {
        if ((Messung4) > Messung3) // Hinten heller als vorne
        {
          if (posvertikal > 0)
          {
            if (myStepper2.moving() == 0)
            {
              posvertikal = posvertikal - 25; // Fahre hoch
              myStepper2.doSteps(-25 ); // Stepper dreht -1
            }
          }
          else
          {
            kontrolle4 = 1;
          }
        }
        else
        {
          kontrolle4 = 1;
        }
      }
      //---------Vertikale Kontrolle Ende-----------------

      //--------Fahren_Lichtquelle suchen Ende------------
    }
    //------------Kontrolle wieder aktivieren-------------
    //--------------------auf / ab------------------------
    if (ablauf == 3)
    {
      if (kontrolle1 == 1)
      {
        if (Messung2 > (Messung1 + 100)) // Links dunkler als rechts
        {
          kontrolle1 = 0;
        }
      }
      if (kontrolle2 == 1)
      {
        if ((Messung2 + 100) < Messung1) // Links heller als rechts
        {
          kontrolle2 = 0;
        }
      }
      //------------Kontrolle wieder aktivieren-------------
      //------------------rechts / links--------------------
      if (kontrolle3 == 1)
      {
        if ((Messung4 + 200) <= Messung3)  // Hinten dunkler als vorne
        {
          kontrolle3 = 0;
        }
      }
      if (kontrolle4 == 1)
      {
        if ((Messung4) >= (Messung3 + 200)) // Hinten heller als vorne
        {
          kontrolle4 = 0;
        }
      }
    }
    //-----------------------------------------------------
    //--------------Kontrolle ob schon zu Dunkel-----------
    if ((Messung1 < 1000) || (Messung2 < 1000) || (Messung3 < 1000) || (Messung4 < 1000))
    {
      ablauf = 4;
    }
    else
    {
      if ((Messung1 > 1400) && (Messung2 > 1400) && (Messung3 > 1400) && (Messung4 > 1400))
      {
        ablauf = 3;
      }
    }
    //-----------------------------------------------------
    //---------In die Nachtposition fahren-----------------
    if (ablauf == 4)
    {
      kontrolle1 = 1;
      kontrolle2 = 1;
      kontrolle3 = 1;
      kontrolle4 = 1;

      //ServoVertikal.write(startposvertikal);
      //ServoHorizontal.write(startposhorizontal);

    }
    // ---------------Ende Referenzpunkt suchen--------------
  }
  //---------------------Display alle Anzeigen---------------
  if ((kontrolle1 == 1) && (kontrolle2 == 1) && (kontrolle3 == 1) && (kontrolle4 == 1))
  {
    if (((Messung1 + 2) < MessAlt1) || ((Messung1 - 2) > MessAlt1))
    {
      lcd.setCursor (7, 3);            // Zeile 4
      lcd.print ("1-    ");
      lcd.setCursor (9, 3);            // Zeile 4
      lcd.print (Messung1);
      MessAlt1 = Messung1;
    }

    if (((Messung2 + 2) < MessAlt2) || ((Messung2 - 2) > MessAlt2))
    {
      lcd.setCursor (6, 1);            // Zeile 2
      lcd.print ("H2-    ");
      lcd.setCursor (9, 1);            // Zeile 2
      lcd.print (Messung2);
      MessAlt2 = Messung2;
    }

    if (((Messung3 + 2) < MessAlt3) || ((Messung3 - 2) > MessAlt3))
    {
      lcd.setCursor (0, 2);
      lcd.print ("V3-    ");
      lcd.setCursor (3, 2);            // Zeile 3
      lcd.print (Messung3);
      MessAlt3 = Messung3;
    }

    if (((Messung4 + 2) < MessAlt4) || ((Messung4 - 2) > MessAlt4))
    {
      lcd.setCursor (12, 2);
      lcd.print ("V4-    ");
      lcd.setCursor (15, 2);            // Zeile 3
      lcd.print (Messung4);
      MessAlt4 = Messung4;
    }

    lcd.setCursor (0, 3);
    lcd.print ("     ");
    lcd.setCursor (0, 3);
    lcd.print ("H-");
    lcd.print (poshorizontal);

    lcd.setCursor (14, 3);
    lcd.print ("     ");
    lcd.setCursor (14, 3);
    lcd.print ("V-");
    lcd.print (posvertikal);
  }
  //----------------------Ende Loop----------------------
}
.
Sonnen_Nachführung_05.jpg
Sonnen_Nachführung_05.jpg (477.91 KiB) 805 mal betrachtet
Benutzeravatar
Admin
Administrator
Beiträge: 1196
Registriert: Mo 20. Apr 2020, 09:47
Wohnort: 82441 Ohlstadt
Kontaktdaten:

Re: Die Position der Sonne mit Sensoren bestimmen

Beitrag von Admin »

Ich habe mal eine Zeitmessung eingebaut, um zu sehen wie lange ein Loop-Durchgang in diesem Programm dauert. Das ist schon sehr lang, obwohl ich wie immer keine einzige delay() Bremse im Programm habe. 75ms, wenn keine Display-Ausgabe aktiv ist. 110 - 150ms wenn das Display aktiv ist. In jedem Loop werden 9 Spannungen gemessen und ausgewertet. Entsprechend Motoren gesteuert, u.s.w. Wenn die Motoren laufen, also wenn das Gerät Horizontal, oder Vertikal gefahren wird, ist jegliche Displayausgabe deaktiviert, dass das Programm die Motorsteuerung zeitnah bedienen kann, um starkes gezittere zu verhindern. Das Programm gibt an Lib. MobaTools immer 25 Schritte aus, kontrolliert dann in den Loop´s ob diese abgearbeitet sind, und wenn alle 25 Schritte gefahren sind, gibt es wieder 25 Schritte aus. Kann sein, dass ich diese 25 Schritte noch erhöhe. Wärend dieser Fahrt werden in jedem Loop-Durchlauf die Lichtverhältnisse neu an allen 4 Lichtsensoren gemessen und miteinander verglichen, dass immer klar ist wohin das Gerät drehen oder schwenken muss, um das Panel ins beste Licht zu rücken. Am Beginn des Programmes ist eine Referenzfahrt eingebaut, wo noch nicht gemessen wird, sondern beide Motoren sich nur auf den Null-Punkt zubewegen und wenn der Entsprechende Sensor das Erreichen des Nullpunktes meldet, den Motor stoppt und den Schrittzähler für diesen Motor auf NUll stellt. Wenn das auf beiden Motoren erledigt ist, wird das eigentliche Steuer- und Messprogramm gestartet. So mal grob umrissen der Ablauf des Programmes. Da ist auch noch die Überprüfung, ob noch genug Licht vorhanden ist, wenn nicht wird eine "Nachtposition angefahren, aber diese Nachtposition habe ich noch nicht integriert. Ich nehme mal an, da werde ich auch die Null-Pos. beider Motoren nutzen, bei der Gelegenheit kann dann gleich wieder eine neue Zentrierung der Motoren auf die Null-Pos. vorgenommen werden. Wenn das Gerät arbeitet, wird immer die beste Pos. eingenommen, und dann wieder die Nachregulierung gestoppt, ausser die Lichtposition hat sich um mindestens 100 Schritte (6400 Schritte sind eine ganze Umdrehung!) in einer der 4 Richtungen verändert. Dann wird die Stellung nachjustiert und wieder in "habacht Stellung" gestoppt.

Franz

PS: Ich könnte natürlich genauso wie bei der Displayausgabe der Panel-Spannung sagen, es wird nur einmal jede Minute gemessen, aber das bringt keine Verbesserung des Programmes, denn es hat in der Programmfase nichts zu tun, ausser diese Kontrollen, und daraus resultierende Nachjustierungen auszuführen.
Benutzeravatar
Admin
Administrator
Beiträge: 1196
Registriert: Mo 20. Apr 2020, 09:47
Wohnort: 82441 Ohlstadt
Kontaktdaten:

Re: Die Position der Sonne mit Sensoren bestimmen

Beitrag von Admin »

Soooo, die Magnet-Sensoren für die Startposition sind eingebaut. Diese Dinger funtionieren suuuper. Jetzt warte ich noch auf ein trockenes, warmes Wetter, dann mache ich mal einen Testlauf draussen. Jetzt macht die Mühler einen neuen Referanzlauf, wenn Stromausfall war, oder wenn der neue Morgen beginnt. Gefällt mir seeeeehr gut. Meinen Nachschub an Nanos V3.0 habe ich jetzt auch bekommen. Die sind ja wieder aus China angereist. :(o): .....hatte die Dinger schon völlig vergessen. Also die heute auch kamen habe ich gestaunt, was ich da alles bekomme :O:

Franz

PS: Ich mache mal nen Video, wenn ich draussen Teste. :(V):

Video draussen kommt noch, das ist jetzt erst mal am Bastelplatz.

So, erste Fahrt im einigermaßen fertigen Zustand im Garten bei schöner Sonne.

Jetzt habe ich hier noch einen Auszug aus dem Video. Das Display nach dem beenden der Fahrt auf die Sonne. Die Werte sind trotz voller Sonne im Bereich 7200 bis 7500 von 8190 möglicher Stärke. Das dürfte reichen. Die Panel-Spannung 13,10 Volt ist auch deutlich über dem, was ich mit den wirklich hellen Lampen an meinem Arbeitsplatz erzeugen kann. Am Arbeitsplatz war das hellste was ich da am Display mal gesehen habe 8,6 Volt.
.
Sonnen_Nachführung_Display_01.jpg
Sonnen_Nachführung_Display_01.jpg (126.39 KiB) 720 mal betrachtet
Was mich bischen stört, ist die Tatsache, dass er eigentlich Vertikal noch weiter runter möchte, aber schon auf "0" ist. Vertikal 4 ist der Untere Lichtsensor, der immer noch mehr Licht bekommt als der V3, also der Obere Sensor. Was bei der tiefen Stellung schon ein wenig ungewöhnlich ist. :roll: Aber ich habe ja die Sensoren abgeglichen. Naja, ich lasse es fürs erste mal so stehen. Wenn ich dann viel Lust habe, kann ich mich ja nochmal drüber machen. :(oo):
Antworten

Zurück zu „Hardware / Schaltungstechnik“

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 5 Gäste