Floating Point vs. Fixed Point Arithmetik auf kleinen PICs

Floating Point vs. Fixed Point Arithmetik auf kleinen PICs ist eine der wichtigsten Grundsatzentscheidungen, wenn Sie mit 8-Bit-Mikrocontrollern wie PIC16 oder PIC18 arbeiten. Viele Projekte starten mit einfachen Sensorwerten, Grenzwerten und ein paar Mittelwerten – und plötzlich werden Umrechnungen, Kalibrierungen, Filter oder Regelalgorithmen nötig. Spätestens dann stellt sich die Frage: Rechne ich bequem mit Gleitkomma (float) oder setze ich konsequent auf Festkomma (fixed point)? Auf „großen“ Controllern mit FPU ist das oft eine Komfortentscheidung. Auf kleinen PICs ohne Hardware-FPU ist es hingegen eine Frage von Laufzeit, Codegröße, Energieverbrauch und Debugbarkeit. Gleitkomma ist leicht zu lesen und vermeidet viele Skalierungsfehler – kostet aber typischerweise deutlich mehr Flash und Taktzyklen. Fixed Point wirkt am Anfang sperriger, kann aber extrem schnell und deterministisch sein, wenn Sie ein sauberes Zahlenformat (z. B. Q-Format) definieren. In diesem Artikel lernen Sie, wann Floating Point sinnvoll ist, wann Fixed Point klar überlegen ist, welche typischen Fehlerquellen es gibt und wie Sie in C (XC8/XC16) praxistaugliche Festkomma-Strategien aufbauen, ohne dass Ihr Code unübersichtlich wird.

Was ist Floating Point – und warum ist es auf 8-Bit-PICs „teuer“?

Floating Point (Gleitkomma) stellt Zahlen als Mantisse und Exponent dar (typischerweise IEEE 754 bei float), wodurch ein großer Wertebereich mit variabler Auflösung möglich ist. Das ist ideal für Berechnungen, bei denen Größenordnungen stark schwanken oder Sie viele Divisionen/Wurzeln/Trigonometrie benötigen. Auf kleinen PICs fehlt jedoch in der Regel eine Hardware-FPU. Das bedeutet: Jede Gleitkommaoperation wird durch Software-Routinen umgesetzt. Diese Routinen benötigen Flash (Bibliothekscode), temporäre Register/RAM und vor allem viele Instruktionen.

  • Codegröße: Schon wenige Float-Operationen ziehen Bibliotheksfunktionen nach, die das Programm deutlich wachsen lassen können.
  • Laufzeit: Addition/Multiplikation/Division in Float kostet viel mehr Zyklen als Integer-Arithmetik.
  • Determinismus: Gleitkomma kann hinsichtlich Timing weniger „vorhersehbar“ wirken, besonders wenn viele Bibliotheksroutinen beteiligt sind.
  • Debugging: Werte sind gut interpretierbar, aber Optimierung und Library-Aufrufe erschweren manchmal die Nachvollziehbarkeit.

Wenn Sie einen Überblick über das Prinzip der Gleitkommadarstellung möchten: IEEE-754-Standard (Überblick).

Was ist Fixed Point – und warum passt es so gut zu kleinen PICs?

Fixed Point (Festkomma) bedeutet: Sie speichern reale Zahlen als ganze Zahlen mit einem fest definierten Skalierungsfaktor. Statt „3,14“ speichern Sie beispielsweise „314“ und interpretieren den Wert als „314 / 100“. Die Hardware rechnet dann nur mit Integern, was auf 8-Bit-PICs deutlich effizienter ist. Der Preis: Sie müssen Skalierung, Überläufe und Rundung bewusst designen.

  • Geschwindigkeit: Integer-Operationen sind auf 8-Bit-Architekturen oft um Größenordnungen schneller als Float.
  • Flash sparen: Sie vermeiden große Teile der Gleitkomma-Library.
  • Deterministisches Timing: Besonders wichtig für Regelungen, Echtzeitmessungen und Interrupt-nahe Logik.
  • Kontrolle über Genauigkeit: Sie entscheiden, wie viele Nachkommabits/Dezimalstellen wirklich nötig sind.

Der Kernunterschied: Wertebereich, Auflösung und Fehlerbild

