mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Problem mit Berechnung


Autor: tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo,

ich habe ein problem mit einer berechnung bei meinem atmega88. es geht 
um eine berechnung einer drehzahl eines motors.

die vorabberechnung sieht so aus:
// Wert muss entsprechend PWM_Init() angepasst werden
#define PRESCALER_TIMER0  1

// PWM Frequenz berechnen, hier 36141 Hz
#define F_PWM    F_CPU / (PRESCALER_TIMER0 * 510)

// Delta t für Drehzahlbestimmt berechnen, hier: 0.0000277 s = 27,7 µs
#define DELTA_T    1 / F_PWM

in der main schleife wird dann so gerechnet:
drehzahl = 1 / (delta_t_counter * DELTA_T);

das problem ist nun dass ich keinen gescheiten wert für drehzahl 
erhalte. den artikel mit der Festkommaarithmetik kenne ich und habs 
damit auch versucht, nur funktionierte es irgendwie nicht.

wenn ich DELTA_T mit dem zu berechnenden wert direkt deklariere:
#define DELTA_T    0.0000277

dann funktioniert die berechnung. allerdings macht der compiler dann, so 
glaub ich, ein float daraus und damit bekomme ich dann einen fast vollen 
programmspeicher von 93% und einen datenspeicher von 62%. vorher 50% 
programm- und 34% datenspeicher.

ich würde das gerne irgendwie umgehen, denn eine auslastung von 93% is 
mir zuviel :-(

habt ihr da einen vorschlag?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
tommy schrieb:

> die vorabberechnung sieht so aus:
>
// Wert muss entsprechend PWM_Init() angepasst werden
> #define PRESCALER_TIMER0  1
> 
> // PWM Frequenz berechnen, hier 36141 Hz
> #define F_PWM    F_CPU / (PRESCALER_TIMER0 * 510)
> 
> // Delta t für Drehzahlbestimmt berechnen, hier: 0.0000277 s = 27,7 µs
> #define DELTA_T    1 / F_PWM
>
> in der main schleife wird dann so gerechnet:
>
drehzahl = 1 / (delta_t_counter * DELTA_T);
>
> das problem ist nun dass ich keinen gescheiten wert für drehzahl
> erhalte.

setze mal deine Makros ein und dann untersuchst du, wo du bei Integer 
Berechnung etwas verlierst.

> wenn ich DELTA_T mit dem zu berechnenden wert direkt deklariere:
>
#define DELTA_T    0.0000277

logisch.
Damit zwingst du dem Compiler eine Gleitkommaberechnung auf. In deiner 
originalen Version hast du die aber nicht. Das wird alles Integer 
berechnet.

http://www.mikrocontroller.net/articles/FAQ#Datent...

Deine Berechnung ergibt nach Makro-Substitution das hier
   drehzahl = 1 / (delta_t_counter * 1 / F_CPU / (1 * 510) ); 

Wenn du das jetzt auswertest, ergibt höchst wahrscheinlich 
delta_t_counter / F_CPU praktisch immer 0

Autor: tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke für die antwort.

du hast recht. F_PWM geht noch, aber DELTA_T schon nichtmehr.

ich hatte irgendwie gehofft das der atmega intern mit der komma 
variablen rechnet und so nicht wirklich mehr speicher benötigt. lag wohl 
falsch :-)

welche möglichkeit hätte ich denn meine originale version zum laufen zu 
bringen?

reicht es wenn ich einen type cast mache, so in etwa:
drehzahl = 1 / (delta_t_counter * (float)DELTA_T);

und die defines so lasse wie sie sind?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
tommy schrieb:
> danke für die antwort.
>
> du hast recht. F_PWM geht noch, aber DELTA_T schon nichtmehr.
>
> ich hatte irgendwie gehofft das der atmega intern mit der komma
> variablen rechnet und so nicht wirklich mehr speicher benötigt. lag wohl
> falsch :-)
>
> welche möglichkeit hätte ich denn meine originale version zum laufen zu
> bringen?

Die Berechnung umstellen

>
> reicht es wenn ich einen type cast mache, so in etwa:
>
drehzahl = 1 / (delta_t_counter * (float)DELTA_T);


Wieder:
Mach das, was der Präprozessor auch macht:
Setze die Texte ineinander ein und sieh nach was rauskommt.

Aber: Mach nur die Textersetzung! Ohne irgendwelche sonstigen Dinge. 
Insbesondere: Klammere keine Ausdrücke, es sei denn durch die 
Textersetzung würden sich welche ergeben.

Wenn du alle Ersetzungen durchgeführt hast, hast du die Berechnung, so 
wie sie dem Compiler vorgeworfen wird. Und dann kannst du dir ansehen, 
in welcher Reihenfolge welche Operationen mit welchen Datentypen 
gerechnet werden.

Autor: tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich wollte das eigentlich wegen der übersichtlichkeit vermeiden, aber 
wenn ich alles einsetze und entsprechend umstelle funktioniert die 
berechnung.

lösung sieht jetzt so aus:
drehzahl = F_CPU / (delta_t_counter * 510);

muss ich wohl die kommentar etwas ausführlicher gestalten, aber passt 
schon.

danke nochmals.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
tommy schrieb:
> ich wollte das eigentlich wegen der übersichtlichkeit vermeiden, aber
> wenn ich alles einsetze und entsprechend umstelle funktioniert die
> berechnung.
>
> lösung sieht jetzt so aus:
>
drehzahl = F_CPU / (delta_t_counter * 510);
>
> muss ich wohl die kommentar etwas ausführlicher gestalten, aber passt
> schon.

Oder aber du gehst von diesem Ergebnis aus und überlegst dir, wie du es 
in Makros aufbrechen kannst, so dass
* anhand der Makros nachvollziehbar ist, was passiert und warum
* genau dieses Ergebnis rauskommt.


Du hast hoffentlich jetzt etwas gelernt:
Bei Makros muss man von hinten anfangen. Zuerst muss klar sein, was am 
Ende rauskommen muss. Und erst dann fängt man an, dieses gewünschte 
Ergebnis in Einzelteile zu zerpflücken und die Einzelteile in Makros zu 
verfrachten, bzw. Abhängigkeiten von äußeren Parametern einzubauen.
Die Umkehrung geht nämlich, vor allem bei Berechnungen, meistens schief. 
Bei Makros steht im Vordergrund immer der Text, der nach der 
vollständigen Substitution der einzelnen Texte rauskommt.

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.