mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik value truncated..


Autor: Kartoffel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi zusammen,

also ich hab zwei kleine Problemchen im Programm, die ich noch beheben 
muss.
Auf die Lösung komm ich irgendwie nicht, vielleicht weiß einer ja Rat.
unsigned int Drehz_setzen(unsigned int Soll_dr)
{
unsigned int a = 0;  
a = (Soll_dr/15)*2;
Hexwert = MIN + a;  // MIN+Soll_dr*7,5

  if (Hexwert > MAX) // Begrenzung auf den max. Registerwert
    {
      Hexwert = MAX;
    }

return Hexwert;
}


MIN = 65135, MAX = 65535
Nach dem Kompillieren von diesem Code, bekomme ich eine Warnung : Value 
truncated. Ich bin aber der Meinung, dass alles passt, ich überschreite 
den Wertebereich doch gar nicht, die Soll_dr kann maximal 3000 sein.

Die zweite Sache: ich bestimme die Drehzahl aus Encoderimpulsen. Der 
Code dafür:
unsigned long int Drehzahl(void)
{
unsigned long int Drehz =0;

  
  if (CC1_CC9 < CC9alt)
    {
    Counter_dif = 0-(CC1_CC9-CC9alt);
    }
  else
    {
  Counter_dif = CC1_CC9-CC9alt;
    }
  CC9alt = CC1_CC9;
  Drehz = 1200000L/(int)Counter_dif; // Drehzahl in Umdrehungen pro Minute
  

   return Drehz; 
}

Die ermittelte Drehzahl stimmt fast immer (ist mit einem Drehzahlmesser 
überprüft), allerdings bekomme ich manchmal noch so komische Drehzahlen 
von 4294967175....ich geh davon aus, dass die Berechnung in manchen 
Fällen ne negative Zahl ergibt. Dachte aber, dass ich diesen Fall mit 
der if-Verzweigung abgefangen habe.

Autor: Bernhard M. (boregard)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
unsigned int Drehz_setzen(unsigned int Soll_dr)
{
unsigned int a = 0;  
a = (Soll_dr/15)*2;
Hexwert = MIN + a;  // MIN+Soll_dr*7,5

  if (Hexwert > MAX) // Begrenzung auf den max. Registerwert
    {
      Hexwert = MAX;
    }

return Hexwert;
}
ist ja wohl unvollständig, da "Hexwert" nirgendwo definiert wird. Das 
ist doch hoffentlich eine lokale Variable!
Ausserden kann es, falls es auch unsigned int ist, nie größer als MAX 
werden (da max ja die größte als unsigned int darstellbare Zahl 
ist)...d.h. die if-Abfrage ist überflüssig - Compiler merken sowas. Du 
solltest wohl eher abfragen:
if (a > (MAX - MIN))
...

Im nächsten Beispiel:
  if (CC1_CC9 < CC9alt)
    {
    Counter_dif = 0-(CC1_CC9-CC9alt);
    }
ist vermutlich falsch, denn ich denke, das Du hiermit den wrap-around 
des Zählers abfangen willst...

Autor: Unbekannter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich bin aber der Meinung, dass alles passt, ich überschreite
> den Wertebereich doch gar nicht, die Soll_dr kann maximal 3000 sein.

Ja nach Compiler bzw. Architektur kann "unsigned int" nur 16 Bit breit 
sein.

Du kannst aber auch einfach den Roh-Wert vergleichen:
  if ( Soll_dr > 3000 )
    return MAX;
  else
    return MIN + (Soll_dr/15)*2;

Wie immer gilt: Konstanten wie 3000, 15 und 2 sind schlechter Stil beim 
Programmieren.

Daher wäre etwa folgendes besser:
#define MIN                 65135
#define MAX                 65535
#define SOLL_DR_DIV         15
#define SOLL_DR_MUL         2
#define SOLL_DR_TO_HEX(x)   ( MAX + ((x)/SOLL_DR_DIV) * SOLL_DR_MUL )
#define SOLL_DR_MAX         ( ((MAX-MIN) * SOLL_DR_DIV) / SOLL_DR_MUL ) 

[...]

  if ( Soll_dr > SOLL_DR_MAX )
    return MAX;
  else
    return SOLL_DR_TO_HEX( Soll_dr );


Autor: Unbekannter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#define SOLL_DR_TO_HEX(x)   ( MAX + ((x)/SOLL_DR_DIV) * SOLL_DR_MUL )

Soll natürlich heissen:
#define SOLL_DR_TO_HEX(x)   ( MIN + ((x)/SOLL_DR_DIV) * SOLL_DR_MUL )

Autor: Kartoffel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Bernhard: also der Hexwert ist auch unsigned int und lokal deklariert.
if (CC1_CC9 < CC9alt)
    {
    Counter_dif = 0-(CC1_CC9-CC9alt);
    }


ja, damit möchte ich abfangen, dass ich beim Zählerüberlauf negative 
Geschwindigkeiten bekomme. Denn die Geschw.berechnung beinhaltet ja 
Counter_dif. Wieso ist das falsch? Liegt hier der Fehler?

Autor: Bernhard M. (boregard)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei einem Überlauf ist ja CC9alt größer als CC1_CC9.
Die wahre Differenz zwischen beiden ist dann doch zum einen die 
Differenz von  CC9alt bis zum max. möglichen Wert plus CC1_CC9 (das ja 
die Differenz von 0 bis CC1_CC9 entspricht.

Bildlich dargestellt:
  0++++++--------------------------------------+++MAX
                                              ^CC9alt
        ^CC1_CC9
Du willst die "länge" des ++ Bereiches, berechnest aber die länge des -- 
Bereiches...

Also:
Counter_dif = CC1_CC9 + (MAX - CC9alt);
wobei MAX die Konstante für den Wert, bei dem es dem Wrap-around gibt, 
sein muß (geht aus Deinem Beispiel nicht hervor).

Autor: Kartoffel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja klar!!!!
Hab alles schon behoben, danke schön.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.