Festkomma-Arithmetik auf Mikrocontrollern

12

Oft verwenden wir Mikrocontroller, um Dinge in unseren Robotern zu erledigen, müssen aber einige Berechnungen in Dezimalzahlen durchführen. Die Verwendung von Gleitkommavariablen ist sehr langsam, da automatisch eine Software-Gleitkomma-Bibliothek enthalten ist (es sei denn, Sie haben einen High-End-Mikrocontroller). Daher verwenden wir im Allgemeinen eine Festkomma-Arithmetik.

Immer wenn ich das mache, verwende ich einfach eine ganze Zahl und erinnere mich, wo die Dezimalstelle ist. Es muss jedoch sorgfältig darauf geachtet werden, dass alles konsistent ist, insbesondere wenn Berechnungen Variablen beinhalten, bei denen sich der Dezimalpunkt an einer anderen Stelle befindet.

Ich habe eine Festpunkt-atan2-Funktion implementiert, aber da ich versucht habe, jeden letzten Tropfen mit begrenzter Genauigkeit (16 Bit) zu komprimieren, habe ich häufig die Definition des Dezimalpunkts geändert und sie hat sich geändert, als ich sie optimiert habe. Außerdem hätte ich einige Konstanten als Quasi-Nachschlagetabelle, die selbst irgendwo einen impliziten Dezimalpunkt haben.

Ich möchte wissen, ob es einen besseren Weg gibt. Gibt es eine Bibliothek oder einen Satz von Makros, die die Verwendung von Festkommavariablen vereinfachen, die Multiplikation und Division zwischen gemischten Variablen vereinfachen und die Deklaration von Dezimalzahlen oder konstanten Ausdrücken ermöglichen, aber beim Kompilieren automatisch in die gewünschte Festkommadarstellung konvertieren können? Zeit?

ronalchn
quelle
1
Ich denke, dies ist tatsächlich besser für den Stackoverflow, da die Lösung generisch ist und nicht viel mit Robotik zu tun hat.
Shahbaz
1
@ Jakob - Beachten Sie, dass beide Fragen als nicht konstruktiv geschlossen wurden.
Mark Booth
1
Dies ist die Art von Dingen, die C ++ für eingebettete Systeme sehr nützlich machen würden. Vorlagen würden automatisch den richtigen und optimalen Code generieren.
Raketenmagnet
1
Kann ich mir Ihre atan-Funktion ansehen? Ich versuche, das Problem der Umwandlung von Gleitkomma in Festkomma in meiner akademischen Forschung anzugehen, und ich würde mich freuen, es zu versuchen.
Joe Hass
1
@ronalchn Teile Arduino (AVR micro) Sprache sind in C ++ implementiert. Es gibt auch eine AVR C ++ - Bibliothek . Und dieser Thread, auf dem Compiler verwendet werden sollen.
embedded.kyle

Antworten:

7

Es wäre schön, wenn wir dem Compiler den Bereich und die Genauigkeit jeder Festkomma-Eingangsvariablen mitteilen könnten (vielleicht keine zwei mit dem Radix-Punkt an derselben Stelle), und es würde automatisch - zur Kompilierungszeit - den richtigen Bereich verwenden und Präzisions- und Neuskalierungsoperationen für die Zwischen- und Endwerte in einer Reihe von Berechnungen. Ich habe Gerüchte gehört, dass dies in der Programmiersprache Ada oder in C ++ - Vorlagen möglich sein könnte.

Leider sind Festpunkt-Arithmetikbibliotheken am nächsten, bei denen Sie als Programmierer die richtige Darstellung manuell auswählen und manuell überprüfen müssen, ob jede Operation einen angemessenen Bereich und eine angemessene Genauigkeit aufweist. Manchmal erleichtern sie die Multiplikation und Division zwischen gemischten Variablen. Sowie:

