Forum: Compiler & IDEs Hilfe zu DS18S20


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Marco M. (marco1987)


Lesenswert?

Ich frage jetzt einfach mal so vorne weg:


Ich brauche einen C Code für einen Temperaturfühler DS18S20.

Ich weisss, das das mehrfach hier diskutiert wurde nur ich möchte nichts 
über den Uart senden, keine extras einfach nur ein main programm, wo 
dieser Sensor ausgelesen wird.

Das Datenblatt habe ich schon gelesen nur steht da kein c code oder 
keine Anleitung zum genaueren Vorgehen.

Wenn man mir nur vllt eine Art Grundgerüst des Codes geben könnte oder 
einen guten Link, dann wäre ich sehr dankkbar

von loetkolben (Gast)


Lesenswert?

Welch Zufall, das versuch ich auch gerade:

Hier mein bisheriger Code (nur Vorhandensein feststellen).
Achtung meine Schaltung nutzt den Parasite-Power mode mit 2 Drähten zum 
Sensor.
1
// ds18s20 support (data line at PD4, parasite power from port)
2
static void DS1820_Init(void)
3
{
4
  PORTD= (byte)~(1u<<4); // activate internal pullups to avoid floating input pins but..
5
                    // not for the data line, have external pullup of 4.7k required for DS1820
6
7
  // DDRD is initial input (output only if we send or are strong pullup mode)
8
}
9
10
// reset, returns true if any 1-wire device present, false elsewhere
11
static bool DS1820_Reset(void)
12
{
13
  PORTD |= (1u<<4); // prepare by setting port to high
14
  DDRD  |= (1u<<4); // port now output
15
16
  PORTD &= ~(1u<<4); // setting port to low (reset impulse)
17
  _delay_us(500); // min 480 us 
18
  DDRD  &= ~(1u<<4); // port now input
19
20
  _delay_us(10); // 15-60 us until DS1820 pulls down the bus (and here the pullup resistor must bring the bus from low to high)
21
22
  // high detected check (sample some pulses to be independent of spikes)
23
  byte b;
24
  for (b= 0; b < 10; ++b) {
25
    if ((PIND & (1u<<4)) == 0) {
26
      TRACE("no high after reset (wire problem - no pullup)");
27
      return false;
28
    }
29
  }
30
31
  // now wait for the down pulse from DS1820 (typ 25 us, counter=15 with above wait of 10 us)
32
  for (b= 0; b < 60; ++b) {
33
    if ((PIND & (1u<<4)) == 0)
34
      break;
35
    _delay_us(1);
36
  }
37
  if (b==60) {
38
    TRACE("no down-pulse after reset (no DS1820 present)");
39
    return false;
40
  }
41
42
  // count the down pulse length
43
  for (b= 0; b < 255; ++b) {
44
    if ((PIND & (1u<<4)) != 0)
45
      break;
46
    _delay_us(1);
47
  }
48
49
  // test if length meets requirements (typ 80-82 us)
50
  if (b < 60 || b > 240) {
51
    TRACE("down pulse length wrong");
52
    return false;
53
  }
54
  return true;
55
}
56
57
int main(void)
58
{
59
  AVR_Init();
60
  LCD_Init();
61
  LCD_Start();
62
  LCD_Clear();
63
  DS1820_Init();
64
  for (;;) {
65
    if (DS1820_Reset())
66
      TRACE("ds1820");
67
    else
68
      TRACE("no ds1820");
69
    waitforKey();
70
    _delay_ms(100);
71
  }
72
}

von Andreas K. (a-k)


Lesenswert?

Den Portpin für 1-Wire Devices steuert man sinnvollerweise 
ausschliesslich als "Open-Collector" an. Das heisst bei AVRs: Man setzt 
PORTxy fest auf 0 und steuert den Pin ausschliesslich über die Richtung 
DDRxy. Für 0 schaltet man auf Ausgang, für 1 auf Eingang. Man vermeidet 
so, dass das 1-Wire-Device irgendwann gegen den Porttreiber arbeitet und 
dabei zweiter Sieger bleibt.

Einzige Ausnahme: Wenn der Messzyklus läuft und das Device parasitär 
versorgt wird, dann muss der Pin den Strom liefern. Aber auch nur dann.

von Marco M. (marco1987)


Lesenswert?

loetkolben wrote:
> Welch Zufall, das versuch ich auch gerade:
>
> Hier mein bisheriger Code (nur Vorhandensein feststellen).
> Achtung meine Schaltung nutzt den Parasite-Power mode mit 2 Drähten zum
> Sensor.
>

hey cool und dein code gehtbei dir?

von Marco M. (marco1987)


Lesenswert?

@loetkolben

du müsstest mal sagen welche bibliotheken du verwendet hast wo kommt 
denn byte usw vor?

von Marco M. (marco1987)


Lesenswert?

keiner mehr da?


hab meinen tempsensor jetzt an Vcc geschlossen, glaube der ist schon 
kaputt, denn er zeiht soviel Strom, dass das Netzteil in begrenzung (1 
A) geht :-(

von Andreas K. (a-k)


Lesenswert?

Q.E.D.

von Andreas K. (a-k)


Lesenswert?

Es gibt übrigens gut funktionierenden Code von Peter Danegger. Müsste 
sich in der Codesammlung finden lassen.

von Gerd G. (elektrikser)


Lesenswert?

>hab meinen tempsensor jetzt an Vcc geschlossen, glaube der ist schon
>kaputt, denn er zeiht soviel Strom, dass das Netzteil in begrenzung (1
>A) geht :-(

Falsch angeschlossen. Bei parasitär von zwei Möglichkeiten genau die 
verkehrte genommen.

Ein Beispiel gibt es bei Martin Thomas:
http://www.siwawi.arubi.uni-kl.de/avr_projects/tempsensor/index.html

von Sepp H. (seppl1)


Lesenswert?

Schaut mal bei avrfreaks.net vorbei. Dort gibt es eine 1-wire Bibliothek 
fix und fertig, die bei mir einwandfrei funktioniert.
http://www.avrfreaks.net/index.php?module=Freaks%20Files&func=viewFile&id=1172&showinfo=1

Wenn der Link nicht geht, nach dem Projekt "1wire" suchen. Dann kommen 
mehrere, das richtig Projekt ist vom 2004-09-02.

Noch ein Hinweis: ich habe mir mal notiert, dass in der Datei "1wire.c" 
in der Funktion "OWTouchReset()" eine Paus nicht richtig hast. Laut 
Datenblatt müsste vor dem Verlassen der Funktion eine Pause der "Länge" 
J (410us) statt I (70us) sein. Gegebenenfalls nochmal im Datenblatt 
überprüfen, aber so funktioniert die Bibliothek bei mir zuverlässig.

von Andreas K. (a-k)


Lesenswert?

Oder der Pintreiber vom Controller hat sich bei Versuch die Leitung auf 
1 zu ziehen gegenüber dem DS18S20 bei seinem Versuch sie auf 0 zu ziehen 
endgültig durchgesetzt.

Man sollte meinen, dass man den DS18S20 als TO92 parasitär kaum falsch 
anschliessen kann, denn eindeutiger geht es kaum.

von loetkolben (Gast)


Lesenswert?

@Marco,
das geht super, zu Deiner Frage:

aus einem common header,
1
// AVR: friendly typedef for a fundamental data type
2
// policy:
3
//   use byte, int, char for normal programming, 
4
//   but uint16_t etc for network data access (int etc may be > 16 bits on some procs)
5
typedef unsigned char byte;
6
typedef unsigned int uint;

Bitte jetzt keine Diskussion, manche bevorzugen die C99-Typen uintxx_t 
usw.

Und hier noch das Trace, gibt bei mir auf dem LCD die Texte aus, kannst 
Du erstmal auskommentieren:
1
#if 1
2
# define TRACE(x) Trace_LCD_P(PSTR(x))
3
#else
4
# define TRACE(x)
5
#endif

gruß,
jetzt geht es an die Daten...

von loetkolben (Gast)


Lesenswert?

@Andreas

Danke für den Tip bzgl. Portpin, werd ihn also nicht aktiv auf high 
setzen, außer wenns ans Parasite Power Strom liefern geht.

Ich wollte halt gleich mal den 1-wire modus nehmen, find es cool das man 
den mit zwei Drähten ansteuern kann.

von loetkolben (Gast)


Lesenswert?

Hier nun der aktuelle Stand, Lesen des EPROM codes geht.

Danke für die Tips, habe jetzt keinen aktiven Pullup.
War auch noch n' Fehler in DS1820_Reset(), da muß auch ein Timeslot nach
Melden des DS1820 eingehalten werden.

Display zeigt: 10 74 8a 6b 1 8 0 10 - crc ok

Freu ;-)
1
// ds18s20 support (data line at PD4, parasite power from port)
2
static void DS1820_Init(void)
3
{
4
  PORTD= (byte)~(1u<<4); // activate internal pullups to avoid floating input pins but..
5
                    // not for the data line, have external pullup of 4.7k required for DS1820
6
7
  // DDRD is initial input (output only if we send or are strong pullup mode)
8
}
9
10
11
// reset, returns true if any 1-wire device present, false elsewhere
12
static bool DS1820_Reset(void)
13
{
14
  PORTD &= (byte)~(1u<<4); // ensure low value, if we switch port to output (is this paranoia?)
15
16
  DDRD  |= (1u<<4); // port now output (reset impulse - low value)
17
18
  _delay_us(500); // min 480 us
19
20
  DDRD  &= ~(1u<<4); // port now input again
21
22
  _delay_us(10); // 15-60 us until DS1820 pulls down the bus (and here the pullup resistor must bring the bus from low to high)
23
24
  // high detected check (sample some pulses to be independent of spikes)
25
  byte b;
26
  for (b= 0; b < 10; ++b) {
27
    if ((PIND & (1u<<4)) == 0) {
28
      TRACE("no high after reset (wire problem - no pullup)");
29
      return false;
30
    }
31
  }
32
33
  // now wait for the down pulse from DS1820 (typ 25 us, counter=15 with above wait of 10 us)
34
  for (b= 0; b < 60; ++b) {
35
    if ((PIND & (1u<<4)) == 0)
36
      break;
37
    _delay_us(1);
38
  }
39
  if (b==60) {
40
    TRACE("no down-pulse after reset (no DS1820 present)");
41
    return false;
42
  }
43
44
  // count the down pulse length
45
  for (b= 0; b < 255; ++b) {
46
    if ((PIND & (1u<<4)) != 0)
47
      break;
48
    _delay_us(1);
49
  }
50
51
  // test if length meets requirements (typ 80-82 us)
52
  if (b < 60 || b > 240) {
53
    TRACE("down pulse length wrong");
54
    return false;
55
  }
56
57
  _delay_us(500); // reset time slot must be min 480 us
58
  return true;
59
}
60
61
// write "0" slot (every write slot must be min 60 us + 1 us recovery time)
62
static inline void DS1820_Write0(void)
63
{
64
  DDRD  |= (1u<<4); // port now output (low value)
65
  _delay_us(60); // min 60 us
66
  DDRD  &= ~(1u<<4); // port now input again
67
  _delay_us(2); // min 1 us, complete the time slot by recovery time
68
}
69
// write "1" slot
70
static inline void DS1820_Write1(void)
71
{
72
  DDRD  |= (1u<<4); // port now output (low value)
73
  _delay_us(2); // min >1 us
74
  DDRD  &= ~(1u<<4); // port now input again
75
  _delay_us(60); // min 60 us, complete the time slot by recovery time
76
}
77
// read bit "0/1" slot
78
static inline bool DS1820_Read(void)
79
{
80
  DDRD  |= (1u<<4); // port now output (low value)
81
  _delay_us(2); // min >1 us
82
  DDRD  &= ~(1u<<4); // port now input again
83
  _delay_us(10-2); // start sampling the bit, 10 us after initiating transfer
84
85
  // sample the line, 16 times
86
  byte h= 0;
87
  for (byte n= 0; n < 16; ++n) {
88
    if ((PIND & (1u<<4)) != 0)
89
      ++h;
90
  }
91
92
  _delay_us(60); // min 60 us, complete the time slot by recovery time
93
94
  // test is this a high or low ?
95
  if (h==0)
96
    return false;
97
  if (h==16)
98
    return true;
99
  TRACE("Read unsure!");
100
  return h > 8;
101
}
102
103
static void DS1820_WriteByte(byte b)
104
{
105
  for (byte n=0; n < 8; ++n) {
106
    if (b & 1)
107
      DS1820_Write1();
108
    else
109
      DS1820_Write0();
110
    b= b >> 1u;
111
  }
112
}
113
114
static byte DS1820_ReadByte(void)
115
{
116
  byte b= 0;
117
  for (byte n=0; n < 8; ++n) {
118
    b= b >> 1;
119
    if (DS1820_Read())
120
      b |= 0x80;
121
  }
122
  return b;
123
}
124
125
int main(void)
126
{
127
  AVR_Init();
128
  LCD_Init();
129
  LCD_Start();
130
  LCD_Clear();
131
  DS1820_Init();
132
  for (;;) {
133
    if (!DS1820_Reset())
134
      TRACE("no ds1820");
135
    DS1820_WriteByte(0x33); // read rom cmd
136
    byte romcode[8];
137
    for (byte n= 0; n < 8; ++n)
138
      romcode[n]= DS1820_ReadByte();
139
140
    Print_LCD("\n");
141
    for (byte n= 0; n < 8; ++n) {
142
      char buf[80];
143
      ultoa(romcode[n], buf, 16);
144
      Print_LCD(buf);
145
      Print_LCD(" ");
146
    }
147
148
    byte crc= 0;
149
    for (byte n= 0; n < 8; ++n)
150
      crc= _crc_ibutton_update(crc, romcode[n]);
151
    if (crc == 0)
152
      Print_LCD("- crc ok");
153
    else
154
      Print_LCD("crc fail:");
155
    
156
    waitforKey();
157
    _delay_ms(100);
158
  }
159
}

von Marco M. (marco1987)


Lesenswert?

Danke für die vielen Antowrten, wie gesgat ich bin mir eigentlich sicher 
das ich ncihts falsch angeschlossen habe ich denke eher das der code 
möglicherweise falsch war.

Also hab vcc an 5 V gnd halt an Gnd und Dq über pull up 4k7 dann wurde 
der sensor sehr heiss. Was ist wenn der datenport dauerhaft an 5 V liegt 
durch zb einem flaschen Code. kann er dann kaputt gehen?

Möglicherweise war er auch von anfang an defekt. naja jetzt darf ich mir 
erstmal einen neuen besorgen. welchen würdet ihr mir empfehlen den ds18S 
oder die B version?

MFG

von Marco M. (marco1987)


Lesenswert?

@loetkolben

du hast immernoch nicht gesagt welche header du einbindet poste daoch 
mal deinen kompletten code von angfang bis ende danke

von Marco L. (c-beginner)


Lesenswert?

> Ein Beispiel gibt es bei Martin Thomas:
> http://www.siwawi.arubi.uni-kl.de/avr_projects/tempsensor/index.html

Hallo zusammen,

bin neu im Forum und wollte mich mit einer Frage mal vorstellen.
Am Anfang gleich mein outing! In C bin ich eine Niete. Da ich es nun 
eingesehen habe, will ich es ändern. Also kleinere Projekte realisieren.

Umgebung:RNCONTROL 1.4 mit atmega32 bei 16Mhz
         avr-gcc
         Windows XP mit Hyper Terminal an RNCONTROL über MAX232

Arbeite gerade daran einen DS1820 mit dem Code von Martin Thomas 
anzusprechen. Es läuft alles prima, jedoch habe ich versucht den DQ des 
DS1820 auf Port D5 statt D6 mit "define OW_PIN  PD5" in der onewire.h zu 
ändern, ohne Erfolg. (Ursache für den Änderungswunsch ist vorhandene 
Hardware mit der Beschaltung auf PD5)
Wie passe ich den Port an?


Ein weiterer Punkt ist, dass ich mit dem Code eine Ausgabe im Hyper 
Terminal erhalte, die immer in der gleichen Zeile schreibt. Also kein CR 
LF durchführt. Warum ist das so?


Danke für die Hilfe :-)

