Nur zum Spaß und um zu beweisen, dass dies möglich ist, habe ich eine AVR-Assemblierungsroutine abgeschlossen, um sin (x) -Ergebnisse in 24 Bit (3 Byte) mit einem Fehlerbit zu berechnen. Der Eingabewinkel wird in Grad mit einer Dezimalstelle angegeben, von 000 bis 900 (0 ~ 90,0) nur für den ersten Quadranten. Es verwendet weniger als 210 AVR-Anweisungen und läuft durchschnittlich 212 Mikrosekunden, die von 211us (Winkel = 001) bis 213us (Winkel = 899) variieren.
Es dauerte mehrere Tage, um alles zu erledigen, mehr als 10 Tage (freie Stunden), nur um über den besten Algorithmus für die Berechnung nachzudenken, wenn man bedenkt, dass der AVR-Mikrocontroller kein Gleitkomma ist und alle möglichen Unterteilungen eliminiert. Was mehr Zeit in Anspruch nahm, war die Erstellung der richtigen Aufwärtswerte für Ganzzahlen. Um eine gute Genauigkeit zu erzielen, müssen die Werte von 1e-8 auf binäre Ganzzahlen 2 ^ 28 oder mehr erhöht werden. Sobald alle Fehler gefunden wurden, die für Präzision und Aufrundung verantwortlich sind, und die Berechnungsauflösung um zusätzliche 2 ^ 8 oder 2 ^ 16 erhöht wurden, wurden die besten Ergebnisse erzielt. Ich habe zuerst alle Berechnungen in Excel simuliert und darauf geachtet, dass alle Werte Int (x) oder Round (x, 0) sind, um genau die AVR-Kernverarbeitung darzustellen.
Im Algorithmus muss der Winkel beispielsweise im Bogenmaß angegeben werden. Die Eingabe erfolgt in Grad, um dem Benutzer die Arbeit zu erleichtern. Um Grad in Bogenmaß umzuwandeln, lautet die Trivialformel rad = Grad * PI / 180, es scheint nett und einfach zu sein, aber es ist nicht so, PI ist eine unendliche Zahl - wenn nur wenige Ziffern verwendet werden, entstehen Fehler am Ausgang, die Division durch 180 erfordert AVR-Bitmanipulation, da es keinen Teilungsbefehl gibt, und darüber hinaus würde das Ergebnis Gleitkomma erfordern, da Zahlen weit unter der Ganzzahl 1 enthalten sind. Beispielsweise beträgt der Radian von 1 ° (Grad) 0,017453293. Da PI und 180 Konstanten sind, können Sie diese Sache für eine einfache Multiplikation umkehren. PI / 180 = 0.017453293, multiplizieren Sie es mit 2 ^ 32 und es ergibt sich eine Konstante 74961320 (0x0477D1A8), multiplizieren Sie diese Zahl mit Ihrem Winkel in Grad, Nehmen wir 900 für 90 ° und verschieben Sie es um 4 Bit nach rechts (÷ 16), um 4216574250 (0xFB53D12A) zu erhalten, dh das Bogenmaß der 90 ° mit 2 ^ 28 Erweiterung, das in 4 Bytes ohne eine einzige Division passt (mit Ausnahme der 4) Bitverschiebung nach rechts). In gewisser Weise ist der in einem solchen Trick enthaltene Fehler kleiner als 2 ^ -27.
Alle weiteren Berechnungen müssen sich also daran erinnern, dass es 2 ^ 28 höher ist und sich darum gekümmert hat. Sie müssen die Ergebnisse für unterwegs durch 16, 256 oder sogar 65536 teilen, um zu vermeiden, dass unnötig wachsende Hungerbytes verwendet werden, die die Auflösung nicht verbessern würden. Das war eine mühsame Aufgabe, nur die minimale Anzahl von Bits in jedem Berechnungsergebnis zu finden und die Ergebnisgenauigkeit bei 24 Bit zu halten. Jede der verschiedenen Berechnungen wurde in Versuch / Irrtum mit höherer oder niedrigerer Bitanzahl im Excel-Fluss durchgeführt, wobei die Gesamtmenge der Fehlerbits am Ergebnis in einem Diagramm beobachtet wurde, das 0-90 ° mit einem Makro zeigt, das den Code 900 Mal ausführt. einmal pro Zehntelgrad. Dieser "visuelle" Excel-Ansatz war ein von mir erstelltes Tool, das mir sehr geholfen hat, die beste Lösung für jeden einzelnen Teil des Codes zu finden.
Wenn Sie beispielsweise dieses spezielle Berechnungsergebnis 13248737.51 auf 13248738 aufrunden oder nur die Dezimalstellen "0,51" verlieren, wie stark wirkt sich dies auf die Genauigkeit des Endergebnisses für alle 900 Eingabewinkel-Tests (00.1 ~ 90.0) aus?
Ich war in der Lage, das Tier bei jeder Berechnung innerhalb von 32 Bit (4 Bytes) zu halten, und endete mit der Magie, innerhalb von 23 Bit des Ergebnisses eine Genauigkeit zu erzielen. Bei der Überprüfung der gesamten 3 Bytes des Ergebnisses beträgt der Fehler ± 1 LSB (ausstehend).
Der Benutzer kann ein, zwei oder drei Bytes aus dem Ergebnis für seine eigenen Genauigkeitsanforderungen abrufen. Wenn nur ein Byte ausreicht, würde ich natürlich empfehlen, eine einzelne 256-Byte-Sin-Tabelle zu verwenden und die AVR-Anweisung 'LPM' zu verwenden, um sie abzurufen.
Sobald die Excel-Sequenz reibungslos und ordentlich lief, dauerte die endgültige Übersetzung von Excel zu AVR weniger als 2 Stunden. Wie üblich sollten Sie zuerst mehr überlegen und später weniger arbeiten.
Zu dieser Zeit war ich in der Lage, noch mehr zu quetschen und die Verwendung von Registern zu reduzieren. Der tatsächliche (nicht endgültige) Code verwendet ungefähr 205 Befehle (~ 410 Bytes) und führt eine sin (x) -Berechnung im Durchschnitt von 212us bei einem Takt von 16 MHz durch. Bei dieser Geschwindigkeit können 4700+ sin (x) pro Sekunde berechnet werden. Nicht wichtig, aber es kann eine präzise Sinuswelle bis zu 4700 Hz mit 23 Bit Genauigkeit und Auflösung ohne Nachschlagetabellen ausführen.
Der Basisalgorithmus basiert auf der Taylor-Reihe für sin (x), wurde jedoch stark modifiziert, um meine Absichten hinsichtlich des AVR-Mikrocontrollers und der Präzision zu erfüllen.
Selbst wenn die Verwendung einer 2700-Byte-Tabelle (900 Einträge * 3 Byte) schnell attraktiv wäre, was ist der Spaß oder die Lernerfahrung dabei? Natürlich wurde auch der CORDIC-Ansatz in Betracht gezogen, vielleicht geht es hier darum, Taylor in den AVR-Kern zu drücken und Wasser aus einem trockenen Gestein zu entnehmen.
Ich frage mich, ob Arduino "sin (78.9 °)" Processing (C ++) mit 23 Bit Genauigkeit in weniger als 212us und dem erforderlichen Code kleiner als 205 Anweisungen ausführen kann. Kann sein, wenn C ++ CORDIC verwendet. Arduino-Skizzen können Assembly-Code importieren.
Es macht keinen Sinn, den Code hier zu posten. Später werde ich diesen Beitrag bearbeiten, um einen Weblink dazu aufzunehmen, möglicherweise in meinem Blog unter dieser URL . Der Blog ist hauptsächlich in Portugiesisch.
Dieses Hobby-No-Money-Unternehmen war interessant und hat die Grenzen der AVR-Engine von fast 16MIPS bei 16MHz ohne Divisionsanweisung und Multiplikation nur in 8x8 Bit überschritten. Es erlaubt die Berechnung von sin (x), cos (x) [= sin (900-x)] und tan (x) [= sin (x) / sin (900-x)].
Vor allem half dies, mein 63 Jahre altes Gehirn poliert und geölt zu halten. Wenn Teenager sagen, dass die 'alten Leute' nichts über Technologie wissen, antworte ich: "Überlegen Sie noch einmal, wer hat Ihrer Meinung nach die Grundlagen für alles geschaffen, was Sie heute genießen?".
Prost