Die Entscheidung ist selten „Float ist immer schlecht“ oder „Fixed ist immer besser“. Sie hängt davon ab, welche Werte Sie abbilden und welche Genauigkeit Sie benötigen.

  • Floating Point: großer Wertebereich, relative Genauigkeit, sehr bequem bei Skalierungswechseln (z. B. mV bis kV).
  • Fixed Point: begrenzter Wertebereich, feste absolute Auflösung, sehr effizient und stabil bei „bekanntem Zahlenraum“ (z. B. Temperatur 0–50 °C, Sensor 0–1023).

Typischerweise ist Fixed Point ideal, wenn Sie Sensoren auslesen, Grenzwerte vergleichen, lineare Umrechnungen durchführen und einfache Filter/Regler einsetzen – solange Sie den Wertebereich sinnvoll definieren.

Q-Format verstehen: Der Standardweg für Festkomma

Eine verbreitete Methode ist das Q-Format. Dabei legen Sie fest, wie viele Bits für den ganzzahligen Anteil und wie viele für den Bruchteil genutzt werden. Bei einem 16-Bit-Wert ist beispielsweise „Q8.8“ ein häufiges Format: 8 Bits ganzzahlig, 8 Bits Bruchteil. Der Wert 1.5 wäre dann 1.5 * 256 = 384.

Skalierung im Q-Format

Allgemein gilt bei einem Bruchteil mit F Bits:

x_fixed = x_real × 2F

Und zurück:

x_real = x_fixed 2F

Das Schöne daran: Multiplikationen und Additionen lassen sich mit Integern rechnen. Sie müssen nur nach einer Multiplikation wieder passend zurückskalieren.

Multiplikation in Fixed Point: Warum ein 32-Bit-Zwischenergebnis Pflicht ist

Auf kleinen PICs ist das häufigste Festkomma-Problem ein Überlauf bei Multiplikationen. Multiplizieren Sie zwei 16-Bit-Festkommawerte, benötigen Sie fast immer ein 32-Bit-Zwischenergebnis, bevor Sie zurückskalieren.

Beispiel: Q8.8 × Q8.8

Wenn beide Werte 8 Bruchbits haben, besitzt das Produkt 16 Bruchbits. Sie müssen also um 8 Bits zurückschieben, um wieder Q8.8 zu erhalten:

p = a×b 2F

In Integerlogik entspricht das „erst 32 Bit multiplizieren, dann rechts schieben“. Für Rundung (statt Abschneiden) addieren Sie vor dem Shift ein halbes LSB:

p_rounded = a×b+2F1 2F

Das reduziert systematische Fehler, besonders bei Filtern und Regelungen.

Division in Fixed Point: Möglich, aber strategisch einsetzen

Division ist auf 8-Bit-PICs ohnehin relativ teuer, egal ob Integer oder Float. In Fixed Point ist Division dennoch oft gut machbar, wenn Sie sie selten ausführen oder vorberechnen. Ein typisches Muster ist: Zähler vor dem Dividieren hochskalieren, damit der Bruchteil erhalten bleibt.

Wenn Sie a durch b teilen möchten und wieder F Bruchbits im Ergebnis wollen:

q = a×2F b

In der Praxis lohnt sich häufig, Divisionskonstanten in Multiplikation mit einem Kehrwert umzuwandeln (z. B. „× 205 / 1024“ statt „/ 5“), solange Genauigkeit und Wertebereich passen.

Wann Floating Point trotz allem sinnvoll ist

Es gibt klare Situationen, in denen Gleitkomma auf kleinen PICs die vernünftige Wahl sein kann – trotz Overhead:

  • Komplexe Mathematik: z. B. trigonometrische Berechnungen, Wurzeln, logarithmische Skalen.
  • Breiter Wertebereich: wenn Skalierungswechsel ständig auftreten und Fixed-Point-Formate ständig „brechen“ würden.
  • Schnelle Entwicklung wichtiger als letzte Prozent Performance: Prototyping, Machbarkeitsstudien, Unterricht.
  • Sehr geringe Rechenfrequenz: z. B. einmal pro Sekunde eine Kalibrierung, während sonst nichts Zeitkritisches läuft.

Ein weiterer Punkt ist Teamarbeit: Wenn mehrere Personen am Code arbeiten, kann ein klarer Float-Code (mit dokumentierten Einheiten) manchmal weniger Fehler erzeugen als ein kompliziertes Fixed-Point-System ohne saubere Konventionen.

Wann Fixed Point klar überlegen ist

Festkomma ist oft die bessere Wahl, wenn Sie Echtzeit brauchen oder Ressourcen knapp sind:

  • Regelung und Filter: PID, gleitender Mittelwert, IIR-Filter, sobald Timing stabil sein muss.
  • ISR-nahe Verarbeitung: Messwerte im Interrupt vorverarbeiten, ohne lange Library-Routinen.
  • Stromsparbetrieb: kürzere Rechenzeit bedeutet weniger aktive Zeit des Controllers.
  • Kleine PICs mit wenig Flash: wenn die Float-Library das Projekt „sprengt“.

In solchen Fällen ist Fixed Point nicht nur schneller, sondern erhöht oft auch die Systemstabilität, weil Sie Rechenlast und Timing viel besser kontrollieren.

Einheiten und Skalierung: Der unterschätzte Erfolgsfaktor

Viele Rechenfehler entstehen nicht durch die Arithmetik selbst, sondern durch uneinheitliche Einheiten und Skalierung. Besonders bei Fixed Point sollten Sie konsequent dokumentieren, was ein Wert bedeutet:

  • Physikalische Einheit: z. B. mV, °C, Pa
  • Skalierung: z. B. „Temperatur in 0,1 °C“, „Spannung in mV“, „Q8.8“
  • Grenzbereiche: minimale/maximale Werte, erwartete Ausreißer
  • Rundung/Sättigung: wann wird gerundet, wann geklemmt?

Ein sehr praxistauglicher Ansatz ist „dezimale Festkomma-Skalierung“, z. B. Temperatur in Zehntelgrad. Das ist leicht lesbar und verhindert, dass Sie ständig in Binärbruchteilen denken müssen. Q-Formate sind dafür besonders gut, wenn Sie häufig multiplizieren und schieben möchten.

Überlauf, Sättigung und Vorzeichen: typische Fixed-Point-Fallen

Festkomma ist schnell – aber unforgiving. Ohne klare Regeln treten Fehler auf, die im Test selten und im Feld plötzlich sichtbar sind.

  • Überlauf: Multiplikation ohne 32-Bit-Intermediate ist eine häufige Ursache.
  • Sättigung: Bei Sensorfehlern oder Ausreißern sollten Werte geklemmt werden, statt „umzukippen“.
  • Signed vs. Unsigned: Temperatur kann negativ sein, ADC-Rohwerte meist nicht. Der Typ muss zur Bedeutung passen.
  • Shift bei signed: Rechts-Shift kann je nach Compiler arithmetisch sein; testen und typisieren Sie bewusst.

Für robuste Systeme lohnt sich ein kleines Set an Hilfsfunktionen/Makros: „saturating_add“, „saturating_mul“, „clamp“, „q_mul“, „q_div“. Damit bleibt Ihr Anwendungscode lesbar, während die kritischen Details zentral gelöst sind.

Performance-Realität auf kleinen PICs: Was in der Praxis bremst

Auf 8-Bit-PICs sind nicht nur Float-Operationen teuer. Auch 16-/32-Bit-Integer können spürbar kosten, weil sie aus mehreren 8-Bit-Schritten zusammengesetzt werden. Deshalb ist die wichtigste Optimierung oft: Zahlen so klein wie möglich halten, aber so groß wie nötig.

  • 8 Bit wo möglich: Flags, kleine Zähler, Zustände.
  • 16 Bit für Messwerte: ADC (10–12 Bit), Timerwerte, skalierte Größen.
  • 32 Bit nur für Zwischenwerte: Multiplikationen, Summen über viele Samples.

Ein häufiges Muster in Filtern: Sie summieren viele 16-Bit-Werte in 32 Bit, teilen am Ende (oder shiften), und speichern wieder 16 Bit. So bleibt die Rechengenauigkeit hoch, ohne permanent 32-Bit-Werte herumzutragen.

