Forum: Mikrocontroller und Digitale Elektronik Problem mit abspeichern von Variablen


von Gast (Gast)


Lesenswert?

Hi,
folgender Sachverhalt.
Habe eine Solarzelle die auf einem Drehteller montiert ist welcher von 
einem Motor angetrieben wird.
Während des Drehvorgangs soll die Momentanspannung mit der 
abgespeicherten Spanung verglichen werden, und wenn diese größert ist 
als der wert in der Variablen soll der neue Wert in die Variable 
abgespeichert werden!
Der Vergleich soll 8 mal gemacht werden. Jede Sekunde ein mal.

Den wert der Variablen habe ich am anfang = 0 gesetzt.

Letztendlich soll die Solarzelle selbstständig auf die Position fahren 
wo die größte Lichtintensität ist.

Das Problem:  Mein Programm Speichert nur ein mal den wert der Spannung 
(immer beim ersten Vergleich)danach bleibt der Wert Konstant.

Vollständigheits halber habe ich den ganzen code als Angang beigefügt.

Ich arbeite mit einem ATmega32
und programmiere in C

Bin noch recht unerfahren in der Programmierung (erstes etwas größeres 
Projekt) hoffe jeband von euch hat nen guten Tip.

Schon mal danke im vorraus.

C-Code:

for(i=1;i<=8;i++)
        {
      lcd_clear();
      set_cursor(2,2);
      lcd_string("Bitte warten....");
      MOTOR_Links();
      DELAY(DELAY_LS_1s);

        if(Spannung1>Spannung2)
        {
          Spannung2 = adcval;
          Time =i;
        }
    }


    uint8_t j =(8-Time);

      for(i=1;i<=j;i++)
        {
            lcd_clear();
            set_cursor(2,2);
            lcd_string("Bitte warten....");
            MOTOR_Links();
            DELAY(DELAY_LS_1s);
        }

von Gast (Gast)


Angehängte Dateien:

Lesenswert?

Angang wurde nicht mit hochgelanden

von Ralf W. (Gast)


Lesenswert?

Hallo,

du deklarierst und initialisierst Spannung1 einmal so:

>  uint16_t Spannung1  = adcval;

und Spannung2 deklarierst und initialisierst du so:

>  uint16_t Spannung2  = 0;

dann hast du in deiner For Schleife folgenden Vergleich:

>        if(Spannung1>Spannung2)
>        {
>          Spannung2 = adcval;
>          Time =i;
>        }

Das heist, die erste Prüfung dieser Bedingung wird mit grosser
Warscheinlickeit immer klappen. Ausser der ADC liefert rein
zufällig 0.
Im Prinzip vergleichst du momentaner ADC Wert > 0(zB. 128 > 0).

So. Jetzt befindet sich dein Programm in dem Codeblock der zur
If Bedingung gehört. Dort weisst du Spannung2 einen neuen ADC Wert
zu. Sollte dieser allerdings zufällig höher als Spannung1 sein (zB. 
256),
wird beim erneuten durchlaufen der For Schleife die If Bedingung nie
mehr war. Der Vergleich würde jetzt lauten 128 > 256.

Besser wäre zb. folgender Code:

uint16_t MaximalWert = 0;

for(....{
...
...
    Momentanwert = AdcValue();
    if(MomentanWert > MaximalWert){
    ...
    ...
        MaximalWert = MomentanWert;
    }
...
...
}

gruss ralf

von Gast (Gast)


Lesenswert?

Hi erst einmal danke für die Antwort.

hatte das wie folgt umgesetzt:


for(i=1;i<=8;i++)
{
        Spannung_mom  = adcval;
  if(Spannung_mom>Spannung_max)
  {
      Spannung_max = Spannung_mom;
      Time =i;
  }
}

hat aber leider nicht funktioniert :-(

von Ralf W. (Gast)


Lesenswert?

Ja. Ist klar. Du machst folgendes:

>  uint16_t adcval;

>  uint16_t Spannung1  = adcval;
>  uint16_t Spannung2  = 0;


und dann später

>  Spannung_mom  = adcval;

Wo kommt aber adcval her?

gruss Ralf







besser wäre sicher

>  uint16_t Spannung1  =  ReadChannel(1);

> Spannung_mom  = ReadChannel(1);

von Gast (Gast)


Lesenswert?

also du meinst dass das ganze so aussehen soll:


uint16_t Spannung_mom ;
uint16_t Spannung_max  = 0;
uint16_t Time  = 0;
uint8_t i;

...

for(i=1;i<=8;i++)
{
      Spannung_mom  = ReadChannel(1);
    if(Spannung_mom>Spannung_max)
    {
      Spannung_max = Spannung_mom;
      Time =i;
    }
}

Ich hoffe das ich das richtig umgesetzt habe wenn ja funktioniert das 
wiklich nicht!

von Ralf W. (Gast)


Lesenswert?

Ja. So sollte es aussehen.

Spannung_mom bekommt vor der if Bedingung den neuen ADC Wert.
Ist Spannung_mom grösser als der alte Maximalwert (Spannung_max)
wird anschliessend in Spannung_max der neue Wert gespeichert.

Ich denke dieser Codeteil ist jetzt so ok.

Du hast ja ein LCD angeschlossen bzw benutzt auch den UART.
Versuch doch mal Debugausgaben zu machen.
nach der Zuweisung Spannung_mom  = ReadChannel(1);
zeigst du dir folgende Werte an:
#  Spannung_mom
#  Spannung_max
und nach  der If Bedingung nochmal Spannung_max.
Zum Beispiel so:

    Spannung_mom  = ReadChannel(1);
    send_int(Spannung_mom);
    send_int(Spannung_max);
    if(Spannung_mom>Spannung_max)

    {
      Spannung_max = Spannung_mom;
      Time =i;
    }
    send_int(Spannung_max);

Dies sollte zeigen das diese Codestelle funktioniert.
Vielleicht funktionert ReadChannel nicht richtig. Darauf
würde man mit diesen Ausgaben auch schliessen können.

Oder deine Hardware ist nicht richtig angeschlossen.
Hast du schon überprüft, ob der ADC vernünftige Werte vom
Solarpanel wandelt und diese auch mal mit einem Multimeter
nachgemessen?

gruss ralf

Offtopic
Fühl dich nicht angegriffen. Ich
wollte halt nur kurz und so präzise wie möglich zeigen wo ich
Probleme sehe und wie ich sie gelöst hätte.

von Gast (Gast)


Lesenswert?

Ach quatsch fühl mich überhaubt nicht angegriffen, eher verzweifelt.

Readchannel ADU usw funktioniert einwandfrei hab das Ding so 
programmiert das ich es auch manuell steuern kann und mir auf dem 
Display die Spannung ausgegeben wird.

Es liegt definitiv an dem Teil in der for schleife!

Desweiteren lasse ich mir während des Drehvorgangs den werd der 
Variablen Spannung_max auf dem Display ausgeben und sehe das die 
Variable nur beim ersten vergleich überschrieben wird.

Danke für die Mühe.

von Ralf W. (Gast)


Lesenswert?

Zeige dir zusätzlich noch Spannung_mom an. Nur so kannst du sehen ob
der Code wirklich nicht funktioniert.
Vielleicht liefert der ADC beim ersten Durchlauf wirklich immer den
höchsten Wert. Eine Lampe in der Nähe?

Folgende Änderungen hätte ich noch gemacht.

    for(i=1;i<=8;i++){
      lcd_clear();
      set_cursor(2,2);
      lcd_string("Bitte warten....");
      Spannung_mom  = ReadChannel(1);
      if(Spannung_mom>Spannung_max){
          Spannung_max = Spannung_mom;
          Time =i;
      }
      MOTOR_Links();
      DELAY(DELAY_LS_1s);
    }

// Das Panel steht zB auf Stelle 1 und dieser Wert wird getestet.
// Erst dann die nächste Stelle anfahren. Dies für die restliche
// 7 Stellen wiederholen.
// Angenommen auf Stelle 5 ist der höchste Wert, so hat Time jetzt
// den Wert 5.

// Dies hier ( uint8_t j =(8-Time); ) ist ungünstig. Das Panel steht auf
// Stelle 8 und soll auf Stelle 5. Mit dieser Anweisung fährt es aber
// auf Stelle 3. Also weg damit.

//Damit wird:
      for(i=1;i<=Time;i++)
        {
        lcd_clear();
        set_cursor(2,2);
        lcd_string("Bitte warten....");
        MOTOR_Links();
        DELAY(DELAY_LS_1s);
    }

Ich hoffe das der Motor auch in festen Schritten fährt. Sonst wär der
Ansatz nicht gut gewählt.

gruß ralf

von Gast (Gast)


Lesenswert?

hier mit hats funktioniert!

  for(i=1;i<=8;i++){
      lcd_clear();
      set_cursor(2,2);
      lcd_string("Bitte warten....");
      Spannung_mom  = ReadChannel(1);
      if(Spannung_mom>Spannung_max){
          Spannung_max = Spannung_mom;
          Time =i;
      }
      MOTOR_Links();
      DELAY(DELAY_LS_1s);
    }


vielen vielen DANK :-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.