DS18B20 Problem

Gast #1783390
Lesenswert?

Hallo,

ich weiß, über die DS1820 wurde schon viel geschieben. Auch ich habe ein 
Problem mit der Ansteuerung. Ich verwende einen Mega32 mit externem 4MHZ 
Quarz.

Der DS18B20 hängt an PD6. An PD5 habe ich eine PWM laufen. (macht das 
was?)
Ich möchte einfach nur die Temperatur auslesen.
Ich verwende nicht den Power-Parasite-Mode.

Hier die Funktionen:
1
void bus_o()
2
{
3
  DDRD |= (1<<PD6);
4
}
5

6
void bus_i()
7
{
8
  DDRD &= ~(1<<PD6);
9
}
10

11
void bus_write(uint32_t a)
12
{
13
  char data[20];
14
  itoa(a, data, 2);
15
  char *s;
16
  s=data;
17

18
  while(*s != '\0')
19
  {
20
    if(*s == '1')
21
    {
22
      bus_o();
23
      _delay_us(14);
24
      bus_i();
25
      _delay_us(70);
26
    }
27

28
    if(*s == '0')
29
    {
30
      bus_o();
31
      _delay_us(100);
32
      bus_i();
33
      _delay_us(2);
34
    }
35

36
    s++;
37

38
    _delay_us(2);
39
  }
40
}
41

42
int bus_read(int anz_bits)
43
{
44
  int t;
45
  char T[20];
46
  int i = 0;
47

48
  while(i < anz_bits)
49
  {
50
    bus_o();
51
    _delay_us(1.1);
52
    bus_i();
53
    _delay_us(10);
54
    
55
    if((PIND & 0b01000000) == 0)
56
    {
57
      T[i] = 0;
58
    }
59

60
    if((PIND & 0b01000000) == 1)
61
    {
62
      T[i] = 1;
63
    }
64

65
    while((PIND & 0b01000000) == 0)
66
    {
67
    }
68

69
    _delay_us(2);
70

71
    i++;
72
  }
73

74
  t = atoi(T);
75

76
  return t;
77
}
78

79
void temperature_get()
80
{
81
  //this function reads the temperature from the DS1820
82

83
  bus_i();
84

85
  //init...
86
  _delay_ms(1);
87
  bus_o();
88
  _delay_us(480);
89
  bus_i();
90
  _delay_ms(1);
91

92
  bus_write(0xCC);   //Skip-ROM, da ich nur einen 1-wire-device habe...
93
  _delay_ms(1);
94
  bus_write(0x44);  //Convert T
95
  _delay_ms(1);
96
  
97
  temperature = bus_read(9);
98
}

Die Funktion "temperature_get()" wird alle 3 sec. aufgerufen. Die 
Variabel "temperature" ist eine globale int.
Leider bleibt der Wert von "temperature" immer bei 0
Was mache ich falsch?

Gruß

georg
Gast #1784479
Lesenswert?

Hallo,

ich habe das Programm nochmals neu überarbeitet und das kam dabei raus:
1
void bus_o()
2
{
3
  DDRD |= (1<<PD6);
4
}
5

6
void bus_i()
7
{
8
  DDRD &= ~(1<<PD6);
9
}
10

11
void write_bit(int b)
12
{
13
  if(b == 1)
14
  {
15
    bus_o();
16
    _delay_us(3);
17
    bus_i();
18
    _delay_us(110);
19
  }
20

21
  if(b == 0)
22
  {
23
    bus_o();
24
    _delay_us(110);
25
    bus_i();
26
  }
27

28
  _delay_us(2);
29
}
30

31
double read_bit()
32
{
33
  double b;
34

35
  bus_o();
36
  _delay_us(2);
37
  bus_i();
38
  _delay_us(10);
39

40
  b = (PIND & 0b01000000);
41

42
  _delay_us(110);
43

44
  return b;
45
}
46

47
void bus_write(uint32_t a, int anz_bits)
48
{
49
  int maske = 1;
50
  int i = 0;
51

52
  while(i != anz_bits)
53
  {
54
    write_bit(a & maske);
55
    maske = maske * 2;
56
    i++;
57
  }
58
}
59

60
int bus_read(int anz_bits)
61
{
62
  int i = 1;
63
  double t = 0;
64
  double x = 1;
65

66
  while(i != anz_bits)
67
  {
68
    t = t + (read_bit() * x);
69
    i++;
70
    x = x * 2;
71
  }
72

73
  return t;
74
}
75

76
void temperature_get()
77
{
78
  //this function reads the temperature from the DS18B20
79
  bus_i();
80

81
  //init...
82
  _delay_ms(1);
83
  bus_o();
84
  _delay_us(490);
85
  bus_i();
86

87
  bus_write(0xCC, 8); //skip ROM
88
  bus_write(0x44, 7); //T Convert
89
  
90
  temperature = bus_read(16);
91
}

Jeodch erhalte ich immer 192 als Temperatur zurück... Was mache ich 
falsch?
Kann man überhaupt die _delay_us() verwenden oder ist das zu ungenau?

Gruß

georg
#1784488
Lesenswert?

georg schrieb:
> double read_bit()

Du traust der CPU wohl nicht, also speicherst Du ein einzelnes Bit in 
einem 64bit-Float Wert.


4MHz ist schon recht knapp, da sollte man besser nur uint8_t als 
Variablen nehmen für den Hardwarezugriff.

Und extra Funktionen fürs Bitsetzen könnte auch zu teuer werden.
Entweder Inline oder als Macro.


Peter
Gast #1784502
Lesenswert?

Hallo,

Danke für den Hinweis!

ok, jetzt habe ich noch was verändert:
1
void write_bit(int b)
2
{
3
  if(b == 1)
4
  {
5
    DDRD |= (1<<PD6);
6
    _delay_us(3);
7
    DDRD &= ~(1<<PD6);
8
    _delay_us(110);
9
  }
10

11
  if(b == 0)
12
  {
13
    DDRD |= (1<<PD6);
14
    _delay_us(110);
15
    DDRD &= ~(1<<PD6);
16
  }
17

18
  _delay_us(2);
19
}
20

21
uint8_t read_bit()
22
{
23
  uint8_t b;
24

25
  DDRD |= (1<<PD6);
26
  _delay_us(2);
27
  DDRD &= ~(1<<PD6);
28
  _delay_us(10);
29

30
  b = (PIND & 0b01000000);
31

32
  _delay_us(110);
33

34
  return b;
35
}
36

37
void bus_write(uint32_t a, int anz_bits)
38
{
39
  int maske = 1;
40
  int i = 0;
41

42
  while(i != anz_bits)
43
  {
44
    write_bit(a & maske);
45
    maske = maske * 2;
46
    i++;
47
  }
48
}
49

50
int bus_read(int anz_bits)
51
{
52
  int i = 1;
53
  int t = 0;
54
  int x = 1;
55

56
  while(i != anz_bits)
57
  {
58
    t = t + (read_bit() * x);
59
    i++;
60
    x = x * 2;
61
  }
62

63
  return t;
64
}
65

66
void reset_bus()
67
{
68
  //init...
69
  _delay_ms(1);
70
  DDRD |= (1<<PD6);
71
  _delay_us(490);
72
  DDRD &= ~(1<<PD6);
73
}
74

75
void temperature_get()
76
{
77
  //this function reads the temperature from the DS18B20
78
  DDRD &= ~(1<<PD6);
79
  
80
  reset_bus();
81
  bus_write(0xCC, 8);
82
  bus_write(0x44, 7);
83
  _delay_ms(10);
84
  reset_bus();
85
  bus_write(0xCC, 8);
86
  bus_write(0xBE,8);
87
  
88
  temperature = bus_read(16);
89

90
  lcd_ausgabe(a);
91
}

Aber leider kommt weiterhin nur 192 als Temperatur zurück. Was mache ich 
denn sonst noch falsch? Ist wo ein Timing-Problem?

georg
Gast #1784891
Lesenswert?

Hallo,

ok, jetzt habe ich die read_bit Funktion so umgeändert:
1
uint8_t read_bit()
2
{
3
  uint8_t b;
4

5
  DDRD |= (1<<PD6);
6
  _delay_us(2);
7
  DDRD &= ~(1<<PD6);
8
  _delay_us(10);
9

10
  if((PIND & 0b01000000) == 0)
11
  b = 0;
12
  else
13
  b = 1;
14

15
  _delay_us(110);
16

17
  return b;
18
}

