Forum: Mikrocontroller und Digitale Elektronik Problem mit Werten von Potentiometer


von Laurin (wildatheart)


Lesenswert?

Ich habe ein seltsames Problem mit dem Wert eines Potentiometers, der 
die Lautstärke eines DAC steuern soll. Meine Schaltung besteht aus einem 
Atmega168, der den DAC (ES9028Pro) via I2C ansteuert. Das Poti bildet 
mit 3.3V und GND einen Spannungsteiler, dessen Augang an PC0 geht.

Der Bereich von 0 bis 1023 wird in einen Bereich von 0 bis 60 
umgewandelt (siehe Code unten). Beim Debuggen sehen alle Werte korrekt 
aus, aber wenn ich 0 vom Potentiometer an die Funktion 
„setAllDACVolumes()“ übergebe, erhalte ich keine Dämpfung von 0, sondern 
kein Audio. Wenn ich aber der Funktion direkt eine "0" gebe, erhalte ich 
null Dämpfung. Oder auch wenn ich direkt eine "10" gebe, erhalte ich die 
korrekte Dämpung von 5dB.

1
int currentVolume = ADC_read(0);
2
if(currentVolume != lastVolume) {
3
    uint8_t att_db = ((currentVolume * 60.0f)/ 1023.0f);
4
    setAllDACVolumes(att_db*2);
5
    lastVolume = currentVolume;
6
}

Die setAllDACVolumes()-Funktion sieht so aus:
1
void setAllDACVolumes(uint8_t Value)
2
{
3
    int i;
4
    for (i=0; i<8; i++)
5
    {
6
        SendCtrlReg2(DAC_REG_VOLUME_BASE+i, Value);  // set DAC Volumes, 0x00 is default
7
    }
8
}

Die Funktion SendCtrlReg2 schreibt den Wert, der der Funktion übergeben 
wird, in das Register des DAC (ES9028Pro). In meinem Fall sind das die 
Register 16 bis 23. Der Standardwert für die Lautstärke ist 0x00. Diese 
Funktion läuft korrekt; sie schreibt auch in andere Register.
Ich code mit Microchip Studio und debugge mit einem Atmel ICE.

: Verschoben durch Moderator
von Michael B. (laberkopp)


Lesenswert?

Laurin schrieb:
> uint8_t att_db = ((currentVolume * 60.0f)/ 1023.0f);

Als 0 x 60.0 und dann / 1023.0 und bei Übergabe nochmal x 2

Du verwendest float, und float ist nie genau. Allerdings sillte das 
Virzeichen stimmen und nicht -0.0001 zu -1 und dann 255 werden, daher 
kann ich den Effekt nicht erklären.

Man könnte die maximal 1023 von (klugerweuse uint16_t) currentVolume 
auch mit 60U multiplizieren, ergibt 61380 und passt noch in einen 
uint16_t und dann durch 1023U teilen zu 59 und dann x 2 macht maximal 
118. Ich hätte erwartet du programmierst 0-255. Aber eigentlich hast du 
ein zusätzliches bit mit 18dB, also 0-291.

von Thilo R. (harfner)


Lesenswert?

Was passiert bei currentVolume == lastVolume ?
Wenn Du das Poti auf 0 stellst, wird das nach dem ersten Mal so sein.
Bei anderen Werten dithert der ADC Wert so rum, da tritt der Fall selten 
auf. Möglicherweise steckt das Problem an einer ganz anderen Stelle als 
Du vermutest.

: Bearbeitet durch User
von Laurin (wildatheart)


Lesenswert?

Thilo R. schrieb:
> Was passiert bei currentVolume == lastVolume ?
> Wenn Du das Poti auf 0 stellst, wird das nach dem ersten Mal so sein.

lastVolume ist definiert als 0xff. Die Bedingung war beim Debuggen zu 
Beginn nie true.

von Thilo R. (harfner)


Lesenswert?

Ist es so, dass die Einstellung via ADC für alle Werte funktioniert, nur 
speziell 0 nicht? Oder funktioniert die Einstellung über das Poti 
generell nicht, aber mit jedem hartkodierten Wert doch?

von Laurin (wildatheart)


Lesenswert?

Thilo R. schrieb:
> Ist es so, dass die Einstellung via ADC für alle Werte funktioniert, nur
> speziell 0 nicht? Oder funktioniert die Einstellung über das Poti
> generell nicht, aber mit jedem hartkodierten Wert doch?

Die ADC funktioniert für alle Werte. Selbst wenn ich 0 nicht einstellen 
könnte, würde der Wert 2 oder 3 in einer sehr kleinen Attenuation 
resultieren, und damit ein klar hörbares Audiosignal durchkommen würde.

von Teo D. (teoderix)


Lesenswert?

Laurin schrieb:
> erhalte ich keine Dämpfung von 0, sondern
> kein Audio.

Was müsste normal gesendet werden, um das zu erreichen?

von Laurin (wildatheart)


Lesenswert?

Teo D. schrieb:
> Laurin schrieb:
>> erhalte ich keine Dämpfung von 0, sondern
>> kein Audio.
>
> Was müsste normal gesendet werden, um das zu erreichen?

Das:
1
void setAllDACVolumes()
2
{
3
    int i;
4
    for (i=0; i<8; i++)
5
    {
6
        SendCtrlReg2(DAC_REG_VOLUME_BASE+i, 0);  // set DAC Volumes, 0x00 is default
7
    }
8
}

von Frank O. (frank_o)


Lesenswert?

Laurin schrieb:
> Der Bereich von 0 bis 1023 wird in einen Bereich von 0 bis 60

In Arduino gibt es die Funktion map(). Wird sicher etwas Ähnliches in 
C/C++ geben. Vielleicht geht es damit. Vor allem, damit kannst du unten 
oder oben was weg x_en.
Ich weiß nicht, ob das auch da rein spielen könnte. Lautstärkepotis sind 
oft nicht linear.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Laurin schrieb:
> und debugge mit einem Atmel ICE.

Na dann laß Dir doch mal anzeigen, was als "Value" übergeben wird.

Laurin schrieb:
> int currentVolume = ADC_read(0);

Also kann ADC_read() auch negative Werte liefern?

Laurin schrieb:
> uint8_t att_db = ((currentVolume * 60.0f)/ 1023.0f);

Was passiert dabei mit negativen Werten?

von Michael B. (laberkopp)


Lesenswert?

Peter D. schrieb:
> Also kann ADC_read() auch negative Werte liefern?

Nein, nur 0 bis 1023. Du kennst das Arduino-Framework nicht ?

Peter D. schrieb:
> Was passiert dabei mit negativen Werten?

uint8_t kennt keine negativen Werte.

Und currentVolume wird, bevor gerechnet wird, von int in float 
gewandelt.

Aber float-Rechnungen sind nicht exakt.

von Rainer W. (rawi)


Lesenswert?

Frank O. schrieb:
> In Arduino gibt es die Funktion map(). Wird sicher etwas Ähnliches in
> C/C++ geben.

Früher (tm) nannte man das Dreisatz, genauer Geradengleichung in der 
Zwei-Punkte-Form. Und natürlich lässt sich die auch in C/C++ 
formulieren, wenn man nicht die Arduino Quellen danach durchsuchen 
möchte.

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Michael B. schrieb:
> Peter D. schrieb:
>> Also kann ADC_read() auch negative Werte liefern?
>
> Nein, nur 0 bis 1023. Du kennst das Arduino-Framework nicht ?

Warum nutzt der TO dann für currentVolume den Typ int?

> Peter D. schrieb:
>> Was passiert dabei mit negativen Werten?
>
> uint8_t kennt keine negativen Werte.

Aber int für currentVolume. Nichts anderes meinte Peter.

BTW. Du plenkst.

von Frank O. (frank_o)


Lesenswert?

Rainer W. schrieb:
> Früher (tm) nannte man das Dreisatz, genauer Geradengleichung in der
> Zwei-Punkte-Form.

Auch heute noch.
Aber vielleicht sind solche Funktionen schon optimiert und funktionieren 
besser?
Ich weiß es nicht. Oder meinst du, dass alle zu doof zum Rechnen sind, 
dass man so was implementieren muss?

von Jens G. (jensig)


Lesenswert?

Laurin schrieb:
> aus, aber wenn ich 0 vom Potentiometer an die Funktion
> „setAllDACVolumes()“ übergebe, erhalte ich keine Dämpfung von 0, sondern

