Forum: Compiler & IDEs auflösung ds18s20


von Steffen K. (steffen3)


Lesenswert?

Hallo,

ich möchte die Auflösung des ds18s20 auf 0.5° steigern, noch feiner 
aufgelöst wäre schön muss aber nicht sein.
Bisher gebe ich die Temperatur nur ganzzahlig aus, indem ich folgenden 
Code verwende
1
int temperatur=data[0]/2;
2
uart_puts(itoa(temperatur,buffer,10));
alle meine bisherigen Ansätze führten dazu, dass der Speicherverbrauch 
von ca.20% auf 105% stieg, so bspw.
1
double t=data[0];
2
double temperatur=t/2;
3
uart_puts(dtostrf(temperatur,2,1,buffer));
Hat jemand eine Idee wie ich es schaffen könnte?
gruss steffen

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Gib die Temperatur in 1/10 Grad aus:
1
char buffer[10];
2
int temperatur=(int)data[0]*5;      // Temperatur in 1/10°C
3
uart_puts(itoa(temperatur,buffer,10));


Oder füge den Dezimalpunkt von Hand ein:
1
char buffer[10];
2
int temperatur=(int)data[0]*5; // Temperatur in 1/10°C
3
itoa(temperatur,buffer,10);
4
i=0;
5
while(i<9&&buffer[i]) i++;     // Stringende suchen
6
buffer[i+1]=0;
7
buffer[i]  =buffer[i-1]; // Nachkommastelle
8
buffer[i-1]='.';         // Dezimalpunkt
9
uart_puts(buffer);

von Karl H. (kbuchegg)


Lesenswert?

Steffen K. schrieb:

> Hat jemand eine Idee wie ich es schaffen könnte?

Warum so kompliziert über floating point?
Du kannst nur 2 mögliche Nachkommastellen haben: entweder .0 oder .5
1
  int temperatur=data[0]/2;
2
  uart_puts(itoa(temperatur,buffer,10));
3
4
  if( data[0] % 2 ==  0 )
5
    uart_puts( ".0" );
6
  else
7
    uart_puts( ".5" );

manchmal ist es besser, vorhandenes Wissen auszunutzen, anstatt lange 
rumzurechnen :-)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Die Idee mit dem LSB ist gut, ich hätte das aber so geschrieben:
1
  int temperatur=data[0]/2;
2
  uart_puts(itoa(temperatur,buffer,10));
3
4
  uart_puts(data[0]&1?".5":".0");
Liest sich irgendwie kopiergeschützt  ;-)

BTW:
Macht der Compiler aus %2 ein &1?

von Karl H. (kbuchegg)


Lesenswert?

Lothar Miller schrieb:

> Liest sich irgendwie kopiergeschützt  ;-)

:-)

> Macht der Compiler aus %2 ein &1?

Wenn er das nicht hinkriegt, sollte sich der Compilerbauer lieber ein 
anderes Hobby suchen. zb. Holzschnitzen :-)

von (prx) A. K. (prx)


Lesenswert?

So simpel ist das wahrlich nicht. In diesem Fall lässt sich das nur 
deshalb direkt mit &1 abwickeln, weil die Daten wahrscheinlich aus einem 
uchar stammen und zumindest GCC deshalb spitz kriegt, dass er negative 
Werte nicht berücksichtigen muss.

Denn formell ist das trotzdem eine Division mit Vorzeichen und nicht 
jeder Compiler kriegt das spitz. Andere optimieren zwar die Division 
raus, aber die Ersatzsequenz ist deutlich komplexer als AND.

Denn -3 % 2 = -1, aber -3 & 1 = 1.

von Karl H. (kbuchegg)


Lesenswert?

A. K. schrieb:
> So simpel ist das wahrlich nicht. In diesem Fall lässt sich das nur
> deshalb direkt mit &1 abwickeln, weil die Daten wahrscheinlich aus einem
> uchar stammen und zumindest GCC deshalb spitz kriegt, dass er negative
> Werte nicht berücksichtigen muss.
>
> Denn formell ist das trotzdem eine Division mit Vorzeichen und nicht
> jeder Compiler kriegt das spitz. Andere optimieren zwar die Division
> raus, aber die Ersatzsequenz ist deutlich komplexer als AND.
>
> Denn -3 % 2 = -1, aber -3 & 1 = 1.

Und beides ist nicht gleich 0
Und nur darum geht es letztendlich in dieser Abfrage. Und das kriegen 
auch die Optimizer raus.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Interessant wird die Berechnung zudem bei negativen Temperaturen (aber 
da is ja noch ein halbes Jahr hin ;-)

 0,5°C = 0x0001
   0°C = 0x0000
-0,5°C = 0xffff

Und das heißt: bei -0,5°C wird erst mal -1 ausgegeben (sofern die 
Übertragung aus data[0] nach temperatur erst mal vorzeichenrichtig 
korrigiert ist), danach wird (weil das LSB gesetzt ist) noch .5 
angehängt...
Daher wird eher die gefühlte als die gemessene Temperatur ausgegeben.

von (prx) A. K. (prx)


Lesenswert?

1
extern unsigned char data[];
2
3
int f(void)
4
{
5
    if (data[0] % 2)
6
        return 2;
7
    return 1;
8
}
9
10
int g(void)
11
{
12
    if (data[0] & 1)
13
        return 2;
14
    return 1;
15
}

läuft bei Digital Mars beispielsweise darauf raus:
1
_f              xor     EAX,EAX
2
                mov     AL,_data
3
                cdq
4
                xor     EAX,EDX
5
                and     EAX,1
6
                add     EDX,EAX
7
                cmp     EDX,1
8
                sbb     EAX,EAX
9
                add     EAX,2
10
                ret
11
12
_g              test    byte ptr _data,1
13
                mov     EAX,2
14
                jne     LF
15
                dec     EAX
16
                ret

von (prx) A. K. (prx)


Lesenswert?

Lothar Miller schrieb:

> Daher wird eher die gefühlte als die gemessene Temperatur ausgegeben.

Lustig kann es allerdings werden, wenn man höher als 0.5° auflösen will, 
das geradeaus mit / und % bastelt und nicht an solche Effekte denkt. 
Also /10 vor und %10 nach dem Komma. Gibt dann so illustre Temperaturen 
wie "0.-3°C".

von Karl H. (kbuchegg)


Lesenswert?

A. K. schrieb:
> Lothar Miller schrieb:
>
>> Daher wird eher die gefühlte als die gemessene Temperatur ausgegeben.
>
> Lustig kann es allerdings werden, wenn man höher als 0.5° auflösen will,
> das geradeaus mit / und % bastelt und nicht an solche Effekte denkt.
> Also /10 vor und %10 nach dem Komma. Gibt dann so illustre Temperaturen
> wie "0.-3°C".

LOL. Ja da ist was drann :-)

Wenns allerdings bei mir in der Wohnung 0.-3 Grad hat, dann ist die 
Anzeige mein geringstes Problem :-)

von Steffen K. (steffen3)


Lesenswert?

Hallo,
danke für die guten Vorschläge. Ich gebe die Temperatur jetzt mit einer 
Auflösung von 0.5° aus, indem ich überprüfe ob das LSB "1" oder "0" ist, 
das reicht mir doch aus für die Anwendung als normales Raumthermometer.

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.