Forum: Mikrocontroller und Digitale Elektronik Problem mit Berechnung


von tommy (Gast)


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:
1
// Wert muss entsprechend PWM_Init() angepasst werden
2
#define PRESCALER_TIMER0  1
3
4
// PWM Frequenz berechnen, hier 36141 Hz
5
#define F_PWM    F_CPU / (PRESCALER_TIMER0 * 510)
6
7
// Delta t für Drehzahlbestimmt berechnen, hier: 0.0000277 s = 27,7 µs
8
#define DELTA_T    1 / F_PWM

in der main schleife wird dann so gerechnet:
1
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:
1
#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?

von Karl H. (kbuchegg)


Lesenswert?

tommy schrieb:

> die vorabberechnung sieht so aus:
>
1
// Wert muss entsprechend PWM_Init() angepasst werden
2
> #define PRESCALER_TIMER0  1
3
> 
4
> // PWM Frequenz berechnen, hier 36141 Hz
5
> #define F_PWM    F_CPU / (PRESCALER_TIMER0 * 510)
6
> 
7
> // Delta t für Drehzahlbestimmt berechnen, hier: 0.0000277 s = 27,7 µs
8
> #define DELTA_T    1 / F_PWM
>
> in der main schleife wird dann so gerechnet:
>
1
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:
>
1
#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#Datentypen_in_Operationen

Deine Berechnung ergibt nach Makro-Substitution das hier
1
   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

von tommy (Gast)


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:
1
drehzahl = 1 / (delta_t_counter * (float)DELTA_T);

und die defines so lasse wie sie sind?

von Karl H. (kbuchegg)


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:
>
1
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.

von tommy (Gast)


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:
1
drehzahl = F_CPU / (delta_t_counter * 510);

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

danke nochmals.

von Karl H. (kbuchegg)


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:
>
1
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.

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.