Vielleicht solltest Du erstmal klären, ob wir nun über Volume 
(Lautstärke, Verstärkung) reden wollen, oder Dämpfung ...

von Rainer W. (rawi)


Lesenswert?

Frank O. schrieb:
> Aber vielleicht sind solche Funktionen schon optimiert und funktionieren
> besser?

Da gilt es erstmal die Bewertungskriterien für "besser" in einem 
bestimmten Szenario zu definieren.

Wie die Arduino Funktion map() sich grob benimmt, ist in der Duko so 
zusammengefasst:
"Die map() - Funktion verwendet Ganzzahl-Mathematik, so dass keine 
Brüche generiert werden, wenn die Mathematik möglicherweise darauf 
hinweist, dass dies der Fall ist. Bruchreste werden abgeschnitten und 
nicht gerundet oder gemittelt."

von Frank O. (frank_o)


Lesenswert?

Rainer W. schrieb:
> zusammengefasst

🔝

von Laurin (wildatheart)


Lesenswert?

Jens G. schrieb:
> Laurin schrieb:
>> aus, aber wenn ich 0 vom Potentiometer an die Funktion
>> „setAllDACVolumes()“ übergebe, erhalte ich keine Dämpfung von 0, sondern
>
> Vielleicht solltest Du erstmal klären, ob wir nun über Volume
> (Lautstärke, Verstärkung) reden wollen, oder Dämpfung ...

In die Register schreibe ich den Wert der Dämpfung. Die lässt sich in 
0.5dB-Schritten pro Wert 1 absenken. 0 dB, oder 0x00 ist volle 
Lautstärke.

von Laurin (wildatheart)


Angehängte Dateien:

Lesenswert?

Auf dem Bild seht Ihr den Debug-Mode. Und die Variable att_db, die an 
die Funktion setAllDAC Volumes() übergeben wird ist 0. Aber ich bekomme 
keine 0 Attenuation und damit auch kein Audio. Das ist für mich nicht 
erklärbar..

von Ob S. (Firma: 1984now) (observer)


Lesenswert?

Laurin schrieb:

> Auf dem Bild seht Ihr den Debug-Mode. Und die Variable att_db, die an
> die Funktion setAllDAC Volumes() übergeben wird ist 0. Aber ich bekomme
> keine 0 Attenuation und damit auch kein Audio. Das ist für mich nicht
> erklärbar..

Was steht in Register15, Bit0?

von Laurin (wildatheart)


Lesenswert?

Ob S. schrieb:
> Laurin schrieb:
>
>> Auf dem Bild seht Ihr den Debug-Mode. Und die Variable att_db, die an
>> die Funktion setAllDAC Volumes() übergeben wird ist 0. Aber ich bekomme
>> keine 0 Attenuation und damit auch kein Audio. Das ist für mich nicht
>> erklärbar..
>
> Was steht in Register15, Bit0?

Register 15 ist auf default

von Rainer W. (rawi)


Lesenswert?

Laurin schrieb:
> Register 15 ist auf default

Zeigt der Debugger "default" oder wie kommst du auf den Wert?

von Michael B. (laberkopp)


Lesenswert?

Laurin schrieb:
> Aber ich bekomme keine 0 Attenuation

Wenn du aber statt der att_db*2 die setAllDACVolumes mit 0 
einkommentierst geht es ?

stack overflow.

von Laurin (wildatheart)


Lesenswert?

Also meinst du, wenn ich der funktion direkt eine 0 gebe? In diesem Fall 
geht es, ja

von Ob S. (Firma: 1984now) (observer)


Lesenswert?

Laurin schrieb:
> Also meinst du, wenn ich der funktion direkt eine 0 gebe? In diesem Fall
> geht es, ja
1
int currentVolume = ADC_read(0);
2
if(currentVolume != lastVolume) {
3
    uint8_t att_db = ((currentVolume * 60.0f)/ 1023.0f);
4
    setAllDACVolumes(att_db*2);
5
                     ^^^^^^^^ 
6
    lastVolume = currentVolume;
7
}

Er meinte sicher das von mir im Zitat hervorgehobene. Was passiert, wenn 
du an Stelle des Ausdrucks "att_db*2" einfach "0" hinschreibst?

von Laurin (wildatheart)


Lesenswert?

Rainer W. schrieb:
> Laurin schrieb:
>> Register 15 ist auf default
>
> Zeigt der Debugger "default" oder wie kommst du auf den Wert?

Ich fasse das Register 15 aktuell nicht an. Deshalb ist es wohl auf 
default.

von Laurin (wildatheart)


Lesenswert?

> Er meinte sicher das von mir im Zitat hervorgehobene. Was passiert, wenn
> du an Stelle des Ausdrucks "att_db*2" einfach "0" hinschreibst?

Wie bereits erwähnt bekomme ich 0dB Dämpfung und damit volles Volumen, 
wenn ich eine "0" anstelle von "att_db*2" setze

von Teo D. (teoderix)


Lesenswert?

Was muss an diese Funktion normalerweise übergeben werden, um kein Audio 
auszugeben. Also um das selbe zu erreichen, wie im Fehlerfall?

von Ob S. (Firma: 1984now) (observer)


Lesenswert?

Laurin schrieb:
>> Er meinte sicher das von mir im Zitat hervorgehobene. Was passiert, wenn
>> du an Stelle des Ausdrucks "att_db*2" einfach "0" hinschreibst?
>
> Wie bereits erwähnt bekomme ich 0dB Dämpfung und damit volles Volumen,
> wenn ich eine "0" anstelle von "att_db*2" setze

OK, nächster Schritt: was passiert, wenn du das mit der 0 so läßt, aber 
zusätzlich eine Zeile höher vor die Variablendeklaration noch ein 
"volatile" schreibst?

Der Sinn der Sache ist, die Ausführung des Gleitkommacode-Gedöhns zu 
erzwingen, auch wenn das Ergebnis der Berechnung dann doch nicht benutzt 
wird.

von Laurin (wildatheart)


Lesenswert?

Teo D. schrieb:
> Was muss an diese Funktion normalerweise übergeben werden, um kein Audio
> auszugeben. Also um das selbe zu erreichen, wie im Fehlerfall?

Eine hohe Dämpfung, in meinem Fall ist die maximale Dämpfung 60dB. Die 
wird erreicht, wenn currentVolume den Wert 1023 hat. att_db wird mit 
Faktor 2 multipliziert, da in 0,5dB-Schritten attenuiert wird.

von Rainer W. (rawi)


Lesenswert?

Ob S. schrieb:
> uint8_t att_db = ((currentVolume * 60.0f)/ 1023.0f);
>     setAllDACVolumes(att_db*2);

Hat jetzt nicht mit dem eigentlichen Problem zu tun, aber die "*2" in 
dem Funktionsaufruf ist arg ungeschickt. Dadurch lassen sich die 
0.5dB-Schritte nicht einstellen. Warum packst du die 2 nicht in die 
Float-Rechnung, bevor der Wert auf uint8_t konvertiert wird, d.h. 
skalierst currentVolume direkt auf 0..120?

: Bearbeitet durch User
von Ob S. (Firma: 1984now) (observer)


Lesenswert?

Rainer W. schrieb:

> Hat jetzt nicht mit dem eigentlichen Problem zu tun, aber die "*2" in
> dem Funktionsaufruf ist arg ungeschickt.

Nicht unbedingt.

Wenn es beispielsweise eins der Designziele war (aus welchen Gründen 
auch immer), nur volle dB-Steps zu ermöglichen, dann passt das schon. 
Offensichtlich wird ja auch der mögliche Bereich (ganz absichtlich) 
nicht ausgenutzt.

Nö, wenn da was zu optimieren wäre, dann wäre die erste Maßnahme, den 
float-Scheiß rauszuwerfen. Das ist, was hier auf jeden Fall kein Mensch 
braucht (und möglicherweise sogar indirekt über den Resourcenverbrauch 
der störende Knackpunkt ist).

von Joachim B. (jar)


Lesenswert?

Ob S. schrieb:
> Nö, wenn da was zu optimieren wäre, dann wäre die erste Maßnahme, den
> float-Scheiß rauszuwerfen.

