Keine Vergleiche mit long möglich???

OP #497288
Lesenswert?
• ▲
▼
Hallo Leute,
ich programmiere meinen Atmega32 mit WINAVR.
Leider habe ich ein problem mit den Datentypen. Meine Stellgröße y einer 
Regelung muß ich als long int definieren, um eine hohe Verstärkung 
nutzen zu können. Leider klappen damit keinerlei logische Vergleiche.

if(y < 0)
{
  direction = 0;
  y = -y;
}

klappt nicht. Auch wenn y wirklich < 0 ist, wird die Bedingung nie 
erfüllt.

if((int) y < 0)
{
  direction = 0;
  y = -y;
}

Obiges funktioniert hingegen. Da kriege ich dann aber Probleme, wenn y 
schon zu groß wird. Dann gibt es einen Überlauf und der gecastete Wert 
wird negativ.

Auch so etwas klappt nicht:

  if(y > 3000)
  {
    y = 3000;
  }

auch nicht so:

  if(y > 3000L)
  {
    y = 3000L;
  }

Weiß jemand, wie man vernünftige long vergleiche erstellt oder 
wenigstens richtig casten kann?
Gruß,
Daniel
Gast #497296
Lesenswert?
• ▲
▼
Poste mal ein wenig mehr aus dem Code. Sollten sich mehrere if(y...) 
Abfragen untereinander befinden versuchs mal mit switch(y). Vom Gefühl 
liegts daran das zwei Abfragen zutreffen und y zweimal das Vorzeichen 
wechselt.
OP #497309
Lesenswert?
• ▲
▼
OK. Das Vorzeichenproblem habe ich gelöst, in dem ich das Vorzeichen des 
Fehlers checke. Der ist vom typ int und da passiert garantiert auch kein 
Überlauf.

Hier mal meine Funktion:

static int e;
static long int y;

void p_control(int x, int w)
{
  e = w - x;
  y = kp * e;

  int direction = 1;

  if(e < 0)
  {
    direction = 0;
    y = -y;
  }

  lcd_clearln();
        lcd_puti(y);
  lcd_puts(" ");
  int y_max = ICR1;

  //avoid values higher than TOP
  if(y > y_max)
  {
    y = y_max;
  }

        lcd_puti(y);
  lcd_puts(" ");
        lcd_puti(direction);
  lcd_newln();
  set_pwm(y, direction);
}

Das Problem liegt eindeutig in der zweiten if Anweisung. So funktioniert 
es nämlich:

        //avoid values higher than TOP
  if((int) y > y_max)
  {
    y = y_max;
  }
OP #497377
Lesenswert?
• ▲
▼
OK. Damit funktioniert der Vergleich schon mal. Hatte diese long int 
Bezeichnung mal in einem Tutorial gesehen und dachte, daß man das unter 
c so macht.

Jetzt habe ich aber immer noch das Problem, daß der Speicherbereich von 
y zu klein ist:

  if(y > y_max)
  {
    y = y_max;
  }

wird y größer als 2^16, gibt es einen Überlauf. Auch wenn ich die 
Variable explizit als int32_t y; definiere.
Gast #497383
Lesenswert?
• ▲
▼
@Daniel Meyer

>wird y größer als 2^16, gibt es einen Überlauf. Auch wenn ich die

Woran erkennst du das?

>Variable explizit als int32_t y; definiere.

long bzw. int32_t sind 32 Bit mit Vorzeichen und können damit +/- 2*10e9 
irgendwas darstellen.

MFG
Falk
#497390
Lesenswert?
• ▲
▼
> aber long int scheint mir komisch

Ist aber völlig richtig. Der Datentyp heist
wirklich "long int". Durch die unsägliche "implizit int"
Regel ist es allerdings möglich, dies zu einfach nur
"long" abzukürzen.

Selbiges mit "unsigned int".
Anstatt
  unsigned int i;
kannst du genausogut
  unsigned i;
schreiben.

Der Compiler denkt sich das "int" dazu, wenn er nichts
anderes hat.

OP #497395
Lesenswert?
• ▲
▼
OK. Dummer Fehler:

y = kp * e;

wobei kp und e beide int variablen sind. Gibt natürlich einen Überlauf 
bevor das Ergebnis in die long variable y geschrieben wird.

Sehen tu ich das, indem ich y ausgebe, daß später wieder < y_max wird, 
obwohl der wert eigentlich höher sein müte.

Vielen Dank
#497399
Lesenswert?
• ▲
▼
Daniel Meyer wrote:
> OK. Dummer Fehler:
>
> y = kp * e;
>
> wobei kp und e beide int variablen sind. Gibt natürlich einen Überlauf
> bevor das Ergebnis in die long variable y geschrieben wird.

Eben.
Und nach einem Überlauf kannst du dich auf gar nichts
mehr verlassen. Weder auf das Vorzeichen noch auf sonst
irgendwas.

Moral von der Story:
Wenn du in deinem Programm seltsames Verhalten hast, dann
hast du in 99% aller Fälle irgendwo Mist gebaut. Es ist
ganz selten, dass in einem derart gut getesteten Compiler
wie dem gcc derart triviale Fehler auftauchen.
#497401
Lesenswert?
• ▲
▼
Daniel Meyer wrote:
> @ Karl Heinz B.:
> Wenn ich long int nehme, wird kein Vergleich ausgeführt.

Dein Problem war schon lange vor dem Vergleich!!!!
Die Berechnung hat einen Overflow produziert.
Ob das Ergebnis dann positiv oder negativ ist, in
welchem Zahlenbereich es liegt, hängt von den konkreten
Zahlen ab, die zum Overflow geführt haben.


Was du siehst, sind die Symptome. Es hilft aber nichts
an den Symptomen herumzudoktorn. Du musst die Ursachen
bekämpfen. Und die Ursache ist der Overflow!

Wenn du Symptome bekämpfen willst, musst du Arzt werden.
#497410
Lesenswert?
• ▲
▼
long double
double
float
unsigned long int    (synonymous with unsigned long)
long int             (synonymous with long)
unsigned int         (synonymous with unsigned)
int
unsigned short int   (synonymous with unsignd short)
short int            (synonymous with short)
unsigned Char
short
Char


Dies ist die Reihung. Der jeweils niedrigere Datentyp
wird auf den höheren angeglichen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren