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
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 | }
|
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.
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?
@loetkolben du müsstest mal sagen welche bibliotheken du verwendet hast wo kommt denn byte usw vor?
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 :-(
Es gibt übrigens gut funktionierenden Code von Peter Danegger. Müsste sich in der Codesammlung finden lassen.
>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
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.
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.
@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...
@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.
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 | }
|
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
@loetkolben du hast immernoch nicht gesagt welche header du einbindet poste daoch mal deinen kompletten code von angfang bis ende danke
> 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 :-)
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
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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.