von Gast^2 (Gast)


Lesenswert?

Moin,

bin im Moment am selben Thema. Ich mache das so:
1
//code
2
3
#define TIMESLOT   70
4
#define RESET_PULSE  480
5
6
//weiterer code
7
8
//-----------------------------------------------------------------------------
9
// Generate a 1-Wire reset, return 1 if no presence detect was found,
10
// return 0 otherwise.
11
// (NOTE: Does not handle alarm presence from DS2404/DS1994)
12
//
13
// Bus hängt am Pin PC3 
14
//
15
uint8_t OWTouchReset(void)
16
{
17
  uint8_t result;
18
19
  DDRC |= (1<<DDC3);   // Port-PIN als Ausgang konfigureren
20
  PORTC &= ~(1<<PC3); // Drives DQ low
21
  _delay_us(RESET_PULSE);
22
  
23
  PORTC |=  (1<<PC3); // Releases the bus
24
  _delay_us(TIMESLOT);
25
  
26
  DDRC &= ~(1<<DDC3);   // Port-PIN als Eingang konfigureren
27
  result = PINC & (1<<PC3); // Sample for presence pulse from slave
28
  _delay_us(RESET_PULSE-TIMESLOT);
29
  
30
  return result; // Return sample presence pulse result
31
}

aufgerufen wird das dann so:
1
i=OWTouchReset();

Gruß

Andreas

von Marco L. (c-beginner)


Lesenswert?

Hallo zusammen,

zum Thema Hyper Terminal und kein CR LF:

Im Hyper Terminal kann man unter Einstellungen/ASCII-Konfiguration den 
Punkt "Beim Empfang Zeilenvorschub am Zeilenende anhängen" aktivieren.
Dann klappt es auch mit dem CR LF.

Gruß

Marco L.

von Slevin (Gast)


Lesenswert?

Hallo,

ich habe ebenfalls den RN-Control Atmega32 @ 16MHz mit einem D18S20+ 
(normale Beschaltung mit Vdd, Code von Martin Thomas) und bei mir 
funktioniert das schon ganz gut.
Im Parasite-Modus gibt der µC konstante +85,0°C aus, kennt jemand eine 
Lösung dafür (Delay anpassen?).
Außerdem kann ich ebenfalls nicht den Port ändern (aktuell auf PD6 (am 
Input Capture Pin)), gibt es da eine Möglichkeit diesen zu ändern, z.B 
auf Port A?

MfG
Slevin

von Schlupp (Gast)


Lesenswert?

Schau mal Im Datenblatt nach... Dem Sensor geht während der 
Conwertierung der Saft aus, und somit gibt er nur den alten im 
Scratchpad gespeicherten Wert aus. Hierbei den Initialisierungswert. Das 
heißt du mußt während er convertiert den Datenport aus High setzen. 
Genaue Angaben findest du im Datenblat und Powermode.

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.