Forum: Mikrocontroller und Digitale Elektronik Ein DS18b20 am ATMEGA32


von Wolfgang S. (Gast)


Lesenswert?

Hallo,
folgendes Problem:
Mit dem Programm unten lese ich die Temperatur aus dem ds18b20 aus.
Beispiel: PortB ( zeigt bei einem int-Typ die unteren 8 Bits an) Bits 
0,1,2 und 4 leuchten = 23 dezimal. Das Zimmerthermometer zeigt 23,2 Grad 
an. Wenn ich den Sensor und das Thermometer ungefähr gleichermassen 
erwärme, steigt an Port B auch der Wert an, fast genauso wie beim 
Thermometer. Beim Abkühlen (Fön) zeigt sich der gleiche Effekt.
An Port D zeigt sich nichts. Ich habe die Routine ds18b20_temperature... 
aus der Hilfe-Datei, nichts weiter beschrieben.
Kann es sein, dass diese Routine die Temperatur auf 8 Bits reduziert 
ausgibt? Mit einer Genauigkeit von 1 Grad (LSB wäre hier 1 Grad).

Was ich eigentlich haben will und erwarte, ist aber das vom DS18B20 
gelieferte 16-Bit Wort der Temperatur. Da ich nur einen Sensor 
verwende,ist kein ROM code array notwendig und die addr muss Null (0) 
sein, siehe Hilfe-Datei über den DS18B20.

Was mache ich falsch?

Eine Bitte: Ich verwende nur einen Sensor, bitte keine Vorschläge mit 
mehreren Sensoren und auch keine Displayzusätze.
Ich möchte das 16Bit-Wort der Temperatur nur in einer Variablen (hier 
z.B. wert) haben.

Ich bin über jede Anregung sehr dankbar!

........
........
// 1 Wire Bus initialization
// 1 Wire Data port: PORTA
// 1 Wire Data bit: 7
// Note: 1 Wire port settings are specified in the
// Project|Configure|C Compiler|Libraries|1 Wire menu.
w1_init();

ds18b20_init((0),15,35,DS18B20_12BIT_RES);

while (1)
      {
      // Place your code here
      int wert;
      wert=ds18b20_temperature(0);
      delay_ms(100);
      PORTB=wert;
      wert=wert/256;
      PORTD=wert;
      delay_ms(1000);
      }

von eProfi (Gast)


Lesenswert?

Beitrag "Re: DS18S20 - extended resolution bei Temperaturen um 0°C"

Dein Wert steht in temp12 (bzw. weiter unten alternativ berechnet t12) 
als 12-Bit-Wert.
Die entscheidenden Zeilen sind:
if(d[1]){temp12=63491+8*d[0]-((d[6]-1)&7);}
else    {temp12=    3+8*d[0]-((d[6]-1)&7);}

d[0] .. d[7] ist das Scratchpad.

Vergiss die anderen kilometerlangen Programme.

von Rodulf (Gast)


Lesenswert?


von Wolfgang (Gast)


Lesenswert?

Danke für die Antwort, eProfi !

Nur, ganz so gut habe ich Codevision nicht im Griff, wie füge ich die 
Zeilen ein ?

Danke im voraus !

von Wolfgang (Gast)


Lesenswert?

Evtl. habe ich nicht aufgeführt:

Es geht um die Programmierung mit Codevision und dem DS18B20.

Ich weiss nicht, ob der DS18B20 voll kompatibel mit dem DS1820 und 
DS18S20 ist !

von Krapao (Gast)


Lesenswert?

> Es geht um die Programmierung mit Codevision und dem DS18B20.

Doku zu CodevisionAVR

http://nubielab.com/online_help/codevisionavr/ds18b20functions.htm
>>> float ds18b20_temperature(unsigned char *addr)

d.h.

>>    int wert;
>>    wert=ds18b20_temperature(0);

ist ein Fail.

von Krapao (Gast)


Lesenswert?

>> Was ich eigentlich haben will und erwarte, ist aber das vom DS18B20
>> gelieferte 16-Bit Wort der Temperatur.

Dafür kannst du die Funktion ds18b20_read_spd() benutzen und die 8-Bit 
Werte temp_lsb und temp_msb aus der internen struct 
__ds18b20_scratch_pad; auslesen und in wert ablegen.

von Wolfgang (Gast)


Lesenswert?

Hallo Krapao,

vielen Dank für Deine Antwort!

Zu der Antwort um 17:27 Uhr:

1. In dieser Doku steht nicht mehr als in der original Codevision Hilfe.
2. float ds18b20_temperature..... funktioniert nicht (bei mir)
3. Den letzte Teil in der Antwort habe ich ja in meinem Programm, ich 
bekomme aber kein 16-Bit Wort zurück, was ja mein Problem ist.

Zu der letzen Antwort: Ich werde die Version mit dem Scratch pad 
versuchen.
Hatte dies erstmal nicht in Betracht, weil dies doch umfangreicher ist.
Ich dachte, es gibt eine kurze Lösung meines Problems.

Nochmals vielen Dank !

von eProfi (Gast)


Lesenswert?

Moment mal, es geht vielleicht doch ganz einfach:

> Doku zu CodevisionAVR
>
> http://nubielab.com/online_help/codevisionavr/ds18...
> >> float ds18b20_temperature(unsigned char *addr)
> d.h.
>
> >>    int wert;
> >>    wert=ds18b20_temperature(0);
>
> ist ein Fail.

Vielleicht doch nicht? Führt er eine automatische Typkonvertierung 
durch?

versuche mal folgendes:
    wert=10.0*ds18b20_temperature(0)+0.5;
oder
    wert=16.0*ds18b20_temperature(0)+0.5;

Wenn er meckert wg. nicht verträglichem Typ, schreibe
    wert=(int)(16.0*ds18b20_temperature(0)+0.5);


Wenn Du es mit dem Scratchpad versuchen willst (diesmal mit der 
alternativen Formel):

  t12=3+8*a[0]-((a[6]-1)&7);//alternative way of calculation
  if(a[1]){t12-=128*16;}    //correct by -128°

heißt bei Dir:
ds18b20_read_spd(0);
wert=3+8*__ds18b20_scratch_pad.temp_lsb-((__ds18b20_scratch_pad.res2-1)& 
7);
if(__ds18b20_scratch_pad.temp_msb){wert-=128*16;}

von Krapao (Gast)


Lesenswert?

> 1. In dieser Doku steht nicht mehr als in der original Codevision Hilfe.

Deine original Codevision Hilfe habe ich nicht. Du hattest geschrieben

>> Ich habe die Routine ds18b20_temperature...
>> aus der Hilfe-Datei, nichts weiter beschrieben.

daher habe ich eine, in meinen Augen ausreichende, Hilfeseite genannt.

> 2. float ds18b20_temperature..... funktioniert nicht (bei mir)

ds18b20_temperature() gibt die Temperatur als Gleitkommazahl zurück, 
der intern in der Funktion aus dem 16-Bit Messwert berechnet wird.

> 3. Den letzte Teil in der Antwort habe ich ja in meinem Programm, ich
> bekomme aber kein 16-Bit Wort zurück, was ja mein Problem ist.

Du wandelst den Rückgabewert der Funktion zwar implizit in eine 
Ganzzahl, aber diese Ganzzahl wert ist nicht der originale 16-Bit 
Wert.

Bei der Umwandlung einer Gleitkommazahl (float 20.3) in eine Ganzzahl 
(int 20) gehen dir aus Werte verloren!

Du kannst das berücksichtigen z.B. in dem du in wert das 10- oder 
100-fache der Temperatur speicherst
1
#define TEMP_FAKTOR 10f
2
  int wert = TEMP_FAKTOR * ds18b20_temperature(0);

und den TEMP_FAKTOR bei der Ausgabe/Anzeige berücksichtigst
1
  printf("Temperatur = %f", wert/TEMP_FAKTOR);

> Zu der letzen Antwort: Ich werde die Version mit dem Scratch pad
> versuchen.
> Hatte dies erstmal nicht in Betracht, weil dies doch umfangreicher ist.
> Ich dachte, es gibt eine kurze Lösung meines Problems.

Bei dem Problem an den orginalen 16-Bit Wert zukommen?
1
  // originaler 16-Bit Wert auslesen
2
  if ( ds18b20_read_spd(0) ) 
3
  {
4
    wert = __ds18b20_scratch_pad.temp_msb; 
5
    wert <<= 8;                   
6
    wert |= __ds18b20_scratch_pad.temp_lsb;
7
  } else
8
    wert = 0xFFFF; // Error

von eProfi (Gast)


Lesenswert?

Stimmt, der B-Typ gibt ja direkt 12 Bit aus, nur beim S muss man nach 
der einfachen Formel umrechnen.
Beim 1820 braucht man die ausführliche Formel, da er mit 2 Oszillatoren 
arbeitet und das CountPerC nicht konstant 16 ist.
NB: Der DS1820 (falsch beschriftet) von Pollin (180014) ist ein DS18S20.




> Du kannst das berücksichtigen z.B. in dem du in wert das 10-
> oder 100-fache der Temperatur speicherst
> #define TEMP_FAKTOR 10f
>  int wert = TEMP_FAKTOR * ds18b20_temperature(0);
>
> und den TEMP_FAKTOR bei der Ausgabe/Anzeige berücksichtigst
> printf("Temperatur = %f", wert/TEMP_FAKTOR);

Dann kannst Du auch gleich direkt ausgeben:
printf("Temperatur = %f", ds18b20_temperature(0));
Wozu erst * und dann / ?


>   } else
>   wert = 0xFFFF; // Error
Würde ich nicht machen, da FFFF das Ergebnis bei -0.0625°C  ist,
siehe Beitrag "Re: DS18S20 - extended resolution bei Temperaturen um 0°C"

von Krapao (Gast)


Lesenswert?

> Wozu erst * und dann / ?

Um ein Konzept zu zeigen, wie man eine Gleikommazahl in einer 
Ganzzahlvariablen unterbringen kann.

Ein anderes Konzept (an der Stelle des TO würde ich das nehmen) wäre, 
die Vorkommastellen im oberen Byte von wert unterbringen und die 
Nachkommastellen im unteren Byte.
1
uint16_t wert;
2
float tmp = ds18b20_temperature(0);
3
wert = tmp;      // Nachkomma abschneiden 
4
wert <<= 8;      // ins obere Byte
5
wert |= tmp*100; // 2 Stellen Nachkomma abschneiden und ins untere Byte

Mit der Ausgabe auf die beiden Ports, hat man dann quasi eine 
Binäranzeige einer Dezimalgleitkommazahl mit Vorkomma/Nachkomma auf 2x8 
LEDs (?).

> Würde ich nicht machen, da FFFF das Ergebnis bei -0.0625°C  ist,

D'accord. Der Errorwert war nur ein Bsp.

von Krapao (Gast)


Lesenswert?

Mist zu schnell abgeschickt...

wert |= (tmp*100)&0x00FF; // 2 Stellen Nachkomma abschneiden und ins 
untere Byte

von Wolfgang (Gast)


Lesenswert?

Hallo eProfi und Krapao  !

Ich habe die Möglichkeit genommen, die Temperatur mit der SPD (Scratch 
Pad) -Funktion auszulesen. Und das funktioniert super !!!!!!!!!!
Ich musste allerdings sehr viel herumprobieren und nachlesen, weil die 
Werte in einer Struktur abgelegt werden, und das Auslesen war nicht 
einfach (kannte die struct Funktion nicht).
Jetzt geht es, man kann sogar kontrollieren, ob temp_low und temp_high 
(Über-Untertemperturwerte) richtig übertragen worden sind.
Mit 4 Zeilen ist alles erledigt.
Nochmals vielen Dank! Ohne Eure Denkanstösse hätte ich das nicht 
hinbekommen!
Gruss, Wolfgang

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.