David Cary
quelle
Dies ist mit ziemlicher Sicherheit mit C ++ - Vorlagen möglich.
Raketenmagnet
Ich arbeite gerade an etwas wie Ihrem Kommentar "Es wäre schön, wenn ...". Es ist ein Plugin für gcc, das Gleitkomma-C-Code in Festkomma konvertiert und alle Binärpunktpositionen auf dem Weg optimiert. Ich habe ein Papier bei einem ACM-Journal eingereicht und ein anderes in Vorbereitung. Wenn Sie C-Code für die atan-Funktion haben, würde ich es gerne ausprobieren ... Ich könnte Ihnen C-Code zurückgeben, der ganzzahlige Variablen verwendet und alle Festkomma-Aufgaben erledigt.
Joe Hass
+1 für eine viel vollständigere Antwort als meine. Ich habe den Link in meinem so bearbeitet, dass er einen Link zu einem Ort enthält, an dem der Quellcode angefordert werden kann, um Mark Booths Kommentar zu adressieren. Möglicherweise möchten Sie auch Ihren Link aktualisieren. Ich würde es selbst tun, aber eine vorgeschlagene Bearbeitung befindet sich in der Warteschlange und blockiert mich.
embedded.kyle
1
@Rocketmagnet Es ist mit Sicherheit möglich, Fixpunkte mithilfe von Vorlagen zu implementieren, siehe FixedPoints (Haftungsausschluss: Ich habe dies geschrieben und es ist noch sehr "jung").
Pharap
gcc link "a" ist kaputt
Lesto
2

Ich habe die TI IQMath-Bibliothek verwendet , um virtuelles Gleitkomma auf ihren Festkomma-DSPs zu implementieren.

Die TMS320C28x IQmath Library von Texas Instruments ist eine Sammlung hochoptimierter und hochpräziser mathematischer Funktionen für C / C ++ - Programmierer, mit denen ein Gleitkomma-Algorithmus nahtlos in Festkomma-Code auf TMS320C28x-Geräten portiert werden kann. Diese Routinen werden normalerweise in rechenintensiven Echtzeitanwendungen verwendet, bei denen eine optimale Ausführungsgeschwindigkeit und eine hohe Genauigkeit von entscheidender Bedeutung sind. Mit diesen Routinen können Sie Ausführungsgeschwindigkeiten erreichen, die erheblich schneller sind als bei gleichwertigem Code, der in der Standardsprache ANSI C geschrieben ist. Durch die Bereitstellung gebrauchsfertiger hochpräziser Funktionen kann die TI IQmath-Bibliothek außerdem die Entwicklungszeit für DSP-Anwendungen erheblich verkürzen.

Das verwendet einige TI-spezifische Dinge, aber ich habe diesen Code auch als Basis verwendet, um virtuelle Gleitkomma-Mathematik auf anderen Mikrocontrollern zu implementieren. Das Portieren erfordert ein wenig Arbeit, ist aber viel einfacher als bei Null anzufangen.

