Hallo
ich möchte in meinem Tiny13 mit der in Excel ermittelte Formel
y = 0.004347x2 + 0.174571x - 155.697431
eine Temperatur (y) berechnen.
Die Formel hab ich genähert durch:
y = (68x/1024)^2 + 89x/512 -156
und entsprechend umgesetzt:
volatile int32_t temperatur;
temperatur = (((68*ADC) >> 10)^2)
+ ((89*ADC) >> 9)
- 156;
Die ADC-Werte überschreiten den Wert von 350 nie, einen Überlauf sollte
also weder beim 1. noch beim 2. Term geben. Doch leider stimmt das
Ergebnis hinten und vorne nicht.
Auch wenn ich im Code die Variable "ADC" durch einen fixen Wert
ersetzte, weicht die Ausgabe stark vom erwarteten Ergebnis ab. Hier
einige Beispiele
Faktor an Stelle von "ADC" Ergebnis erw. Ergebnis
0 -154 -156
16 -151 -153 (= 1^2 + 2 - 156)
128 -124 -70 (= 8^2 + 22 - 156)
256 -93 177 (= 17^2 + 44 - 156)
350 -75 433 (= 23^2 + 60 - 156)
Woran liegt der Fehler???
Besten dank für eure Hilfe
Weil du in C nicht einfach so ^2 schreiben kannst, dafür gibt es die Funktion pow() http://www.elook.org/programming/c/pow.html MfG
oooops, schande über mich, jetzt funktionierts auch ;) vielen dank!
Pow schrieb: > dafür gibt es die Funktion pow() Nee, die nutzt hier nun grade absolut überhaupt nichts.
Bei einer Bitfummelei etwas zu ver-XOR-n sieht zwar witzig aus, aber so tät ich des nicht machen. Schreib dir eben eine pow(); - Funktion. Oder eine Makrofunktion. Inline könnte es eine while-Schleife mit ordentlichem Funktionsrumpf richten. mfg mf
Wofür pow()? Hier reicht doch einfach x*x zu schreiben. Wenn man den Exponenten nicht dynamisch bestimmt, sollte sowas meistens schneller sein und weniger Code benötigen, wenn ich mich nicht irre.
wenn ich nun den ersten term mit ((68*ADC) >> 10) * ((68*ADC) >> 10) berechne (die funktion pow() kann ich nicht einsetzten, hat keinen platz hat in meinem 1k flash), scheint das resultat korrekt zu sein. rechne ich jedoch (68*68*ADC*ADC) >> 20) (oder 4624 anstelle von 68*68) erhalte ich nicht das gewünschte. mein ADC wert hat zwar eine breite von 11 Bit, wie aber oben erwänt wird der ADC-wert aber nie grösser als 380 und braucht somit auch höchstens 9 bits. damit tritt bei der berechnung keinen überlauf auf und kann immer in einer 32-bit variable (eigentlich ja nur 31 bits für den wert, 1 bit fürs vorzeichen) gespeichert werden. woran liegt das?
1 | 380 * 380 * 4624 -> 667705600 |
und das ist weit über dem mit 16 Bit machbaren Maximum schon alleine, dass du das Ergebnis (das maximal 16 Bit haben kann) um 20 Bit nach rechts schieben willst, hätte dich stutzig machen müssen.
aber ich hab ja ein int32_t, also 32 bits (31 für den wert und 1 vorzeichenbit)?!?!
> die funktion pow() kann ich nicht einsetzten
Die Funktion pow willst du auch nicht für so etwas triviales wie ein
Quadrat einsetzen.
Markus schrieb: > aber ich hab ja ein int32_t, also 32 bits (31 für den wert und 1 > vorzeichenbit)?!?! Wo hast du einen int32_t?
Und von welchem Typ ist ADC? Die Zahlen 68, 1024 sind erst mal int.
Du meinst den hier? volatile int32_t temperatur; der ist uninteressant. Der besagt nur, dass das Ergebnis deiner Berechung auf 32 Bit aufgeblasen wird, nachdem der Ausdruck ausgewertet wurde. Aber solange ADC kein 32 Bit Wert ist, ist das eine stink normale 16 Bit Berechnung. http://www.mikrocontroller.net/articles/FAQ#Datentypen_in_Operationen
Und wenn du schon mit int32 rechnest solltest du das >>20 zum Schluss machen: y = 0.004347x2 + 0.174571x - 155.697431 = (4558,159872x2 + 183050,960896x - 163260589,408256 )/ 1024/1024 = ((4558 * x + 183051)*x - 163260589)>>20
ok vielen dank, jetzt klappts so wie ichs mir vorgestellt hab. thx;)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.