Hallo. Mir scheint, dass Variable der folgenden Formeln im Prog-Auszug nicht richtig definiert wurden. Prog. reagiert nicht auf Änderungen Poty01, Poty02 Sollte Periode und PosWelleProzent als uint64_t definiert werden? Wert von Var. PosWelle und NegWelle müssen nach Berechnung Ganzzahlig zw. 1-1000 liegen. _______________________________________________ main... // Nachfolgendes funktioniert nicht uint16_t Poty01; // aus ADC ausgelesen, 0-1023 uint16_t Poty01_alt = 0; // 0-1023 uint16_t Poty02; // aus ADC ausgelesen, 0-1023 uint16_t Poty02_alt = 0; // 0-1023 uint16_t Periode; uint16_t PosWelleProzent; uint16_t PosWelle; uint16_t NegWelle; uint8_t Veraenderung = 0; ... //werden unter Präprozessor-Makro definiert FREQ_BEREICH=999; FREQ_LOW=1; PWM_BEREICH=90; PWM_LOW=5; ... Veraenderung=1; switch(Veraenderung) { case 1: Periode = FREQ_BEREICH/1024*Poty01+FREQ_LOW; //nach case=1 direkt case=2 abarbeiten case 2: PosWelleProzent = PWM_BEREICH/1024*Poty02+PWM_LOW; PosWelle = Periode/100*PosWelleProzent; NegWelle = Periode-PosWelle; break; } ...
Hallo, Periode = FREQ_BEREICH/1024*Poty01+FREQ_LOW; was kommt da raus? C rechnet in Integer wenn nicht zwingend anders angegeben. 999/1024 = 0 0*Poty01 = 0 ü+FREQ_LOW = 1 kommt also immer 1 raus, bei der 2. Formel eben 5. FREQ_BEREICH*Poty01/1024+FREQ_LOW könnte da eher gehen. Da passt die Rechnung aber dann nicht in 16 Bit, also mindestens einen der Werte der Formael auf 32 Bit casten. Gruß aus Berlin Michael
:
Bearbeitet durch User
Michael U. schrieb: > 999/1024 = 0 Klar, rutscht unter 0 Dürfte bei uint64_t egal sein - oder? Michael U. schrieb: > FREQ_BEREICH*Poty01/1024+FREQ_LOW könnte da eher gehen. Gleiche Formel, aber auch Dezimalstellen. PS: Wie ist das bei uint16_t, wird erste Dezimalstelle auf/abgerundet. Ganzzahlig bleibt unberührt erhalten? Bsp: uint16_t PosWelle=9,71234; Steht in PosWelle jetzt 9, oder 10 ?
__Son´s B. schrieb: > Steht in PosWelle jetzt 9, oder 10 ? 9. Es wird einfach nur der Nachkommaanteil abgeschnitten.
__Son´s B. schrieb: > int16_t PosWelle=9,71234; > Steht in PosWelle jetzt 9, oder 10 ? es wird immer abgerundet
Hallo, __Son´s B. schrieb: > Klar, rutscht unter 0 > Dürfte bei uint64_t egal sein - oder? auch ein 64Bit unsigned Integer ist ein Ganzzahlwert und es kommt 0 raus. Gruß aus Berlin Michael
__Son´s B. schrieb: > uint16_t PosWelle=9,71234; > Steht in PosWelle jetzt 9, oder 10 ? weder noch. Das gibt einen Fehler beim Compilieren.
__Son´s B. schrieb: > uint16_t PosWelle=9,71234; > Steht in PosWelle jetzt 9, oder 10 ? Wenn du um 9,71234 noch eine runde Klammer machst kommt 71234 raus.
Daniel A. schrieb: > Wenn du um 9,71234 noch eine runde Klammer machst kommt 71234 raus. Es waere 5698 ;)
Kirsch schrieb: > __Son´s B. schrieb: >> int16_t PosWelle=9,71234; (ich nehme mal an, dass eigentlich 9.71234 gemeint war) >> Steht in PosWelle jetzt 9, oder 10 ? > > es wird immer abgerundet Nein, es wird der Nachkommateil abgeschnitten. Das heißt, dass im Falle eines negativen Wertes aufgerudet wird.
Michael U. schrieb: > __Son´s B. schrieb: >> Klar, rutscht unter 0 >> Dürfte bei uint64_t egal sein - oder? > > auch ein 64Bit unsigned Integer ist ein Ganzzahlwert und es kommt 0 > raus. Stimmt - habe unter C99-Standard keine Fließkomma-Definition gefunden. Gibts das überhaupt? _________________________________ Kaj G. schrieb: >> Steht in PosWelle jetzt 9, oder 10 ? > 9. Es wird einfach nur der Nachkommaanteil abgeschnitten. Kirsch schrieb: >> int16_t PosWelle=9,71234; >> Steht in PosWelle jetzt 9, oder 10 ? > > es wird immer abgerundet Rolf M. schrieb: >>> Steht in PosWelle jetzt 9, oder 10 ? >> >> es wird immer abgerundet > > Nein, es wird der Nachkommateil abgeschnitten. Das heißt, dass im Falle > eines negativen Wertes aufgerudet wird. Ok, damit kann man kalkulieren. ___________________________________ Markus F. schrieb: >> uint16_t PosWelle=9,71234; >> Steht in PosWelle jetzt 9, oder 10 ? > > weder noch. Das gibt einen Fehler beim Compilieren. Mein Compiler (Atmel Studio 7.0) wirft keine Fehler raus. ___________________________________ Daniel A. schrieb: >> uint16_t PosWelle=9,71234; >> Steht in PosWelle jetzt 9, oder 10 ? > > Wenn du um 9,71234 noch eine runde Klammer machst kommt 71234 raus. Kaj G. schrieb: >> Wenn du um 9,71234 noch eine runde Klammer machst kommt 71234 raus. > Es waere 5698 ;) Was stimmt denn nun? Welche Logik steckt dahinter.
:
Bearbeitet durch User
__Son´s B. schrieb: > Stimmt - habe unter C99-Standard keine Fließkomma-Definition gefunden. > Gibts das überhaupt? Aua. Die Datentypen double und float gibt es schon erheblich länger als C99.
>> uint16_t PosWelle=9,71234; __Son´s B. schrieb: >>> Wenn du um 9,71234 noch eine runde Klammer machst kommt 71234 raus. >> Es waere 5698 ;) > > Was stimmt denn nun? > Welche Logik steckt dahinter. Ohne Klammer würde eine weitere variable vom Typ uint16_t angelegt werden wollen. Da würde aber der Name fehlen -> Error. Mit Klammer ist es ein ganz normales Komma als Operator. Das Ergebnis des Ausdrucks ist dann das, was rechts vom Komma steht, also 71234.
DANKE! Noch eine wichtige Frage zu Berechnungen; ------------------------- uint16_t Poty01; // Wert aus ADC kann zw.0-1023 liegen if (Poty01<1) Poty01=1; // Berechnungssicherheit uint16_t periode=999/1024*Poty01+5; // oder // uint16_t periode=999*Poty01/1024+5; ------------------------- Frage 1: Unterscheidet der Compiler zwischen beiden Varianten? Frage 2: Werden INNERHALB der Berechnungen, Dezimalstellen ordentlich mit Nachkomma berechnet und erst dem Ergebnis die Dezimalstellen abgeschnitten?
__Son´s B. schrieb: > Werden INNERHALB der Berechnungen, Dezimalstellen ordentlich mit > Nachkomma berechnet Nein, wenn Du nur Ganzzahlen angibst, wird auch nur mit Ganzzahlen gerechnet. Lies ein C-Buch. Das haben wir Dir in den vergangenen Jahren wohl schon das eine oder andere Mal nahegelegt, wenn ich mich recht erinnere.
Darth Moan schrieb: > was rechts vom Komma steht, also 71234. Das ist aber mehr als in einem uint16_t passt, also wird Modulo 65536 genommen und dann kommt 5698 raus.
Der Compiler wertet den Ausdruck im mathematischem Sinn aus. Also Klammer- vor Punkt- vor Strichrechnung. Und der Datentyp ist der, der für die Berechnung des aktuellen Teilausdrucks ausreichend ist. Fall 1: uint16_t periode=999/1024*Poty01+5; 999/1024 ist eine Integerdivision. Keine implizite Umwandlung in float. Da kommt 0 raus *Poty01 Integermultiplikation, da das vorhergehende Ergebniss auch Integer war und das Ergebnis negativ sein könnte (egal dass da nur positive Werte sind) + 5 Addition (geschenkt) Fall 2 uint16_t periode=999*Poty01/1024+5; 999*Poty01 Ob das Probleme macht, hängt davon ab, wir groß ein int bei dir ist. Bei 16-Bit gibt es Probleme (überlauf), bei 32-Bit nicht. Da du jetzt eine große Zahl hast, gibt es beim /1024 kein Problem mehr. Da es bei diesen Fällen zu unterschiedliche Ergebnisse kommt (was durchaus gewünscht sein kann), muss der Compiler die Fälle unterscheiden. Wenn du im zweiten Fall 999L statt 999 schreibst, sollte das Problem behoben sein.
Dirk B. schrieb: > 999/1024 ist eine Integerdivision. Keine implizite Umwandlung in float. > Da kommt 0 raus Wogegen 999.0/1024 eine Fließkommaberechnung wäre.
Rufus Τ. F. schrieb: > __Son´s B. schrieb: >> Werden INNERHALB der Berechnungen, Dezimalstellen ordentlich mit >> Nachkomma berechnet > > Nein, wenn Du nur Ganzzahlen angibst, wird auch nur mit Ganzzahlen > gerechnet. > > Lies ein C-Buch. > > Das haben wir Dir in den vergangenen Jahren wohl schon das eine oder > andere Mal nahegelegt, wenn ich mich recht erinnere. Tja, offensichtlich habe ich eher oberflächliche C-Fachbücher. Dort wird nur so dividiert, dass Ganzzahlen raus kommen - Einsteiger-Niveau. Grundsätzlich finde ich den Verweis auf Datenblätter und Literatur sinnvoll, NACH einer ordentlichen, dem Einsteiger angepassten Beschreibung - zur Wissensvertiefung! Gott sei dank, gibt es hier im Forum aber auch Menschen mit kostruktiven Anregungen. Denen, meinen tiefen Dank!
Brummbär schrieb: > Dirk B. schrieb: >> 999/1024 ist eine Integerdivision. Keine implizite Umwandlung in float. >> Da kommt 0 raus > > Wogegen 999.0/1024 eine Fließkommaberechnung wäre. "999" ist in meinem Fall eine uint16_t Variable, die ganz woanders her kommt - höllische Falle...
Brummbär schrieb: > Dirk B. schrieb: >> 999/1024 ist eine Integerdivision. Keine implizite Umwandlung in float. >> Da kommt 0 raus > > Wogegen 999.0/1024 eine Fließkommaberechnung wäre. Das wird aber auch nicht genauer als die Umstellung zum Fall 2. Es wird aber meist langsamer als Fall 2 sein.
__Son´s B. schrieb: > "999" ist in meinem Fall eine uint16_t Variable, die ganz woanders her > kommt - höllische Falle... Aha: __Son´s B. schrieb: > //werden unter Präprozessor-Makro definiert > FREQ_BEREICH=999;
__Son´s B. schrieb: > Tja, offensichtlich habe ich eher oberflächliche C-Fachbücher. Dort wird > nur so dividiert, dass Ganzzahlen raus kommen - Einsteiger-Niveau. > Grundsätzlich finde ich den Verweis auf Datenblätter und Literatur > sinnvoll, NACH einer ordentlichen, dem Einsteiger angepassten > Beschreibung - zur Wissensvertiefung! Nö, die Ausrede lasse ich nicht gelten.
Rufus Τ. F. schrieb: > Nö, die Ausrede lasse ich nicht gelten. Deine auch nicht -> Berufsblindheit! Tatsächlich bin ich ein C-Anfänger und werde es auch mit 1-3/uC-Prog/Jahr bleiben.
So, 3 Formeln sind umgestellt, 4 Var. von uint16_t auf float umgestellt
>>> Prog läuft fehlerlos!
Danke noch einmal!!!
__Son´s B. schrieb: > So, 3 Formeln sind umgestellt, 4 Var. von uint16_t auf float umgestellt Das ist gar nicht nötig. Du willst das Problem nicht verstehen.
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.