embedded.kyle
quelle
@downvoter Möchtest du kommentieren, was mit meiner Antwort falsch war?
embedded.kyle
+1: Diese Bibliothek ist besser als das, was er jetzt verwendet ("benutze nur eine ganze Zahl"). Es macht nicht alles , was die ursprüngliche Frage verlangt hat, aber ich denke, eine Antwort wie diese (nützlich, aber keine vollständige Lösung) verdient keine Ablehnung - es sei denn, es gibt tatsächlich eine vollständige Lösung (was ich in diesem Fall bezweifle) ).
David Cary
Es scheint mir, dass eine Antwort, die spezifisch für eine einzelne Reihe von Geräten ist und nur wie bei Bier und nicht wie bei Sprache kostenlos ist, für zukünftige Besucher nur begrenzt von Nutzen ist.
Mark Booth
@ MarkBooth Ich habe den Link von der C28x-Bibliothek zur C64x-Bibliothek geändert. Wenn Sie diesem Link folgen, können Sie den Quellcode anfordern. Sie benötigen eine Unternehmens- oder Universitäts-E-Mail, um Zugriff zu erhalten. Immer noch frei wie in Bier und Sprache. Sie müssen nur Ihre Hand heben und warten, bis Sie angerufen werden, bevor Sie sprechen können. Ein bisschen nervig, aber sobald Sie den Quellcode haben, kann er an jeden Prozessor angepasst werden, den Sie mögen.
embedded.kyle
Dank @ embedded.kyle Quellcode ist definitiv besser als nur Binärcode, aber immer noch von geringem allgemeinem Nutzen, wenn die Lizenz es Ihnen nur erlaubt, ihn auf begrenzte Weise zu verwenden. Laut der Seite C6x Software Libraries wird diese Quelle nur unter der TI Commercial License veröffentlicht , die mit ziemlicher Sicherheit nicht so frei ist wie in der Sprache .
Mark Booth
1

Es gibt eine Reihe von Implementierungen (keine Bibliotheken, die mir sofort bekannt sind) der binären Skalierung (auch bekannt als B-Skalierung).

In diesem Fall behalten Sie eine mentale Notiz (oder dokumentieren noch besser den Code ...) darüber, wo sich der Dezimalpunkt befindet, und verschieben den Dezimalpunkt mithilfe von Verschiebungen nach oben oder unten.

Ich habe B-Skalierung in Assembler bei Verteidigungsprojekten verwendet, selbst bei kleinsten CPUs, damit ich für die Eignung für alles andere bürgen kann ...

Andrew
quelle
Wahrscheinlich so etwas, aber ich habe noch nie gesehen, dass es als B-Skalierung bezeichnet wird. Ich betrachte es als festen Punkt - die Dezimalstelle schwebt nie, denn obwohl sich der Dezimalpunkt im Verlauf der Berechnungen ändern kann, hat jede Variable immer den Dezimalpunkt an einer bestimmten Stelle festgelegt
ronalchn
0

Wenn Sie eine Ganzzahl verwenden, um sich zu merken, wo sich der "Punkt" befindet, verwenden sie eine Art Gleitkomma-Arithmetik. Fixpunkt, hat wirklich Fixpunkt .

atancosππ

Dies hängt vom Wertebereich ab, den Ihre Anwendung benötigt. Möglicherweise möchten Sie jedoch vollständig zu einer Festpunktdarstellung wechseln. Das heißt zum Beispiel, anstatt eine Nummer wie diese zu behalten:

struct num
{
    uint16_t number;
    uint16_t decimal_point;
};

Wo numberist die ganze Zahl und decimal_pointsagt, wo der Dezimalpunkt ist, können Sie es wie folgt speichern:

struct num
{
    uint16_t integer;
    uint16_t fraction;
};

wobei die ganze Zahl ist integer.fraction, die die gleiche Speichernutzung hat, einen höheren Wertebereich hat und im Allgemeinen einfacher zu verwenden ist.

Shahbaz
quelle
Wenn Sie den Dezimalpunkt tatsächlich speichern, ähnelt er eher einem Gleitkomma. Normalerweise wird der Dezimalpunkt zur Kompilierungszeit definiert, und Sie wechseln je nach Operation zwischen den Darstellungen.
Jakob
Ich meine nicht erinnern, wie in in einer Variablen gespeichert, ich meine erinnern, wie in erinnern, wie man das Ergebnis interpretiert (indem man weiß, wo der Dezimalpunkt ist)
ronalchn
@ronalchn, ich verstehe. Du hast so etwas wie mit a gemeint #define, oder? Ich dachte, Sie speichern es tatsächlich und es kann variieren, je nachdem, wie groß oder klein Ihre Nummer ist.
Shahbaz
@ronalchn - denkst du über B-Skalierung nach? (siehe meine Antwort)
Andrew