wenn ich weiß daß ich float nicht brauche wäre das meine erste Maßnahme 
und im µC brauche ich für ADC und DAC nie float.
Float brauche ich allenfalls für eine Ausgabe zu Menschen und kurz davor 
kann ich zu float wandeln wenns sein muß und das sogar ohne float 
Library, ich rechne z.B. in CentiVolt als uint_16 und setze zur Ausgabe 
nur das Komma per Textersetzung in den String.

: Bearbeitet durch User
von Gregor J. (Firma: Jasinski) (gregor_jasinski)


Lesenswert?

Joachim B. schrieb:
> wenn ich weiß daß ich float nicht brauche wäre das meine erste Maßnahme
> und im µC brauche ich für ADC und DAC nie float.
> Float brauche ich allenfalls für eine Ausgabe zu Menschen und kurz davor
> kann ich zu float wandeln wenns sein muß und das sogar ohne float
> Library, ich rechne z.B. in CentiVolt als uint_16 und setze zur Ausgabe
> nur das Komma per Textersetzung in den String.

Ich persönlich brauche in fast allen µC-Fällen auch keine 
Fließkommazahlenberechnungen und mache das so ähnlich wie beschrieben. 
In dem vorliegenden Fall müsste man den Wert an der entsprechenden 
Stelle auch casten, es wird aber alles sehr zäh und schwierig, wenn 
jemand nicht einmal in der Lage ist, seine fünf Zeilen Code systematisch 
so durchzudebuggen, dass er die Ursache für seine falschen Werte 
eingrenzen und auf diese Weise finden kann. Bei so etwas gibt es bei mir 
kein Mitleid, denn das kann man relativ schnell lernen und Methoden zum 
Debuggen gibt es viele; und diese eigenen Hausaufgaben sollte man auch 
so schnell wie möglich erledigen. Fertigcode gibt es von mir auch nicht, 
denn das sollte derjenige schon selbst hier so weit korrigieren und 
anpassen, bis es passt, sonst wird der Lernprozess nie in Gang gesetzt 
und in ein paar Wochen oder Monaten wird ein neuer Thread mit ähnlicher 
Problematik eröffnet... und wieder darauf gewartet, dass einem ein 
fertiges Kotelett serviert wird.

von Rainer W. (rawi)


Lesenswert?

Joachim B. schrieb:
> Float brauche ich allenfalls für eine Ausgabe zu Menschen ...

Gerade der Mensch will eine Darstellung mit Mantisse und Exponent 
eigentlich nicht habe, sondern kann beim Ablesen besser mit einem Komma 
an fester Position umgehen, falls es sich nicht um Daten mit extrem 
großem Dynamikbereich handelt. Dafür eignen sich dann oft logarithmische 
Angaben besser z.B. in dB oder nach der Richter Skala - je nach Kontext.

von Rainer W. (rawi)


Lesenswert?

Ob S. schrieb:
> Wenn es beispielsweise eins der Designziele war (aus welchen Gründen
> auch immer), nur volle dB-Steps zu ermöglichen, dann passt das schon.
> Offensichtlich wird ja auch der mögliche Bereich (ganz absichtlich)
> nicht ausgenutzt.

Sag mir einen vernünftigen Grund, warum man bei Einsatz eines Potis als 
Geber für die Lautstärkeeinstellung diese Lautstärke der Einstellung 
nicht möglichst kontinuierlich folgen soll.
So, wie sich der TO mit dem Debuggen schwer tut, vermute ich erstmal 
keine ernste Absicht hinter dem Verhalten, sondern eher krampfhaftes 
Festhalten an einer 1dB-Teilung.

: Bearbeitet durch User
von Teo D. (teoderix)


Lesenswert?

Rainer W. schrieb:
> So, wie sich der TO mit dem Debuggen schwer tut, vermute ich erstmal
> keine ernste Absicht hinter dem Verhalten, sondern eher krampfhaftes
> Festhalten an einer 1dB-Teilung.

Also so wie bei 98% aller Hobbyprojekten?!

Nenn mir einen vernünftigen Grund, warum dich dieser Thread über haut 
interessiert? Ernste Absichten scheinst du ja nicht zu haben!

von Harald K. (kirnbichler)


Lesenswert?

Statt der float-Herumrechnerei könnte man auch einfach mal einen Blick 
auf Zweierpotenzen werfen.

Den ADC-Wert, der zwischen 0 und 1023 liegt, teilt man durch 16. Dann 
erhält man einen Wert zwischen 0 und 63.

Teilen durch eine Zweierpotenz ist einfach nur schieben nach rechts.

Und jetzt macht man noch 'ne simple Bereichsbegrenzung, ist der Wert 
größer als 60, wird er auf 60 begrenzt.

Daß da potentiell ein bisschen Drehwinkel des Potis kurz vor dem 
Anschlag verloren geht, sollte man verkraften können, das ist eh' alles 
analog und Potis vor allem sind nicht irrwitzig linear und genau schon 
gar nicht.
1
    uint8_t att_db = currentVolume / 16;
2
    if (att_db > 60)
3
      att_db = 60;

Wenn das Ziel tatsächlich ist, auf 60 dB zu kommen, sollte man nicht 
durch 16, sondern nur durch 8 teilen, denn die Lautstärkenregister 
arbeiten mit 0.5-dB-Schritten.

Auf die Bereichsbegrenzung kann man auch verzichten, denn die 
Lautstärkenregister sind 8 Bit breit, können also Werte von 0..255 
annehmen.

Und wenn man den vollen Wertebereich der Lautstärkenregister nutzen 
will, statt bei 60 (oder 63) dB aufzuhören, teilt man den ADC-Wert durch 
4.

Fertig. Kein Floatgekrampfe nötig.

von Nemopuk (nemopuk)


Lesenswert?

Laurin schrieb:
> wenn ich 0 vom Potentiometer an die Funktion „setAllDACVolumes()“
> übergebe, erhalte ich keine Dämpfung von 0, sondern kein Audio. Wenn ich
> aber der Funktion direkt eine "0" gebe, erhalte ich null Dämpfung.

Deine Funktion erwartet einen Integer als Argument. Dort ist die 0 
eindeutig definiert, egal woher sie kommt. Es kann nicht sein, dass die 
Funktion sich unterschiedlich verhält, je nach dem woher die 0 kommt.

Also solltest du diese Annahme nochmal doppelt und dreifach überprüfen, 
wahlweise mit einem Unterbrechungspunkt innerhalb der Funktion oder mit 
einer seriellen Text-Ausgabe. Letzteres würde ich bevorzugen.

Wenn das keine neue Erkenntnis bringt  dann bedenke, dass Timing eine 
Rolle spielen kann. Und bedenke, dass ganz andere scheinbar intakte 
Teile des Programms möglicherweise Fehlfunktionen auslösen, z.B. indem 
sie einen Heap/Stack Überlauf auslösen, über Array-Grenzen hinaus 
laufen, oder mit nicht initialisierten Zeigern arbeiten.

Manchmal hilft es, das Programm schrittweise zu verkleinern (Teile 
auskommentieren, bzw. durch Dummies ersetzen), bus der Fehler 
verschwindet. Oder anders herum mit einem minimalen Programm neu 
anfangen und Schrittweise erweitern, bis der Fehler wieder kommt.

: Bearbeitet durch User
von Gregor J. (Firma: Jasinski) (gregor_jasinski)


Lesenswert?

Harald K. schrieb:
> Statt der float-Herumrechnerei könnte man auch einfach mal einen Blick
> auf Zweierpotenzen werfen.

Statt mit Float, rechnet man mit kleinstmöglichen Integern – in diesem 
Fall wäre das z.B. 16-Bit ohne Vorzeichen, weil man auf knapp über 60 
Tausend kommen möchte, da man die Multiplikation in der Regel immer 
zuerst machen muss. Wenn es nicht ausreicht oder besser mit noch anderen 
Integern im Konzept passt, nimmt man z.B. 32-Bit – die 
Integerberechnungen (Multiplikationen und Divisionen) werden auf einem 
AVR höchstwahrscheinlich immer noch schneller als Floatberechnungen 
sein. Bei Addition und Subtraktion wird es auf jeden Fall so sein – wenn 
es ganz schnell gehen muss, kann man manche Multiplikationen oder 
Divisionen auch durch Bitverschiebung und/oder Addition ersetzen (z.B. 
2a+a=3a oder 4a+a=5a), diese Akrobatik ist in diesem Fall aber gar nicht 
nötig. Ferner kann man Wertebereiche auch an Zweierpotenzen ausrichten – 
z.B. wenn man Dezimationen mit ADCs machen möchte und es schnell gehen 
soll, braucht man dann am Ende nicht 'krumm' teilen, sondern verschiebt 
das Ergebnis um so viele Bitstellen wie nötig.

Schreibt man dagegen ein Programm für einen PC, sind Floatberechnungen 
manchmal die erste Wahl – bei Unity (schreiben eines Spiels) oder 
WPF-Anwendungen z.B. nimmt die grafische Oberfläche in userem Code von 
vorherein nur Doubles an, also sogar gleich in zweifacher Genauigkeit, 
weil das von der GPU der Grafikkarte eh alles schneller berechnet werden 
kann und beim Rendering, Skalierung oder Transformationen (z.B. Drehung 
von Objekten auf dem Bildschirm) die Integer nur Probleme verursachen 
würden bzw. völlig unbrauchbar wären. Falls man die Werte gerundet und 
in einfacher Form haben möchte, um sie beispielsweise als String in 
seiner ConfigDatei abspeichern zu können, kann man sie vorher für diesen 
Zweck entsprechend konvertieren – später beim Auslesen macht man es dann 
umgekehrt und bildet daraus wieder Doubles, damit die Objekte der Grafik 
es überhaupt annehmen können.

_________
> Daß da potentiell ein bisschen Drehwinkel des Potis kurz vor dem
> Anschlag verloren geht, sollte man verkraften können, das ist eh' alles
> analog und Potis vor allem sind nicht irrwitzig linear und genau schon
> gar nicht.

Die Randproblematik des Potis, die übrigens real ist, kann man auch ganz 
einfach lösen, indem man den Wertebereich etwas verschiebt, ausdehnt 
oder kürzt und anschließend mit einer oder zwei IF-Zeilen absichert. 
Dieser Feinarbeit oder Nachjustierung sollte man sich aber grundsätzlich 
erst danach widmen, also nachdem unsere Hauptroutinen das tun, was sie 
sollten, um nicht noch mehr Unbekannte ins Spiel zu bringen. Die Regel 
der Systematik ist ganz einfach: man macht den Code am Anfang extrem 
einfach und wenn dieser das tut, was er soll, baut man ihn weiter ein 
wenig aus und prüft wieder. Beim Debuggen von sehr merkwürdigen Fehlern 
so vorgehen: die verdächtigen Bereiche/Blöcke stupide Zeile für Zeile 
debuggen, also sich die Werte anschauen oder ausgeben lassen, denn 
irgendwo muss der Fehler bzw. müssen die falschen Werte ja auftauchen, 
manchmal ist der Fehler auch schon früher passiert, weil man einen 
Denkfehler gemacht hat, aber auch das sieht man bei dieser Art des 
Debuggens sofort. Und Leute: wir reden hier von 5-10 zeilen Code, um den 
Zonk dingfest zu machen! Bei ein paar Tausend Zeilen, wie bei mir oft 
der Fall ist, funktioniert das Prinzip des systematischen Debuggens aber 
genauso gut.

: Bearbeitet durch User
von Ob S. (Firma: 1984now) (observer)


Lesenswert?

Gregor J. schrieb:

> Harald K. schrieb:
>> Statt der float-Herumrechnerei könnte man auch einfach mal einen Blick
>> auf Zweierpotenzen werfen.
>
> Statt mit Float, rechnet man mit kleinstmöglichen Integern
[...]

Jetzt ist es endgültig sicher: Gregor J. ist eine KI. Die typischen 
Anzeichen waren ja schon länger da (ausschweifendes Werfen von 
Wattebällchen).

Aber hier hat es konkret auf auf das Posting von Harald geantwortet, 
dabei aber offenbart, das es von dem semantischen Inhalt des Postings 
rein garnichts verstanden hat.

Also: entweder KI oder menschliches semmeldummes Pförtnerkind. Da 
letztere aber normalerweise zu faul und zu dumm sind, solch 
ausschweifende Postings in fast fehlerfreiem Deutsch zu verfassen, 
bleibt nur: KI.

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
Noch kein Account? Hier anmelden.