Debugging und Testbarkeit: Float wirkt einfacher, Fixed braucht Checks

Beim Debugging sind Float-Werte angenehm, weil sie direkt wie Messwerte aussehen. Fixed-Point-Werte sind oft „komisch“, solange Sie die Skalierung nicht im Kopf haben. Das lässt sich pragmatisch lösen:

  • Konvertierung nur für Debug-Ausgaben: z. B. für UART-Log oder Display aus Fixed nach „mV“/„°C“ umrechnen.
  • Unit-Tests am PC: Fixed-Point-Funktionen in einem Host-Test prüfen (Randfälle: Überlauf, Rundung).
  • Referenzrechnung: Für kritische Formeln einmalig Float als Referenz nutzen und Fixed dagegen validieren.

So erhalten Sie die Entwicklungsfreundlichkeit von Float, ohne im Produktbetrieb den Float-Overhead zu bezahlen.

Praxisbeispiele: Sensor-Umrechnung mit Fixed Point statt Float

Ein klassischer Fall ist die lineare Umrechnung eines ADC-Wertes in Millivolt. Nehmen wir an, ein 10-Bit-ADC liefert Werte 0–1023, Referenzspannung 5000 mV. Dann ist:

UmV = ADC×5000 1023

In Fixed Point können Sie das ohne Float lösen, indem Sie mit 32 Bit multiplizieren und am Ende dividieren. Wenn Division zu teuer ist, können Sie stattdessen mit einer Näherung arbeiten oder einen Kehrwert verwenden, sofern die Genauigkeit reicht. Für viele Anwendungen ist es außerdem völlig ausreichend, auf 1024 zu normieren (Bitshift), wenn Sie den kleinen systematischen Fehler tolerieren oder später kalibrieren.

Entscheidungshilfe: Eine kurze Checkliste

  • Ist die Berechnung zeitkritisch (ISR, schneller Regelkreis)? → meist Fixed Point.
  • Ist Flash knapp oder wächst der Code stark durch Libraries? → Fixed Point bevorzugen.
  • Ist der Wertebereich groß und stark wechselnd? → eher Float oder sehr durchdachtes Q-Format.
  • Ist Lesbarkeit/Time-to-Market wichtiger als maximale Effizienz? → Float kann sinnvoll sein.
  • Gibt es viele Multiplikationen/Additionen und wenige Divisionen? → Fixed Point spielt seine Stärken aus.

Outbound-Links für Grundlagen und Toolchain

IoT-PCB-Design, Mikrocontroller-Programmierung & Firmware-Entwicklung

PCB Design • Arduino • Embedded Systems • Firmware

Ich biete professionelle Entwicklung von IoT-Hardware, einschließlich PCB-Design, Arduino- und Mikrocontroller-Programmierung sowie Firmware-Entwicklung. Die Lösungen werden zuverlässig, effizient und anwendungsorientiert umgesetzt – von der Konzeptphase bis zum funktionsfähigen Prototyp.

Diese Dienstleistung richtet sich an Unternehmen, Start-ups, Entwickler und Produktteams, die maßgeschneiderte Embedded- und IoT-Lösungen benötigen. Finden Sie mich auf Fiverr.

Leistungsumfang:

  • IoT-PCB-Design & Schaltplanerstellung

  • Leiterplattenlayout (mehrlagig, produktionstauglich)

  • Arduino- & Mikrocontroller-Programmierung (z. B. ESP32, STM32, ATmega)

  • Firmware-Entwicklung für Embedded Systems

  • Sensor- & Aktor-Integration

  • Kommunikation: Wi-Fi, Bluetooth, MQTT, I²C, SPI, UART

  • Optimierung für Leistung, Stabilität & Energieeffizienz

Lieferumfang:

  • Schaltpläne & PCB-Layouts

  • Gerber- & Produktionsdaten

  • Quellcode & Firmware

  • Dokumentation & Support zur Integration

Arbeitsweise:Strukturiert • Zuverlässig • Hardware-nah • Produktorientiert

CTA:
Planen Sie ein IoT- oder Embedded-System-Projekt?
Kontaktieren Sie mich gerne für eine technische Abstimmung oder ein unverbindliches Angebot. Finden Sie mich auf Fiverr.

 

Related Articles