Guten Tag Ich möchte mit dem Atmega48 und den WinAVR einen Analogen Wert einlesen und diesen logarithmisch umwandeln. Die A/D Wandlung verläuft wie im AVR-GCC-Tutorial. Der Wert lässt sich gut einlesen und wird bisher in einen Integer gespeichert. Für den Logarithmus habe ich die Formel: x=20*log10(x/1024); Diese eignet sich aber nicht für Integer und bei Float steig der Programmspeicherbedarf um etwa 100% an wenn ich das ADCH Register in den Float hineinschreiben will. Wie kann ich nun das Register sauber in einen Float verrechnen? oder kennt jemand eine Alternative zu meiner Lösung? Freundliche Grüsse Zangetsu
Arbeite mit einer Tabelle (der ACD liefert 10bit = 0-1023; wenn Du für jeden 10. Wert einen Tabelleneintrag als 16bit-int hast sollte das gehen)
@zangetsu So wie ich das sehe willst du dB ausrechnen (20*log10(x)). Eine Möglichkeit dazu ist Zählen wieviele Nullen (von links aus gesehen) bis zur ersten 1 kommen. Jede 0 sind -6dB. Dann die Restlichen (beispielsweise 4 Bit) über eine kleine Tabelle ausrechnen um die Zwischenschritte von 1-5dB zu erhalten. Bsp : 0000 1000 0000 4 Nullen -> -24dB "000" nach der 1 -> +0dB als zus. Addition 0010 1000 0000 -> -12dB "010" nach der 1 -> ca +2dB -> -10dB Das ganze ist nur exemplarisch und müsste mal genauer ausgerechnet werden. Aber das wäre neben der Tabelle ein Lösungsweg.
Ok muss ich wohl zur Tabelle greifen. Aber nur um sicher zu gehen: gibt es wirklich keine "normale" Möglichkeit einen Integer in einen Float zu schreiben?
@ Zangetsu (Gast) >Ok muss ich wohl zur Tabelle greifen. Aber nur um sicher zu gehen: gibt >es wirklich keine "normale" Möglichkeit einen Integer in einen Float zu >schreiben? Sicher.
1 | int a; |
2 | float b; |
3 | |
4 | b=a; |
MFG Falk
>Ok muss ich wohl zur Tabelle greifen. Aber nur um sicher zu gehen: gibt >es wirklich keine "normale" Möglichkeit einen Integer in einen Float zu >schreiben? Entweder durch das Casten:
1 | float f; |
2 | int i; |
3 | i=IrgendwasWildes(); |
4 | f=(float)i; |
Dann ist in f statt z.B. 243 die 243,00 gespeichert. Oder du bastelst die dein Float selbst, indem du das Vorzeichen, den Exponent, sowie die Mantisse zurechtfrickelst. ( http://de.wikipedia.org/wiki/Gleitkommazahl ) Zurück zum Logarithmieren: 1) Nimm ne Tabelle in der die Funktionswerte in äquidistanten Abständen gespeichert sind und interpoliere dazwischen linear. 2) Mit Kenntnis über den Logarithmus (bzw den betrachteten Bereich), kannst du die Tabelle anpassen und dort wo sich die Werte stärker ändern mehrere Einträge machen.
1 | int Tabelleneintraege[]={1,3,9,16,25,36,100}; |
2 | int zugehörigeWerte[] ={1,2,3, 4, 5, 6, 10}; |
3 | |
4 | int getWert(int input){ |
5 | int ret; |
6 | int i=0; |
7 | while(Tabelleneintrag[i]<input)i++; |
8 | |
9 | //dein Wert liegt jetzt zwischen i und i+1
|
10 | // also musst du zwischen zugehörigeWerte[i] und zugehörigeWerte[i+1]
|
11 | // linear interpolieren.
|
12 | |
13 | ret=Tabelleneintraege[i]+ \ |
14 | ( Tabelleneintraege[i+1]-Tabelleneintraege[i]) / \ |
15 | (zugehörigeWerte[i+1]-zugehörigeWerte[i])*input-Tabelleneinträge[i]; |
16 | return ret; |
17 | }
|
Zu guter Letzt: Du kennst Festkomma-Arithmetik? ( http://de.wikipedia.org/wiki/Festkommazahl ) ( http://www.mikrocontroller.net/articles/Festkommaarithmetik ) Viele Grüße Stefan
Falk Brunner schrieb: > @ Zangetsu (Gast) > >>Ok muss ich wohl zur Tabelle greifen. Aber nur um sicher zu gehen: gibt >>es wirklich keine "normale" Möglichkeit einen Integer in einen Float zu >>schreiben? > > Sicher. > >
1 | > int a; |
2 | > float b; |
3 | >
|
4 | > b=a; |
5 | >
|
6 | >
|
@Zangetsu Aber sicher nicht so
1 | x=20*log10(x/1024); |
denn x / 1024 ergibt bei dir immer 0 http://www.mikrocontroller.net/articles/FAQ#Datentypen_in_Operationen
Vor kurzem gab es hier einen anderen Thread zum Thema Logarithmus und Exponentialfunktion (finde ihn gerade nicht). Für den Logarithmus wurde folgendes Verfahren vorgeschlagen, das mit Integermultiplikationen und -additionen auskommt: http://de.wikipedia.org/wiki/Logarithmus#Berechnung_einzelner_Bin.C3.A4rziffern
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.