Forum: Mikrocontroller und Digitale Elektronik Hilfe DS1820 und DS18b20 in c


von Holger W. (mb_holger)


Lesenswert?

Hallo,
ich brauche Hilfe.

Ich habe folgenden c code. Im Projekt funktioniert alles bis auf die 
Ausgabe der Temperatur, die zeigt falsche Werte an. zb. bei 13 grad 
werden 104 grad ausgegeben oder bei 16 grad werden -115 ausgegeben.

Der c code ist für einen DS 1820 gemacht, leider habe ich aber DS 18B20.
Das wird der Fehler sein. Das mit den 1-Wire Bus habe ich alles soweit 
verstanden, aber bei der Funktion auslesen scheitere ich. Mit den 
Hinweisen im Netz komme ich nicht weiter.

Meine Kenntnisse reichen hier nicht, bisher habe ich alles analog 
eingelesen. Ich bitte um einen Hinweis für die Änderung des Codes.
1
//#################################################################################
2
//#################################################################################
3
//#################################################################################
4
/*  Library to use ds18x20 with ATMEL Atmega family.
5
  For short ds18x20 wires there is no need for an external pullup resistor.
6
  If the wire length exceeds one meter you should use a 4.7k pullup resistor 
7
  on the data line. This library does not work for parasite power. 
8
  You can just use one ds18x20 per Atmega Pin.
9
  
10
  Copyright (C) 2010 Stefan Sicklinger
11
12
  For support check out http://www.sicklinger.com
13
    
14
  This library is free software: you can redistribute it and/or modify
15
    it under the terms of the GNU General Public License as published by
16
    the Free Software Foundation, either version 3 of the License, or
17
    (at your option) any later version.
18
19
    This program is distributed in the hope that it will be useful,
20
    but WITHOUT ANY WARRANTY; without even the implied warranty of
21
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
    GNU General Public License for more details.
23
24
    You should have received a copy of the GNU General Public License
25
    along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
26
//#################################################################################
27
//#################################################################################
28
//#################################################################################
29
30
#include "ds18x20lib.h"
31
32
33
//----------------------------------------
34
// Reset DS18S20
35
//----------------------------------------
36
uint8_t ds1820_reset(uint8_t used_pin)
37
{
38
  uint8_t err=100;
39
  DS1820_DDR |= 1<<used_pin;            // define as ouput
40
  DS1820_PORT &= ~(1<<used_pin);          //Pull low
41
  delay_us(480);        ;          // 480 us
42
  DS1820_DDR &= ~(1<<used_pin);            // define as input
43
  DS1820_PORT |= 1<<used_pin;            //Pullup on
44
  delay_us(66);                    // 66 us
45
  err = (DS1820_PIN & (1<<used_pin)) >> used_pin;  // no presence detect --> err=1 otherwise err=0
46
  delay_us(240);                  // 240 us
47
  if( (DS1820_PIN & (1<<used_pin)) == 0 ){      // short circuit --> err=2
48
    err = 2;
49
  }
50
  return err;
51
}
52
//-----------------------------------------
53
// Write one bit to DS18S20
54
//-----------------------------------------
55
void ds1820_wr_bit(uint8_t wrbit,uint8_t used_pin)
56
{
57
  if (wrbit ==0)  {
58
    DS1820_DDR |= 1<<used_pin;          // define as ouput
59
      DS1820_PORT &= ~(1<<used_pin);        //Pull low
60
    delay_us(60);
61
    DS1820_DDR &= ~(1<<used_pin);        // define as input
62
      DS1820_PORT |= 1<<used_pin;          //Pullup on
63
    delay_us(4);
64
  }
65
  if (wrbit ==1)  {
66
    DS1820_DDR |= 1<<used_pin;          // define as ouput
67
      DS1820_PORT &= ~(1<<used_pin);        //Pull low
68
    delay_us(10);
69
    DS1820_DDR &= ~(1<<used_pin);        // define as input
70
      DS1820_PORT |= 1<<used_pin;          //Pullup on
71
    delay_us(54);
72
  }
73
}
74
//-----------------------------------------
75
// Read one bit from DS18S20
76
//-----------------------------------------
77
uint8_t ds1820_re_bit(uint8_t used_pin)
78
{
79
  uint8_t rebit;
80
  DS1820_DDR |= 1<<used_pin;              // define as ouput
81
    DS1820_PORT &= ~(1<<used_pin);            //Pull low
82
  delay_us(1);
83
  DS1820_DDR &= ~(1<<used_pin);            // define as input
84
  DS1820_PORT |= 1<<used_pin;              //Pullup on
85
  delay_us(10);
86
  rebit = (DS1820_PIN & (1<<used_pin)) >> used_pin;   //Read bit
87
  delay_us(50);
88
  return rebit;                
89
}
90
//-----------------------------------------
91
// Read 1 byte from DS18S20
92
//-----------------------------------------
93
uint8_t ds1820_re_byte(uint8_t used_pin)
94
{
95
  uint8_t rebyte =0x00;
96
  uint8_t rebit;
97
  uint8_t i;
98
99
  for (i=0;i<8;i++)
100
  {
101
    rebit=ds1820_re_bit(used_pin);
102
    //delay_us(2);                  //be on the save side
103
    if (rebit==1){
104
      rebyte|=(1<<i);
105
    }
106
  }
107
  return(rebyte);
108
}
109
//-----------------------------------------
110
// Write 1 byte to DS18S20
111
//-----------------------------------------
112
void ds1820_wr_byte(uint8_t wrbyte,uint8_t used_pin)
113
{
114
  uint8_t i;
115
  for (i=0; i<8; i++) // writes byte, one bit at a time
116
  {      
117
    ds1820_wr_bit((wrbyte & 0b00000001),used_pin);
118
    wrbyte = wrbyte >> 1;
119
  }
120
  delay_us(5);
121
}
122
//-----------------------------------------
123
// Read temperature
124
//-----------------------------------------
125
float  ds1820_read_temp(uint8_t used_pin)  
126
{
127
  uint8_t error,i;
128
  uint16_t j=0;
129
    uint8_t scratchpad[9];
130
  float temp=0;
131
  scratchpad[0]=0;
132
  scratchpad[1]=0;
133
  scratchpad[2]=0;
134
  scratchpad[3]=0;
135
  scratchpad[4]=0;
136
  scratchpad[5]=0;
137
  scratchpad[6]=0;
138
  scratchpad[7]=0;
139
  scratchpad[8]=0;
140
  error=ds1820_reset(used_pin);                  //1. Reset
141
  if (error==0){
142
      ds1820_wr_byte(0xCC,used_pin);                //2. skip ROM
143
      ds1820_wr_byte(0x44,used_pin);                //3. ask for temperature conversion
144
      while (ds1820_re_byte(used_pin)==0xFF && j<1000){      //4. wait until conversion is finished 
145
      _delay_us(1);
146
      j++;
147
    }                   
148
      error=ds1820_reset(used_pin);                //5. Reset
149
      ds1820_wr_byte(0xCC,used_pin);                //6. skip ROM
150
      ds1820_wr_byte(0xBE,used_pin);                //7. Read entire scratchpad 9 bytes
151
    
152
      for (i=0; i<9; i++)                       //8. Get scratchpad byte by byte
153
      {
154
         scratchpad[i]=ds1820_re_byte(used_pin);           //9. read one DS18S20 byte
155
      }
156
  }
157
  if(scratchpad[1]==0x00 && scratchpad[7]!=0){          //Value pos.
158
    scratchpad[0]=scratchpad[0] >> 1;
159
    temp=(scratchpad[0]-0.25f+(((float)scratchpad[7]-(float)scratchpad[6])/(float)scratchpad[7]));
160
    temp = (floor(temp*10.0+0.5)/10);              //Round value .x
161
162
  }
163
  if(scratchpad[1]!=0x00){                    //Value negative
164
    uint8_t tmp;
165
    tmp =scratchpad[0];                      //Save Kommabit
166
    tmp= ~ tmp;
167
    tmp= tmp >> 1;
168
    temp = (-1)*(tmp+1);
169
    if ((scratchpad[0]&0b00000001)==1){
170
      temp=temp+0.5;
171
    }
172
173
  }
174
175
  return temp;
176
}
177
//-----------------------------------------
178
// Initialize DS18S20
179
//-----------------------------------------
180
void  ds1820_init(uint8_t used_pin)  
181
{
182
  uint8_t error;
183
  uint16_t i =0;
184
  error=ds1820_reset(used_pin);                  //1. Reset
185
  if (error==0){
186
      ds1820_wr_byte(0xCC,used_pin);                //2. skip ROM
187
      ds1820_wr_byte(0x44,used_pin);                //3. ask for temperature conversion
188
      while (ds1820_re_byte(used_pin)==0xFF && i<1000){      //4. wait until conversion is finished 
189
      _delay_us(1);
190
      i++;
191
    }
192
    error=ds1820_reset(used_pin);                //5. Reset
193
      ds1820_wr_byte(0xCC,used_pin);                //6. skip ROM
194
      ds1820_wr_byte(0xBE,used_pin);                //7. Read entire scratchpad 9 bytes
195
    }
196
    
197
     
198
}

von Holger W. (mb_holger)


Lesenswert?

Ich noch mal.

Ich verstehe auch die Funktion nicht.
Meine Bitte: ist es möglich, dass mir ein Fachmann die Funktion anpasst?
Ich werde mich mit dieser Materie auch tiefer beschäftigen, aber im 
Moment fehlen mir meine Kenntnisse dafür.
vielen Dank.
1
// Read temperature
2
//-----------------------------------------
3
float  ds1820_read_temp(uint8_t used_pin)  
4
{
5
  uint8_t error,i;
6
  uint16_t j=0;
7
    uint8_t scratchpad[9];
8
  float temp=0;
9
  scratchpad[0]=0;
10
  scratchpad[1]=0;
11
  scratchpad[2]=0;
12
  scratchpad[3]=0;
13
  scratchpad[4]=0;
14
  scratchpad[5]=0;
15
  scratchpad[6]=0;
16
  scratchpad[7]=0;
17
  scratchpad[8]=0;
18
  error=ds1820_reset(used_pin);                  //1. Reset
19
  if (error==0){
20
      ds1820_wr_byte(0xCC,used_pin);                //2. skip ROM
21
      ds1820_wr_byte(0x44,used_pin);                //3. ask for temperature conversion
22
      while (ds1820_re_byte(used_pin)==0xFF && j<1000){      //4. wait until conversion is finished 
23
      _delay_us(1);
24
      j++;
25
    }                   
26
      error=ds1820_reset(used_pin);                //5. Reset
27
      ds1820_wr_byte(0xCC,used_pin);                //6. skip ROM
28
      ds1820_wr_byte(0xBE,used_pin);                //7. Read entire scratchpad 9 bytes
29
    
30
      for (i=0; i<9; i++)                       //8. Get scratchpad byte by byte
31
      {
32
         scratchpad[i]=ds1820_re_byte(used_pin);           //9. read one DS18S20 byte
33
      }
34
  }
35
  if(scratchpad[1]==0x00 && scratchpad[7]!=0){          //Value pos.
36
    scratchpad[0]=scratchpad[0] >> 1;
37
    temp=(scratchpad[0]-0.25f+(((float)scratchpad[7]-(float)scratchpad[6])/(float)scratchpad[7]));
38
    temp = (floor(temp*10.0+0.5)/10);              //Round value .x
39
40
  }
41
  if(scratchpad[1]!=0x00){                    //Value negative
42
    uint8_t tmp;
43
    tmp =scratchpad[0];                      //Save Kommabit
44
    tmp= ~ tmp;
45
    tmp= tmp >> 1;
46
    temp = (-1)*(tmp+1);
47
    if ((scratchpad[0]&0b00000001)==1){
48
      temp=temp+0.5;
49
    }
50
51
  }
52
53
  return temp;
54
}
55
//-----------------------------------------
56
// Initialize DS18S20
57
//-----------------------------------------
58
void  ds1820_init(uint8_t used_pin)  
59
{
60
  uint8_t error;
61
  uint16_t i =0;
62
  error=ds1820_reset(used_pin);                  //1. Reset
63
  if (error==0){
64
      ds1820_wr_byte(0xCC,used_pin);                //2. skip ROM
65
      ds1820_wr_byte(0x44,used_pin);                //3. ask for temperature conversion
66
      while (ds1820_re_byte(used_pin)==0xFF && i<1000){      //4. wait until conversion is finished 
67
      _delay_us(1);
68
      i++;
69
    }
70
    error=ds1820_reset(used_pin);                //5. Reset
71
      ds1820_wr_byte(0xCC,used_pin);                //6. skip ROM
72
      ds1820_wr_byte(0xBE,used_pin);                //7. Read entire scratchpad 9 bytes
73
    }

von Holger W. (mb_holger)


Lesenswert?

Was die Variable scratchpad macht verstehe ich. Ich dachte der Sensor 
sendet einfach die Temperatur als byte an den avr und gut.
vielen Dank Holger

von Falk B. (falk)


Lesenswert?

@Holger Weiß (mb_holger)

>Ich verstehe auch die Funktion nicht.
>Meine Bitte: ist es möglich, dass mir ein Fachmann die Funktion anpasst?

Die gibt es schon schön und fertig.

Beitrag "Onewire + DS18x20 Library"

"The DS18S20 was designed to be a drop-in replacement for the original 
DS1820."

Das Auslesen und verarbeiten der Temperatur im 9 Bit Format ist schon 
geradezu trivial.
1
uint8_t ds18S20_read_temp(int16_t *temperature) {
2
    int16_t temp;
3
    uint8_t scratchpad[9];
4
    
5
    ds18x20_read_scratchpad(scratchpad);
6
    if (onewire_crc(scratchpad, 9)) {
7
        return ONEWIRE_CRC_ERROR;
8
    }
9
10
    temp = ((int16_t)scratchpad[1] << 8) | scratchpad[0];
11
    *temperature = 5*temp;  // temperature in 1/10 C
12
    return ONEWIRE_OK;
13
}

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.