-         

Ergebnis 1 bis 7 von 7

Thema: Float verhindern

  1. #1
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    21.04.2010
    Beiträge
    356

    Float verhindern

    Anzeige

    Hallo,
    ich habe folgendes Problem:
    Ich bekomme Werte vom ADC(12bit), diese werden dann auf einen bestimmten bereich beschränkt (Da die Potis die Maximalwerte nicht erreichen) und ein offset abgezogen, sodass dann werte zwischen 0 und ca. 2900 (je nach kanal unterschiedlich).
    Nun möchte ich die werte in dem Bereich in den Bereich 0-1023 (10bit) Packen.
    Die erste Idee war (natürlich) den Wert einfach mit einem float zu multiplizieren.
    Allerdings hab ich immer jede menge geschichten gehört das float auf avrs so schlimm ist und so weiter.
    Leider hab ich da keine Erfahrungswerte weil ich noch nie Floats auf nem AVR gebraucht hab.
    Daher nun meine Frage: sind die wirklich so schlimm ?
    Und wie lange (in takten) würd eine die Multiplikation einer 16 bit unsigned zahl mit einem float ungefähr dauern ?
    Meine Zweite idee war dann (da ich die 16 ja eh nicht ausschöpfe) die zahl erst per multiplikation mit einem 8bit auf die vollen 16bit zu erweitern und dann per rightshift in die 10 bit zu rücken.
    Allerdings kommt da bei meinem beispiel (maximalwert 2900, multi= 2^16/2900=22) ein maximalwert für die 10bit zahl von 996 raus, was nur 97% des werte bereichs entspricht.
    Is es irgendwie möglich (mindestens) 99% genauigkeit hinzukriegen ohne das es zu rechenaufwendig wird ?

    MFG Thalhammer

  2. #2
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    So schlimm sind Fließkommazahlen auch nicht. Wie lange es braucht, könnte man ggf. im Simulator probieren. Meine Schätzung liegt so bei vielleicht 100-500 Zyklen für das Umwandeln und Multiplizieren. Es hängt aber auch vom µC ab (ein Tiny ist da langsamer). Das 2. Problem ist ggf, das man einmal einiges an Code-größe dazu bekommt.

    Die Idee mit der Multiplication und Shifts ist schon richtig. So wie es aussieht müsste man aber wohl schon auf unsigned long, also einen 32 Bit Datentypen gehen (einen 24 Bit Datentypen unterstützt C nicht direkt, nur die Fließkomma Zahlen sind 24 Bit + Exponent). Das sollte immer noch etwas schneller als mit Fließkommazahlen sein. Bei den 32 Bit Zahlen kann man sich dann ggf. beim Shiften einiges Sparen und das Ergebnis aus den oberen 16 Bit nehmen.

  3. #3
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    21.04.2010
    Beiträge
    356
    Also ich hab in der zwischenzeit bisl gegooglet und wies ausschaut ist der UNterschied schon kraß:
    Hier :http://www.avrfreaks.net/index.php?n...=72923&start=0
    hat einer ein paar tests mit unterschiedlichen Datentypen gemacht und anscheinend hat da ein float schon enorme nachteile und schlägt offensichtlich mit 1876 takten zu buche (vs 86 bei nem 32bit integer).
    Also ich denke das da meine Lösung deutlich besser abschneidet:
    #define MAX 3750
    #define MIN 850
    #define MULTI 4294967296/(RV_MAX-RV_MIN)

    static inline uint16_t to10bit(uint16_t val)
    {
    if(val<MIN) val=0;
    else if(val>MAX) val=max-min;
    else val=val-min;
    uint32_t t=val*multi;
    t=t>>22;
    return (uint16_t)t;
    }
    Ich weis zwar nicht genau wieviel takte das braucht aber weniger als 1800 sinds sicher
    und die genauigkeit ist auf jedenfall ausreichend.

    PS: Mir is klar das man das noch optimieren kann (max-min vorher ausrechnen) aber ich vertraue da in den Compiler da es ja geinlined wird und bereits zur compilezeit bekannt ist.

    MFG Thalhammer

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    27.08.2013
    Ort
    Region Basel
    Alter
    59
    Beiträge
    2.435
    Hallo Thalhammer,

    Das geht ganz einfach übers Bruchrechnen.

    x = (n*k1)/k2;

    Anstatt mit
    x = n*0.75;
    rechnest du
    x = (n*3)/4;
    3/4 = 0.75

    Du musst nur erst nachsehen, mit welcher Genauigkeit dein C Zwischenberechnungen ausführt Meist sind es 32-Bit, das Zwischenresultat darf nicht grösser werden. Hinzu kommt noch, dass die entsprechenden Bibliotheken Platz benötigen.
    In meinen MicroController-Projekten der letzten 35 Jahre, findest du nirgends FP-Arithmetik. Allerdings kann es sein, dass z.B. in hundertstel Grad gerechnet wird. Falls nötig, wird dann das Komma bei der Ausgabe "dran gefummelt".

    MfG Peter(TOO)


    Praktisch kannst du damit rechnen, dass Floating-Point-Emulation so in der Grössenordnung Faktor 100 langsamer als Integer ist.
    Manchmal frage ich mich, wieso meine Generation Geräte ohne Simulation entwickeln konnte?

  5. #5
    Erfahrener Benutzer Roboter Genie Avatar von BMS
    Registriert seit
    21.06.2006
    Ort
    TT,KA
    Alter
    26
    Beiträge
    1.192
    Hallo,
    das "Bruchrechnen" habe ich in meinen Projekten auch verwendet. Der Bruch sollte dabei so weit wie möglich gekürzt werden. Auf möglichen Überlauf hat Peter(TOO) bereits hingewiesen. Zudem muss auch beim Teilen durch große Zahlen beachtet werden, dass aufgrund des ganzzahligen Teilens ohne Rest Genauigkeit verloren gehen kann.

    22 Shifts im obigen Code brauchen ohne Barrel Shifter auch viele Takte. Das Schieben kann auch auf das nächste Vielfache von 8 Bit geschehen, der Zugriff kann dann auf die einzelnen Bytes erfolgen:
    Code:
        //Vorraussetzung: Little Endian
        lsbyte0=*(((uint8_t*)(&variablemit32bit))+0);
        byte1=*(((uint8_t*)(&variablemit32bit))+1);
        byte2=*(((uint8_t*)(&variablemit32bit))+2);
        msbyte3=*(((uint8_t*)(&variablemit32bit))+3);
    Grüße, Bernhard
    "Im Leben geht es nicht darum, gute Karten zu haben, sondern auch mit einem schlechten Blatt gut zu spielen." R.L. Stevenson

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    27.08.2013
    Ort
    Region Basel
    Alter
    59
    Beiträge
    2.435
    Hallo Bernhard,
    Zitat Zitat von BMS Beitrag anzeigen
    Zudem muss auch beim Teilen durch große Zahlen beachtet werden, dass aufgrund des ganzzahligen Teilens ohne Rest Genauigkeit verloren gehen kann.
    Da muss man eben optimieren. Den Bruch so klein wie möglich, aber so gross, dass man die benötigte Genauigkeit noch erreicht!
    Aber gefragt wurde nach einem Fehler im Bereich von 1% und das ist eigentlich kein Problem.
    Zitat Zitat von BMS Beitrag anzeigen
    22 Shifts im obigen Code brauchen ohne Barrel Shifter auch viele Takte. Das Schieben kann auch auf das nächste Vielfache von 8 Bit geschehen, der Zugriff kann dann auf die einzelnen Bytes erfolgen.
    Das ist im Allgemeinen aber der Job des Compilerherstellers, dass er optimalen Code erzeugt.

    Bei manchen CPUs ist eine Integermultiplikation schneller als mehrere Left-Shifts.

    MfG Peter(TOO)
    Manchmal frage ich mich, wieso meine Generation Geräte ohne Simulation entwickeln konnte?

  7. #7
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    26.11.2004
    Beiträge
    451
    Zum weiteren Optimieren, sollte man auch noch versuchen den Nenner als eine 2er Potenz zu wählen.

    Der AVR kann zwar multiplizieren, zum Dividieren gibt es aber keinen Befehl. Hier muss also emuliert werden, außer es handelt sich um eine 2er Potenz, dann kann man das Ergebnis einfach nach rechts schieben.

Ähnliche Themen

  1. Relais anziehen beim anstecken verhindern?
    Von Filozof im Forum Controller- und Roboterboards von Conrad.de
    Antworten: 6
    Letzter Beitrag: 18.12.2008, 12:38
  2. mehrfaches Auswerten einer IF/Then Bedingung verhindern
    Von mat-sche im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 5
    Letzter Beitrag: 30.11.2008, 10:36
  3. Pulsüberschläge gegen Masse verhindern ?
    Von magic33 im Forum Elektronik
    Antworten: 4
    Letzter Beitrag: 17.11.2007, 13:33
  4. HILFE: Ledlauflicht Stacküberlauf verhindern
    Von Matthiasbaue im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 17
    Letzter Beitrag: 06.11.2006, 15:13
  5. Transitor - Teilleiten verhindern
    Von 2H2+O2=2H2O im Forum Elektronik
    Antworten: 4
    Letzter Beitrag: 27.04.2006, 23:35

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •