Ich war heute auf einer IBM Veranstaltung in Böblingen. Am Ende hatten wir das Glück, dass wir noch die nicht öffentliche Computersammlung besichtigen konnten. Leider kam meine einfache Handy-Kamera nicht besonders gut mit der Beleuchtung zurecht, aber es sind doch ein paar brauchbare Bilder entstanden.
Archiv für den Autor: Matthias
Fließkommazahlen und unerfahrene Programmierer
Gestern habe ich auf slashdot.org ein Beitrag eines Programmierers gesehen, der sich darüber beklagt hat, dass von ihm verlangt wurde, eine Steuerberechnung mit JavaScript zu entwickeln. Schließlich kennt JavaScript nur Fließkommazahlen und „jeder“ weiß, dass man damit keine kaufmännischen Anwendungen schreiben kann.
Diese Meinung ist weit verbreitet – gerade in diesen Kreisen. Das weckt bei mir den Argwohn, ob im Bereich kaufmännischer Software verstärkt mäßig erfahrene Programmierer unterwegs sind? Und aus solchen Vorurteilen und mangelnden Wissen resultieren dann BCD Arithmetik-Libraries und BCD Befehle in Prozessoren (BCD = binary coded decimal – zwei Dezimalziffern 0-9 und 0-9 in einem Byte).
Das ist totaler Unfug und zeigt nur einen erheblichen Mangel an (mathematischen) Wissen.
Mythos 1: im Binärsystem kann man Zahlen nicht exakt darstellen, im Dezimalsystem schon.
Fast völliger Unsinn. Es wird immer der Wert 0.1 (als Bruch: 1/10) als Beispiel genommen. Dieser Wert ist im Binärsystem tatsächlich nur gerundet darzustellen, da er dort eine unendliche Periode besitzt. Aber solche Zahlen gibt es im Dezimalsystem auch: 1/3. Dieser Wert lässt sich Dezimal auch nur gerundet darstellen. Prinzipiell gilt für (teilerfremde) Brüche der Art p/q, dass sie eine periodische Darstellung haben, wenn q Primfaktoren besitzt, die in der Basis nicht vorkommen. Das Binärsystem hat nur den Primfaktor 2 in der Basis – wirklich nicht üppig. Im Dezimalsystem sind es 2 und 5 – auch nicht wirklich besser. 1/3 – 1/7 – 1/11 – 1/13… verdammt viele Brüche erzeugen in beiden Systemen eine periodische Darstellung.
Das Problem ließe sich hier noch lösen, indem man mit Rationalen Zahlen arbeitet. Das hat aber Grenzen, denn man kann niemanden eine Rechnung schicken, auf der 47/11 Euro gefordert werden. Auf der Rechnung werden also doch nur 4,272727272727272727272727272727… Euro oder gerundet 4,27 Euro auftauchen.
Mythos 2: mit Fließkommazahlen kann man nicht Cent-genau rechnen
Eine double Fließkommazahl (wie sie z.B. von JavaScript verwendet wird) besitzt über 50 Bit für die Mantisse. Das sind mehr als 15 Dezimalstellen. Damit kann man mehr als nur das gesamte Geld dieser Welt auf einen Cent genau darstellen. Man muss lediglich darauf achten, den Fließkommawert bei der Ausgabe zum nächsten Cent hin auf- oder abzurunden.
Wenn die NASA mit Fließkommaberechnungen Satelliten auf Milliarden Kilometer genau steuern kann, dann sollte auch ein mäßig begabter Programmierer in der Lage sein, eine Leberwurst und 200 Gramm Butter abzurechnen. Das ist keine Raketenwissenschaft.
Mythos 3: wenn ich Integer-Werte für Cent-Beträge verwende, habe ich keine Rundungsfehler
Das gilt nur, wenn man sich auf simple Addition, Subtraktion oder Multiplikation beschränkt. Sobald eine Division ins Spiel kommt, ist der Vorteil dahin (ab hier sind es rationale Zahlen). Sieben Prozent Mehrwertsteuer auf mein Buch für 43,21 Euro sind 3,0247 Euro. Natürlich kann ich auch in hundertstel-Cent statt Cent rechnen. Aber das verschiebt das Problem nur und löst es nicht prinzipiell. Sobald ich den Betrag über eine Split-Buchung auf drei Kostenstellen aufteile, ist es mit exakten Werten vorbei.
Mythos 4: in einer Rechnung müssen alle Beträge auf den Cent genau stimmen
Das funktioniert nur, wenn man genügend ungenau hinschaut. Wenn ich auf einer Rechnung die gerundeten Mwst-Beträge zu jeder Rechnungsposition ausweise, wird die Summe der Beträge nur zufällig exakt zum gerundeten Mwst-Betrag der Netto Summe passen. Das Finanzamt weiß das. Jeder vernünftige Kaufmann ebenfalls. Und ein Programmierer sollte das auch wissen.
Fazit: man kann auch kaufmännische Software mit Fließkommazahlen erstellen
Es müssen halt einfach ein paar Rahmenbedingungen beachtet werden. Alle Ausgabewerte sollten auf den nächsten Cent auf- oder abgerundet werden. Sonst passieren so Dinge wie „überweisen Sie 4,272727272727273 Euro auf unser Konto“. Das ist immer für einen Lacher gut, aber genau genommen ist nichts schlimmes passiert. Der Betrag ist unhandlich aber nicht so falsch, dass ein messbarer Schaden entsteht.
Man kann einen Fließkommawert nicht unbesehen als Schleifenzähler verwenden. Dann kann es zu den gefürchteten „one off“ Fehlern kommen, die Schleife läuft einmal zu oft oder zu wenig. Auch hier muss man mit einer geeigneten Skalierung und Rundung arbeiten – dann geht das sehr wohl.
Bei extrem unterschiedlichen Werten kann die Reihenfolge der Berechnung für das Ergebnis wichtig sein: (1.001 * 10 hoch 15 + 0.00000001) – 1.0005 * 10 hoch 15 wird ein anderes Ergebnis liefern als (1.001 * 10 hoch 15 – 1.0005 * 10 hoch 15) + 0.00000001. So etwas kommt in der Physik und in der Mathematik durchaus vor. In kaufmännischen Anwendungen hat man so eine Dynamik eher nicht.
Der Altenburg-Express in Erfurt
Während wir auf unseren Regionalzug nach Weimar warteten, wurde ein Zug angekündigt, der nicht auf dem Fahrplan stand – der Altenburg-Express. Wir konnten zwar nicht mitfahren, es sind dafür aber ein paar schöne Bilder von der Abfahrt entstanden.
Fehler im Bewerbungsgespräch
Ich habe noch einen Fehler, den man in Bewerbungsgesprächen vermeiden sollte: wenn man in den Bewerbungsunterlagen wichtige Projekte aufführt (z.B. Diplomarbeit, Praktika oder auch Hobbyprojekte), dann sollte man auch etwas dazu erzählen können. Ich habe in den letzten Monaten mehrfach mit Bewerbern gesprochen, die noch nicht mal grundlegende Angaben zum Projekt machen konnten – z.B. was für eine Entwicklungsumgebung verwendet wurde. Und das zum Teil bei Projekten, die noch nicht mal drei Jahre in der Vergangenheit lagen.
Mir fallen dafür nur wenig schmeichelnde Erklärungen ein:
* Es war ein Gruppenprojekt und der Bewerber hat sich vom Team durchschleppen lassen, ohne selber einen nennenswerten Beitrag zu leisten.
* Das Projekt war nicht wirklich wichtig – eine kleine Nebensache, die man sich nicht merken muss.
* Der Bewerber ist unkonzentriert und hat ein sehr schlechtes Gedächtnis.
Sicher gibt es noch weitere – neutralere Erklärungen. Und wenn es das einzige Problem ist, dann ist das auch kein k.o. Kriterium. Aber es ist auf jeden Fall ein negativer Punkt, den man leicht vermeiden kann. Einfach zu Beginn der Bewerbungsphase noch mal die alten Unterlagen ansehen oder sich das Projekt anderweitig noch mal vor Augen führen. Falls das nicht klappt, würde ich mir überlegen, das Projekt ganz aus den Bewerbungsunterlagen zu streichen.
Standseilbahn fahren in Bad Wildbad
Wenn ich schon eine neue Rubrik „Bahn“ habe, dann muss ich sie natürlich auch mit Leben füllen. Hier ein kurzes Video von einer Talfahrt mit der Seilbahn in Bad Wildbad.
Metro fahren in Paris
Wegen Urlaub, Arbeit und Vereinsaktivitäten musste dieser Blog ein wenig zurückstehen. Aus Paris habe ich aber ein paar Bilder von einer Metro Linie mitgebracht, die ich vorher noch nicht gekannt habe. Auf den ersten Blick sieht sie aus wie eine ganz normale Metro. Allerdings macht Sie bei der Einfahrt einen Höllenlärm.
Wenn man genauer hinschaut, sieht man auch warum: sie fährt mit Reifen auf einer Art Riffel-Stahlblech Fahrbahn.
Frequenzzähler/ Periodenmesser mit einem PIC32 – Teil 8
Mittlerweile habe ich das Projekt abgeschlossen. Das Gerät funktioniert wie erwartet und die Genauigkeit und Kurzzeitstabilität ist gut. Einzig den Quarzoszillator werde ich wohl noch mal austauschen, da er eine zu hohe Temperaturabhängigkeit aufweist. Wenn man ihn mit dem Finger erwärmt, kann man das Messgerät auch als Fieberthermometer verwenden. Sobald ich mal günstig einen 1ppm TCXO mit 25 MHz bekomme wird das besser.
Im letzten Schritt habe ich noch die Spannungsversorgung ergänzt. Als Basis verwende ich ein normales USB Netzteil für die 5 Volt, die ich für die Anzeige und ein Teil der Eingangssignalverarbeitung benötige. Daraus leite ich dann noch mit einem einfachen Linearregler die 3,3 Volt für den Microcontroller ab.
Platine und Bereichsumschalter habe ich dann in ein Gehäuse eingebaut. Da ich keine Befestigungsschrauben auf der Vorderseite haben wollte, habe ich den Taster von der Rückseite her angeklebt. Das wäre beinahe schief gegangen, da ein wenig von dem Kleber auch an die Tastenkappe gekommen ist und diese mit der Frontplatte verklebt hat. Zum Glück konnte ich das Missgeschick mit etwas Geduld und Silikonöl beheben.
Was würde ich nun anders machen?
Im Vorfeld habe ich mir zu wenige Gedanken über den Aufbau der Platine und die Verteilung der Port-Pins gemacht. Da ich zuerst das Anzeigemodul aufgebaut habe, habe ich die Port-Pins danach ausgewählt, dass ich möglichst zusammenhängende Bits für die Bus Signale habe. Dabei habe ich nicht darauf geachtet, dass nur ein Teil der Input-Pins 5 Volt tolerant sind – und genau diese dann als Output verwendet. Zum Glück gibt es das 4-fach AND Gatter 7408 in einer VHC Version als Pegelwandler – allerdings nur im SMD Gehäuse. Die kleinen Pins in einer fliegenden Verdrahtung frei Hand anzulöten ist nicht einfach. Ich muss mir mal einen Vorrat an Adapterplatinen zulegen.
Weiterhin würde ich nun keinen 7447 mehr als 7 Segment Decoder verwenden. Statt dessen würde ich drei zusätzliche Port-Pins spendieren und jedes Segment einzeln per Software steuern. Das würde aber auch dazu führen, dass ich statt der 28 Pin Variante des PIC32 ein 44 Pin Gehäuse verwenden müsste. Und die zusätzlichen Pins würden weitere Zusatzfunktionen erlauben.
Zuletzt würde ich statt der beiden 32 Bit Counter nun vier 16 Bit Counter verwenden, die per Software dann jeweils auf 32 Bit verlängert werden – durch eine Interrupt Routine beim Überlauf. Damit hätte ich dann eine Zwei-Kanal Lösung oder könnte auch das Impuls-Pausen-Verhältnis messen.
Vielleicht werde ich das Projekt später noch mal aufgreifen und verbessern. Im Augenblick bin ich mit dem aktuellen Stand zufrieden und beende das Projekt erst mal.
Frequenzzähler/ Periodenmesser mit einem PIC32 – Teil 7
Heute habe ich mich mal hingesetzt um den Schaltplan und die Funktionsweise der Counter Teils aufzuzeichnen.
Die Funktionsweise ist eigentlich einfach. Wenn man einfach nur die Signalimpulse über einen definierten Zeitraum (der Torzeit) zählen würde, wäre es praktisch nicht möglich bei niedrigen Frequenzen eine vernünftige Auflösung zu bekommen. Für eine 6-stellige Anzeige benötigt man 1 Millionen Takte. Bei 100 Hertz wäre dafür eine Torzeit von 10.000 Sekunden nötig – rund 3 Stunden.
Alternativ dazu kann man die Periode messen. Dazu gibt das Messsignal die Torzeit vor und man zählt, wie viele Takte das Referenzsignal in dieser Zeit abgibt. Das ist bei 100 Hertz gut machbar, bei 1 MHz wiederum kaum mit guter Genauigkeit möglich.
Das hier verwendete Messprinzip ist im Wesentlichen eine Kombination der beiden Messmethoden. Bei einer Messung werden gleich zwei Zähler aktiv. Über den Zeitraum der Torzeit zählt ein Counter die Takte der Referenzfrequenz und ein weiterer die Takte der Signalfrequenz. Über das D FlipFlop wird sicher gestellt, dass die tatsächliche Torzeit immer nur ganze Perioden der Signalfrequenz beträgt. Andernfalls würde man bei niedrigen Frequenzen einen erheblichen Messfehler bekommen.
Das Diagramm zeigt ein Eingangssignal von 12,5 MHz an Pin A.
Wenn der Microcontroller eine neue Messsequenz einleiten will, setzt er Pin B auf 1. Da das D FlipFlop ein invertiertes Signal bekommt, wird mit der nächsten fallenden Signalflanke die Torzeit beginnen, der Ausgang Q des FlipFlop springt dann auf 1 (Pin C)
Mit dem Beginn der Torzeit werden über die beiden UND Gatter die beiden Counter für Signal- und Referenzfrequenz freigeschaltet und zählen nun hoch (Pin D und E an Pin 2 und 4 des Microcontrollers).
Der Microcontroller kann den Beginn der Torzeit über seinen Input – Pin C (an Pin 3 des PIC) lesen. Jetzt wartet er die gewünschte Zeit ab (z.B. ca. eine Sekunde) und setzt den Pin B wieder auf 0 zurück. Die genaue Zeit ist hier nicht wichtig, sie geht nicht in das Messergebnis ein solange sie ausreichend groß für die gewünschte Auflösung ist.
Das Tor bleibt jetzt aber noch offen – bis zur nächsten fallenden Flanke des Signals. Damit ist sicher gestellt, dass nur ganze Signalperioden gelesen werden. Wenn der Microcontroller feststellt, dass am Pin C wieder 0 anliegt, weiß er, dass eine Messperiode abgeschlossen ist. Nun kann er die Counter einlesen und das Ergebnis berechnen.
Im Bild sieht man die (viel zu kurze) Torzeit des Microcontrollers am Pin B von 200 nS (5 Referenz-Takte). Durch die Synchronisierung mit dem Signal wird die tatsächliche Torzeit auf 6 Takte gedehnt (Pin C). In dieser Zeit werden 3 steigende Flanken des Signals gezählt und 6 steigende Flanken der Referenz.
Aus diesen Werten kann nun die tatsächliche Signalfrequenz ermittelt werden:
Signalfrequenz = Signal-Takte * Referenzfrequenz / Referenz-Takte = 3 * 25000000 / 6 = 12500000
Natürlich ist die Torzeit in der Zeichnung viel zu kurz. Tatsächlich würde man hier eher eine Torzeit von ca. einer halben Sekunde wählen. Das kann ich nur nicht vernünftig Zeichnen. In diesem Fall würde die Rechnung vielleicht so aussehen ( bei einer Torzeit 0,51 Sekunden):
Signalfrequenz = Signal-Takte * Referenzfrequenz / Referenz-Takte = 6375000 * 25000000 / 12750000 = 12500000
Frequenzzähler/ Periodenmesser mit einem PIC32 – Teil 6
Heute bin ich dazu gekommen den internen Oszillator einzubauen. Ich habe dafür einen TCXO mit 25 MHz bestellt – in der Hoffnung, dass ich damit eine gute Stabilität erreiche. Laut Datenblatt sollte die Genauigkeit im Bereich 50ppm liegen. Zur Messung steht mir nur mein Rigol DG1062 zur Verfügung. Ich weiß nicht sicher, wie genau dieses Gerät ist, aber da es recht teuer war, hoffe ich auf gute Eigenschaften. Mein TCXO liegt 23ppm neben der Nomialfrequenz. Im Laufe der letzten Stunde hat die Anzeige meines Frequenzmessers nur um 4 Digits auf der 8. Stelle geschwankt. Das akzeptiere ich mal als sehr gutes Ergebnis.
Aufgrund des Messprinzips kann man sehr niedrige Frequenzen messen. Ich bin mir nicht sicher, ob ich die Originalschaltung falsch gelesen habe oder ob sie tatsächlich eine Race Condition enthält – bei mir hat das dazu geführt, dass ich mit ca. 50%er Wahrscheinlichkeit einen Takt zu viel gezählt habe. Bei 20 MHz und einem Messintervall von 1 Sekunde ist das kein Problem. Bei 1 Hertz gibt das völlig falsche Ergebnisse. Ich habe die Schaltung deshalb so abgeändert, dass das Gate mit fallenden Takt statt mit steigenden Takt geschaltet wird. Bei steigenden Takt zählt der Zähler hoch, so dass ich eine halbe Taktperiode Zeit zwischen den beiden wichtigen Ereignissen bekomme. Nach dieser Änderung steht die Anzeige auch bei sehr niedrigen Frequenzen exakt.
Bei sehr niedrigen Frequenzen unter 2 Hertz verlängert sich das Messintervall, im Durchschnitt auf das 2-fache der Periodendauer. Unter 100 Millihertz bekomme ich aber auch keine sinnvolle Anzeige mehr. Das ist aber auch nicht wichtig, es liegt weiter außerhalb des angepeilten Messbereichs. Nach oben komme ich bis 24 MHz, darüber gibt es ebenfalls erhebliche Messfehler.
Jetzt fehlt noch eine verbesserte Software mit Anzeige des Messbereichs (Hertz, Kilohertz, Megahertz), das Netzteil und das Gehäuse.
Frequenzzähler/ Periodenmesser mit einem PIC32 – Teil 5
Nach einigen Fehlversuchen bin ich nun wieder einen Schritt weiter. Geplant war es eigentlich, dass ich mit einen Referenztakt von 25 MHz arbeite. Bei meinem aktuellen Aufbau komme ich aber nicht zuverlässig über 10 MHz. Allerdings habe ich noch viele lang frei fliegende Leitungen.
Bei einem Referenztakt von 10 MHz und einem Signal von 1,234567 MHz komme ich auf eine Anzeige, die zwischen 1,234567 und 1,234568 pendelt. Besser kann ich es nicht erwarten. Meine Messperiode liegt bei ziemlich genau einer Sekunde.
Meine Hand liegt nicht zufällig links neben dem Zählermodul auf dem Kabel der Spannungsversorgung. Sie dient als Filter damit ich nicht über dieses Kabel erhebliche Störungen einfange. Ohne diesen Filter sind meine Messwerte immer ca. ein Promille zu hoch.
Die nächsten Schritte bestehen darin, dass ich den externen Referenztakt von meinem Funktionsgenerator auf den internen Oszillator umstelle. Dabei werde ich dann nochmal versuchen auf 25 MHz zu gehen und die Messperiode auf eine halbe Sekunde verkürzen. Falls das nicht klappt, bleibe ich eben bei 10 MHz.