Hallo zusammen, ich habe mir eine Routine geschrieben, mit der ich das Summensignal eines RC-Empfängers in ein Array (uint16) lesen kann. Die Werte werden in µs erfasst und so auch in das Array geschrieben. Da die Servos so eine Genauigkeit nicht abbilden können, würde ich gerne die letzte Stelle des Messwertes (uint16) runden, also nur 0 oder 5 am Ende. Da ich mit der Arithmethik völlig auf Kriegsfuß stehe, würde ich mich über Vorschläge zur Umsetzung freuen. Vielen Dank schon einmal im voraus. Marco
:
Verschoben durch Moderator
z.B. rundet allerdings immer ab.
1 | uint16_t zahl = zahl - (zahl%5); |
1 | uint16_t zahl; |
2 | uint8_t diff = zahl%5; |
3 | |
4 | diff > 2 ? zahl = zahl - diff : zahl = zahl + (5-diff); |
Das lässt sich natürlich wesentlich schöner und lesbarer schreiben. Das sollte nur als Beispiel dienen. Getestet ist es auch nicht, kann also noch Fehler haben ;-). Grüsse, R.
Mit uint16_t kannst du Zahlen zwischen 0 und 65535 darstellen. Die letzten Stellen haben dabei die Wertigkeit 1 - 2 - 4 - 8. Da ist es ungeschickt, auf 0 oder 5 runden zu wollen. Am nächsten dran wäre die 4. Also addierst du 2 und streichst dann die letzten beiden Stellen weg (setzt sie auf 0).
sorry:
1 | diff < 3 ? zahl = zahl - diff : zahl = zahl + (5-diff); |
Addiere 0,5 und teile die Zahl dann durch 10. Divisionen und Fließkomma-Berechnungen sind für Mikrocontroller allerdings Schwerstarbeit. Viel schneller ist es, einfach die unteren drei Bit abzuschneiden: neu=alt/8 oder neu=alt>>3 (erzeugt beiden den gleichen Maschinen-Code). Das entspricht einer Division durch 8 und es wird immer abgerundet. Prüfe nach, ob diese einfachere Variante für Deine Anwendung genügt.
Hallo und Danke für die schnellen Antworten. Leider verstehe ich diesen Part nicht ganz :
1 | uint16_t zahl = zahl - (zahl%5); |
Was bedeutet das %5 ? Auf der Suche nach einer Übersichtsseite mit den ganzen Operatoren bin ich leider noch nicht fündig geworden. Viele Grüße aus dem verschneiten Norden. Marco
http://www.imb-jena.de/~gmueller/kurse/c_c++/c_operat.html http://de.wikipedia.org/wiki/Division_mit_Rest#Modulo
Marco S. schrieb: > Was bedeutet das %5 ? Auf der Suche nach einer Übersichtsseite mit den > ganzen Operatoren bin ich leider noch nicht fündig geworden Echt? Kann ich mir eigentlich nicht vorstellen. Siehe: http://de.wikibooks.org/wiki/C-Programmierung:_Ausdr%C3%BCcke_und_Operatoren
Ihr wart zu schnell ;-) Ich habe es in der Zwischenzeit gefunden (Modulus). Danke nochmal !!! Marco
Wenn abrunden reicht, genügt einfach:
1 | zahl = zahl / 5 * 5; |
Ansonsten:
1 | zahl = (2 * zahl + 5) / 10 * 5; |
Dann aber auf die Wertebereiche aufpassen. 2 * zahl + 5 darf maximal 65535 ergeben. zahl darf also maximal 32765 sein. Ansonsten zuerst auf uint32_t casten.
@ Fabian O. (xfr) Die erste sinnvolle und verständliche Antwort im Thread.
Man könnte es auch etwas perfomanter über modul machen, damit hat man auch kein Problem mit Überläufen, aber das ist eher akademisch.
1 | rest = zahl % 5; |
2 | if (rest<3) zahl -= rest; else zahl+=(5-rest); |
Hallo Marco, das % bedeutet Module. 12%5 ergibt dann 2. Grüsse, R.
Georg G. schrieb: > ist es > ungeschickt, auf 0 oder 5 runden zu wollen. Der einzige wahre Satz bisher. Denn die wirkliche Frage lautet: WARUM? Was genau versprichst du dir davon, die Werte auf- oder abzurunden? Den Servos ist das herzlich egal, dem Prozessor auch. Solange du bei 16-Bit-Werten bleibst, verbrauchst du auch nicht weniger Speicher. Du verbrauchst nur Rechenzeit für die Umrechnung. Also: Entweder reduzierst du die Auflösung um 2 oder ein vielfaches davon, dann aber richtig per Rechtsschift, oder du lässt die Werte, wie sie sind. Nur so als Hinweis: Aktuelle "hochwertige" RC-Anlagen arbeiten mit 11 bit, andere mit 10, und ein preiswertes Servo löst vielleicht mit viel Glück auf 7 bit auf... Oliver
Rene schrieb: > z.B. > > rundet allerdings immer ab. > uint16_t zahl = zahl - (zahl%5); Einfach davor 5 addieren dann rundet es auch auf
Oliver schrieb: > Georg G. schrieb: >> ist es >> ungeschickt, auf 0 oder 5 runden zu wollen. > > Der einzige wahre Satz bisher. > Denn die wirkliche Frage lautet: WARUM? Diese Frage ist genau die richtige Antwort auf die Anfrage. Klar wird ein Servo das Steuersignal nicht auf die µs genau auswerten. Wird der Wert aber vorher gerundet, kommt zum Fehler des Servos noch der Rundungsfehler hinzu. Man verschwendet also Rechenaufwand und Flash- Speicher dafür, das Gesamtsystem ungenauer zu machen.
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.