Forum: Mikrocontroller und Digitale Elektronik Ds18S20 schickt nur 1er über 1-wire Bussystem - Verständnisproblem


von F. S. (de0_board)


Lesenswert?

Hallo Forumsgemeinde,

ich bin noch nicht so viel Erfahrung in Embedded Systems. Ich versuche 
gerade ein kleines Projekt zu schreiben, wo ich einen Dallas DS18S20 
über das 1-wire Bussystem die Temperatur auszulesen und sie über UART 
auszugeben.

Ich habe folgenden Code:

main.c:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
5
#include <stdio.h>
6
7
#include "UART.h"
8
#include "1wire.h"
9
10
11
int main(void)
12
{
13
    DDRC=0xFF;
14
    PORTC=0xFF;
15
    USART_Init(103);
16
17
    sei();
18
    rs232_printf("Test 1\n");
19
    rs232_printf("Reset: %d\n", OWTouchReset());  //gibt 0 zurück
20
    rs232_printf("Test 2\n");
21
22
    while(1)
23
    {
24
        rs232_printf("Endwert: %d\n",OWReadByte());  //ganzes Byte auslesen
25
      _delay_ms(1500);
26
  }
27
    return 0;
28
}

1wire.c:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
5
#include <stdio.h>
6
7
#include "UART.h"
8
#include "1wire.h"
9
10
//-----------------------------------------------------------------------------
11
// Generate a 1-Wire reset, return 1 if no presence detect was found,
12
// return 0 otherwise.
13
// (NOTE: Does not handle alarm presence from DS2404/DS1994)
14
//
15
int OWTouchReset(void)
16
{
17
    int result;
18
19
    _delay_us(0);
20
    DDRD&=(0<<PD6);         // Drives DQ low
21
    PORTD=0x0;
22
    _delay_us(480);
23
    DDRD&=(1<<PD6);         // Drives DQ high
24
    PORTD=0b01000000;
25
    _delay_us(70);
26
    DDRD&=(0<<PD6);         // Drives DQ low
27
    PORTD=0x0;
28
    result=(PIND&0b01000000);
29
    DDRD&=(1<<PD6);         // Drives DQ high
30
    PORTD=0b01000000;
31
    _delay_us(410);
32
    return result; // Return sample presence pulse result
33
}
34
35
//-----------------------------------------------------------------------------
36
// Read a bit from the 1-Wire bus and return it. Provide 10us recovery time.
37
//
38
int OWReadBit(void)
39
{
40
    int result;
41
42
    DDRD&=(0<<PD6);         // Drives DQ low
43
    PORTD=0x0;              //hier muss ich PORTD eh auf 0 setzen, oder?
44
    _delay_us(15);
45
    DDRD|=(1<<PD6);
46
    PORTD=0b01000000;
47
    _delay_us(12);
48
    result=(PIND&0b01000000)>>6;
49
    rs232_printf("result = %d\n",result);
50
    _delay_us(55);
51
52
    return result;
53
}
54
55
//-----------------------------------------------------------------------------
56
// Read 1-Wire data byte and return it
57
//
58
int OWReadByte(void)
59
{
60
    volatile int loop, result=0,zwischen=0;
61
62
    for (loop = 0; loop < 8; loop++)
63
    {
64
        zwischen=OWReadBit();
65
        //rs232_printf("%d\n", zwischen);
66
        result=result|(zwischen<<loop);
67
    }
68
    rs232_printf("gesendet\n");
69
    return result;
70
}

Ich empfange nur 1er. Ich versuche mich an diese Webseite mit den Zeiten 
zu orientieren:

http://www.maximintegrated.com/app-notes/index.mvp/id/126

Hab auch die Funktionen daraus entnommen. Alles wird über PIN 6 
gesteuert.

Kann mir bitte einer sagen was ich da falsch mache? Irgendwie habe ich 
das Gefühl, dass ich das nicht richtig verstehe.

Liebe Grüße,
DE0_Board

von Osterhasi (Gast)


Lesenswert?

F. S. schrieb:
> Kann mir bitte einer sagen was ich da falsch mache? Irgendwie habe ich
> das Gefühl, dass ich das nicht richtig verstehe.

Der Sensor weiß ja garnicht, was Du von ihm willst.
Wenn ich Dir keine Frage stelle und dann von Dir eine Antwort haben 
will, bekomme ich auch nur "Stille".

von F. S. (de0_board)


Lesenswert?

Osterhasi schrieb:
> Der Sensor weiß ja garnicht, was Du von ihm willst.
> Wenn ich Dir keine Frage stelle und dann von Dir eine Antwort haben
> will, bekomme ich auch nur "Stille".

Hmm, ich verstehe nicht so ganz was Du meinst. Ich dachte, dass wenn ich 
den PIN auf Low und dann auf High beziehe mit dden entsprechenden 
Zeitverzögerungen dazwischen, ist dem Sensor gesagt, dass er mir einen 
Wert gegben soll, oder?
Ich hab gedacht, dass man durch die verzögerungszeiten und die 
Pegeländerung dem Sensot mitteilt WAS er tun soll...

von Karl H. (kbuchegg)


Lesenswert?

>     DDRD&=(0<<PD6);         // Drives DQ low
> ...
>     DDRD&=(1<<PD6);         // Drives DQ high


?

Sieh dir doch bitte mal an, wie andere 1-Wire Routinen programmieren. 
Wenn du sonst nichts findest, in der Codesammlung hier im Forum gibt es 
jede Menge Beiträge dazu.

int OWReadBit(void)
{
  ...
    rs232_printf("result = %d\n",result);
    _delay_us(55);
....

Bei 1-Wire hast du ein recht strenges Timing-Korsett, dass du nicht 
durcheinander bringen darfst. Ein printf, und dann noch dazu einer, der 
über USART ausgibt, hat da sicher nichts verloren und bringt dir alles 
durcheinander.

Aber das ist nicht dein einziges Problem, erst mal musst du absolut 
zuverlässig in der Lage seinen, einen Ausgangtspin in jede beliebige 
Lage zu bringen, die du benötigst. Sieh dir bei anderen Leuten an, wie 
die das alles machen, bzw. übernimm deren Code. Das ist keine Schande. 
Eine Schande wäre es nur, wenn man den Code einfach unbesehen übernimmt 
und sich nicht dafür interessiert, wie er funktioniert. Aber solange du 
den Code studierst und dir klar ist, wie und warum genau was im Code 
passiert, solange du also davon lernst, ist es keine Schande und es gibt 
keinen wirklichen Grund sich tagelang mit grundsätzlichen Problemen 
rumzuschlagen.

> ich bin noch nicht so viel Erfahrung in Embedded Systems.

Grundvoraussetzung, sozusagen der 'Kindergarten' der µC-Programmierung 
ist die Fähigkeit, ein Bit gezielt auf 1 bzw. auf 0 zu setzen. Dazu muss 
man die binären Operationen &, | und ~ (und, oder, nicht) verstehen. Das 
sind die absoluten Basisbausteine. Ohne sie kann man nicht 
µC-Programmieren.

Wenn ich sowas sehe
1
int OWTouchReset(void)
2
{
3
    int result;
4
5
    _delay_us(0);
6
    DDRD&=(0<<PD6);         // Drives DQ low
7
    PORTD=0x0;
8
    _delay_us(480);
9
    DDRD&=(1<<PD6);         // Drives DQ high
10
    PORTD=0b01000000;
11
    _delay_us(70);
12
    DDRD&=(0<<PD6);         // Drives DQ low
13
    PORTD=0x0;
14
    result=(PIND&0b01000000);
15
    DDRD&=(1<<PD6);         // Drives DQ high
16
    PORTD=0b01000000;
17
    _delay_us(410);
18
    return result; // Return sample presence pulse result
19
}

dann kann ich nur diagnostizieren: Du hast diese Operationen nicht 
verstanden und speziell in diesem Punkt einen großen Nachholbedarf.

von Karl H. (kbuchegg)


Lesenswert?

F. S. schrieb:
> Osterhasi schrieb:
>> Der Sensor weiß ja garnicht, was Du von ihm willst.
>> Wenn ich Dir keine Frage stelle und dann von Dir eine Antwort haben
>> will, bekomme ich auch nur "Stille".
>
> Hmm, ich verstehe nicht so ganz was Du meinst. Ich dachte, dass wenn ich
> den PIN auf Low und dann auf High beziehe mit dden entsprechenden
> Zeitverzögerungen dazwischen, ist dem Sensor gesagt, dass er mir einen
> Wert gegben soll, oder?

Nein.

> Ich hab gedacht, dass man durch die verzögerungszeiten und die
> Pegeländerung dem Sensot mitteilt WAS er tun soll...

Und noch ein Nein.
Lies das Datenblatt. Und studier anderer Leute Code (zb. alles von Peter 
Danegger kannst du getrost verwenden). Du wirst alles, was du im 
Datenblatt findest in diesem Code wieder finden. Aber tu es! Mit deinen 
Annahmen kommst du nicht weiter - die sind allesamt falsch.

von F. S. (de0_board)


Lesenswert?

Karl Heinz Buchegger schrieb:
>Du hast diese Operationen nicht
> verstanden und speziell in diesem Punkt einen großen Nachholbedarf.

Karl Heinz Buchegger schrieb:
> Mit deinen
> Annahmen kommst du nicht weiter - die sind allesamt falsch.

schon gut Karl Heinz...calm down! EINMAL sagen, reicht!

von Karl H. (kbuchegg)


Lesenswert?

F. S. schrieb:
> Karl Heinz Buchegger schrieb:
>>Du hast diese Operationen nicht
>> verstanden und speziell in diesem Punkt einen großen Nachholbedarf.
>
> Karl Heinz Buchegger schrieb:
>> Mit deinen
>> Annahmen kommst du nicht weiter - die sind allesamt falsch.
>
> schon gut Karl Heinz...calm down! EINMAL sagen, reicht!

Wieso?
Das sind 2 grundverschiedene Dinge.
Das eine ist die Basistechnik - das andere ist ihre Anwendung in einem 
spezifischen Kontext bzw. das Verständnis über Abläufe/Protokolle

von F. S. (de0_board)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Wieso?
> Das sind 2 grundverschiedene Dinge.
> Das eine ist die Basistechnik - das andere ist ihre Anwendung in einem
> spezifischen Kontext bzw. das Verständnis über Abläufe/Protokolle

jaja...danke dir!

von (prx) A. K. (prx)


Lesenswert?

F. S. schrieb:
> Hmm, ich verstehe nicht so ganz was Du meinst. Ich dachte, dass wenn ich
> den PIN auf Low und dann auf High beziehe mit dden entsprechenden
> Zeitverzögerungen dazwischen, ist dem Sensor gesagt, dass er mir einen
> Wert gegben soll, oder?

Mit Ausnahme der Messphase eines parasitär versorgten 18x20 zieht man 
einen 1-Wire Bus zu keinem Zeitpunkt aktiv auf 1, sondern überlässt das 
einem externen Widerstand. Wie sollte der arme schwache Sensor gegen den 
ziemlich kräftigen Treiber des Controllers anstinken und die Leitung auf 
0 ziehen können?

Ein solcher Pin wechselt also seitens des Programms nur zwischen 2 
Zuständen: aktiver Ausgang auf 0, oder inaktiver Eingang.

von F. S. (de0_board)


Angehängte Dateien:

Lesenswert?

Ich habe nun viele Beiträge gelesen und mir auch die Bibliothek vom 
Peter Dannegger hergeholt. Jedoch komme ich nicht an dem Problem mit den 
85° herum.
In einigen Beiträgen kann es dazu kommen, dass man zu wenig wartet und 
das man kwasi den Befehl des MATCH ROM zurüclbekommt, eben die 0x55.

Jedoch kann ich beim besten Willen nicht feststellen warum es nicht mehr 
funktioniert. Die Bibliothel reagiert wenn ich den Sensor herausnheme 
und schreibt mir dann "no sensor found". Ich habe probiert den DS1820 
über parasitär UND an einer externe Stromversorgung anzuschließen.

Es funktioniert nicht.

Ich habe den gesamten Code auch raufgeladen und erbitte nun erneut 
Hilfe. Ich habe wirklich probiert den Fehler zu finden, scheitere aber 
danach...

Einzige Veränderung die ich gemacht habe: Ich habe das DELAY durch das 
übliche _delay_us() ersetzt. Daruch muss ich den Timer nicht ansteuern.
Ich habe es auch mit einem Digitalen Oszilloskop gemessen, es kommen 
auch Zeiten vor die ich nie programmiert habe.

Danke an euch.

von (prx) A. K. (prx)


Lesenswert?

Sowas geht natürlich garnicht:
  if( (W1_IN & 1<< W1_PIN)==1 )
Nie in solche Bit-Tests auf ==1 testen, immer auf !=0.

von (prx) A. K. (prx)


Lesenswert?

Nach dem Reset muss für den Start der Messung entweder ein einzelner 
Sensor adressiert werden (MATCH ROM) oder alle zusammen (SKIP ROM). 
Andernfalls ignoriert der Sensor dich völlig.

von F. S. (de0_board)


Lesenswert?

Danke, jetzt funktioniert es :)

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.