Jetzt erhalte ich aber als Temperatur immer 255 °C! Was nun?

georg
Gast #1784905
Lesenswert?

Hallo,

ok, habe mein write_bit jetzt so umgeändert:
1
void write_bit(uint8_t b)
2
{
3
  if(b == 0)
4
  {
5
    DDRD |= (1<<PD6);
6
    _delay_us(120);
7
    DDRD &= ~(1<<PD6);
8
  }
9
  else
10
  {
11
    DDRD |= (1<<PD6);
12
    _delay_us(2);
13
    DDRD &= ~(1<<PD6);
14
    _delay_us(120);
15
  }
16

17
  _delay_us(2);
18
}

Aber es geht immernoch nicht... was nun? :-(

georg
Gast #1784914
Lesenswert?

Hallo,

jetzt geht er!!! (jetzt ändert sich der Wert, wenn ich den DS18B20 
erwärme, aber die Werte stimmen nicht.)

Zuvor bei den Werten mit 336 z.B. blieb das konstant.

Seit ich bus_write(0x44, 7); in bus_write(0x44, 8); umgeändert habe, 
geht er... wieso das, frage ich mich???

Naja, mit "er geht" meine ich, dass ich endlich was auslesen kann. 
Jedoch zeigt er z.B. 168 an. Muss mal mit einem Termomenter vergleichen, 
aber ich glaube, das kommt nicht ganz hin.

was hat es denn beim DS18B20 mit der "THERMOMETER RESOLUTION 
CONFIGURATION" auf sich????

-georg

Danke für die Hilfe!
#1784924
Lesenswert?

georg schrieb:

> Naja, mit "er geht" meine ich, dass ich endlich was auslesen kann.
> Jedoch zeigt er z.B. 168 an. Muss mal mit einem Termomenter vergleichen,
> aber ich glaube, das kommt nicht ganz hin.

Ab und zu mal eine Nacht mit 168 wär jetzt nicht übel, aber auf Dauer 
doch etwas zu frisch für Juli. Die 336 gefielen mir besser (als 
Ergebnis).

> was hat es denn beim DS18B20 mit der "THERMOMETER RESOLUTION
> CONFIGURATION" auf sich????

Für den Anfang erstmal garnix. Kannst damit zwischen langsam/genau und 
schnell/ungenau wählen.
Gast #1784929
Lesenswert?

Hallo,

ah, ok, danke, aber wie bekomme ich da jetzt die korrekte Temperatur 
hin?
meine bus_read Funktion sieht jetzt so aus:
1
uint32_t bus_read(uint32_t anz_bits)
2
{
3
  uint16_t i = 1;
4
  uint16_t t = 0;
5
  uint8_t x = 1;
6

7
  while(i != anz_bits)
8
  {
9
    t = t + (read_bit() * x);
10
    i++;
11
    x = x * 2;
12
  }
13

14
  return t;
15
}

liegt da der Fehler?

georg
Gast #1784943
Lesenswert?

Hallo,

ok, wenn ich die bus_read Funktion so habe:
1
int bus_read(int anz_bits)
2
{
3
  int i = 1;
4
  int t = 0;
5
  int x = 1;
6

7
  while(i != anz_bits)
8
  {
9
    t = t + (read_bit() * x);
10
    i++;
11
    x = x * 2;
12
  }
13

14
  return t;
15
}
Dann kommt 1360, also 0x550. Als Temperatur zeigt er aber leider z.B. 
bei Raumtemperatur 433 an... Muss ich den das noch durch 16 teilen, weil 
im Datenblatt die Tabelle 2: (im Anhang...)

georg
Angehängte Dateien:
Gast #1784955
Lesenswert?

Cool, danke!

Jetzt zeigt er auch 26°C an!!! und mein analog-Tchibo Thermometer 
auch!!!
und, wenn ich den Finger drann halte, dann geht er auf ca. 30!!!

Scheint also zu gehen!! freu Und danke nochmals für die tolle Hilfe!

Eine Frage habe ich aber noch: Ich habe jetzt ja einen DS18 B 20 
drann. Darum muss ich auch die Temperatur noch durch 16 teilen. Wie ist 
das aber, wenn ich einen DS18 S 20 drann hab??? Durch 2????

georg

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren