Forum: Mikrocontroller und Digitale Elektronik 1-Wire Reset Impuls?


von Yannic B. (yannic_b) Benutzerseite


Lesenswert?

Hi liebe Community,

ich bin grade am Verzweifeln... Ich hab mich mal ein bisschen in 
1-Wire-Bus eingelesen. Will jetzt mit nem ATMega8 (8MHz) den DS18S20 
Sensor auslesen... Also erstmal aufn nem Steckbrett den Sensor gesteckt, 
VCC auf 5V, GND auf Masse und DQ mit 4k7 gegen VCC. Die DQ Leitung geht 
bei mir an den PB1.
Wenn ich das richtig verstanden habe, sendet der Master (µC) eine 
logische 0 auf die DQ-Leitung wenn der PB1 für min 480µs auf 0 gesetzt 
ist. (Reset Impuls) Richtig? Da hab ich auch schon das erste Problem. 
Ich Schalte den PB1 zum Test für 1 Sekunde auf 0 und die Spannung am DQ 
Pin des Sensors fällt nur auf 4,19V ab und steigt dann wieder auf 5V 
(=VCC)... (Code siehe unten)
Liege ich richtig? Wie schalte ich die DQ auf Masse? Hab auch einen 2ten 
DS18S20 schon ausprobiert... Das gleiche Problem...
1
#include <stdlib.h>
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#define W1_PIN  PB1
5
#define W1_IN   PINB
6
#define W1_OUT  PORTB
7
#define W1_DDR  DDRB
8
int main(void)
9
{
10
  W1_DDR = 0xFF;
11
  W1_OUT = 0x20;
12
  _delay_ms(1000);
13
  W1_OUT = 0x30;
14
  
15
return 0;
16
}

von (prx) A. K. (prx)


Lesenswert?

Beim 1-Wire Protokoll ist es keine gute Idee, den Port irgendwann auf 1 
zu ziehen, denn es kann sein, dass der Sensor grad versucht, ihn auf 0 
zu ziehen. Das könnte der übel nehmen.

Andererseits hat dein Code keinerlei Ähnlichkeit mit der Beschreibung 
darüber und ich kann mir kaum vorstellen, dass der AVR nicht in der Lage 
sein sollte, bei einer 0 auf PB1 (Bitmaske 0x02) nicht gegen den 4K7 
Pullup anzustinken.

Ich würde empfehlen, die Lücken in der Kenntnis über die Art, wie man 
Portbits steuert, erst einmal zu schliessen, bevor du möglicherweise auf 
dem Weg dorthin eine Serie DS18S20 opferst. Geeignet dazu wäre 
beispielsweise das hiesige Tutorial.

von holger (Gast)


Lesenswert?

>Liege ich richtig? Wie schalte ich die DQ auf Masse?

Schalte das DDR Register und nicht das PORT Register.
Wenn du vom DS1820 was lesen möchtest darf der Pin
kein Ausgang sein.

von (prx) A. K. (prx)


Lesenswert?

Fortsetzung:

Man sollte den Zustand DDRx.DQ=1 und PORTx.DQ=1 stets vermeiden (hier 
auch nicht der Fall). Sondern PORTx.DQ=0 fixieren und nur zwischen 
Ausgang (low) und Eingang (high durch Pullup, ggf. low durch Sensor) 
umschalten.

Einzige Ausnahme davon ist die Messphase bei parasitärem Betrieb, aber 
das ist hier nicht der Fall und sollte erst in Angriff genommen werden, 
wenn man den Betrieb mit normaler Stromversorgung des Sensors 
beherrscht.

Ein "return" aus main() ist höchst selten sinnvoll. Was sollte der 
Controller da wohl machen?

von Unterstützer (Gast)


Angehängte Dateien:

Lesenswert?

Hier mal ne kleine Hilfestellung. Im Anhang siehst Du wie es aussehen 
sollte mit dem Resetimpuls.

 Sendet ein Resetimpuls von 480µs. Darauf hin sollte mind. ein Sensor
; sich bemerkbar machen mit einem Presence-Impuls.
; Der Presence-Impuls kann erst nach nach 60µs abgefragt werden.
; Eine optional angeschlossene LED leuchtet wenn kein Sensor
; angeschlossen ist oder ein Kabelbruch besteht.
; Danach wird der Bus durch den Pullup-Widerstand wieder frei gemacht 
(High-Signal).

.CSEG

wire_reset:

   cbi   wire_out, wire_pin
   sbi   wire_ddr, wire_pin
   rcall  wait480us
   cbi   wire_ddr, wire_pin
   ldi   temp, _60us
_wire:
   dec   temp
   brne  _wire
   sbic  wire_in, wire_pin
   cbi   wire_out, err_led
   sbis  wire_in, wire_pin
   sbi   wire_out, err_led
   rcall  wait480us
   sbis  wire_in, wire_pin
   cbi   wire_out, err_led
ret

von Yannic B. (yannic_b) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hi,

hab jetzt mal das PDF auf dem Artikel "Temperatursensor" 
(http://www.teslabs.com/openplayer/docs/docs/other/ds18b20_pre1.pdf) zur 
Hilfe genommen.
Es läuft gut... Nur ich bekomme immer 10,6250°C... Das ist nicht 
richtig.
Ich habe ja einen DS18S20 und kein DS18B20. Auch wenn die Abfrage der 
Werte in einer Dauerschleife sind, ändert sich der Wert nicht... Im PDF 
ist eine 12Bit Auflösung vom DS18B20 verwendet worden... Kann es damit 
zusammen hängen?

#define THERM_DECIMAL_STEPS_12BIT 625 //.625

Wie wäre denn der Wert für 9 Bit? Hab iwo 50 gelesen und probiert... 
10,500 °C war dann das Ergebnis.

Wäre euch dankbar. :)

VG

von Nico H. (nico84)


Lesenswert?

Das würde mich auch mal interessieren. Bei mir sieht das jetzt ganz 
genauso aus. Kann hier evtl. nochmal jemand schauen?

von Christopher G. (cbg)


Lesenswert?

Yannic B. schrieb:
> Ich habe ja einen DS18S20 und kein DS18B20.

Dann würd ich mal in das DS18S20 Datenblatt sehen. Das MS Byte ist 
einfach 8 Mal das signed Bit, das LS Byte geht von 2^-1 bis 2^6. 
therm_read_temperature(char*) in main.c wandelt also nicht in die 
korrekte Zahl um. Für eine Granularität kleiner 2^-1 muss man noch zwei 
weitere Register auswerten und das ganze in eine Formel stecken. Steht 
alles im Datenblatt.

von Nico H. (nico84)


Angehängte Dateien:

Lesenswert?

Aber das ist so soweit richtig? Theoretisch müsste ich doch dann nurnoch 
das Temperature MSB durch 2 Teilen und ausgeben? In dem Fall kommt bei 
mir 0 raus ;(

von Christopher G. (cbg)


Lesenswert?

Die ganzen Wartezeiten sind nicht ganz korrekt. In der Appnote von Atmel 
[1] stehen zum Teil ganz andere Zeitspannen.
Ad Konvertierung: Damit du ein int8_t - mit einer Auflösung von 1°C - 
erhälst, musst du folgendes machen.
1
int8_t temp = (low_byte >> 1) | (high_byte & 0x80);

[1] http://www.atmel.com/dyn/resources/prod_documents/doc2579.pdf

von Nico H. (nico84)


Angehängte Dateien:

Lesenswert?

Christopher G. schrieb:
> Die ganzen Wartezeiten sind nicht ganz korrekt.

Der der 1-Wire Bus soll da ja sehr tolerant sein. Beim Reset Impuls 
hatte ich noch eine Abfrage eingebaut, scheint also zu funktionieren.
1
 if( therm_reset() == 1)
2
 {
3
 while(1)
4
 {
5
  lcd_setcursor( 0, 1 );
6
  lcd_string( "reset error1" ); 
7
8
 }
9
 }

Warum kann ich die Umrechnung nicht wie im Bild machen? Zumindest klappt 
sie so nicht.

von Christopher G. (cbg)


Lesenswert?

Das durch 2 dividieren ist einfach ein rechtsshift um 1. Ob man jetzt /2 
oder >> 1 schreibt ist relativ egal. Ob der Compiler diesmal jedoch 
lieber zur float lib greift, weil /2.0 steht weiß ich nicht. Wäre 
sinnlos für diese Operation.
Beim 2er Komplement bildet man die alternative Darstellung, indem man 
alle Bits invertiert und dann 1 dazuzählt.

Wie gut sich das mit zuweisung zu Float verträgt weiß ich nicht. Ich 
denke mal es kommt dann darauf an, welche art von integer Datentyp 
(signed oder unsigned) man zuweist. Ob die letzte Aktion noch hilfreich 
ist müsste man auch überprüfen.

von Nico H. (nico84)


Lesenswert?

Aber davon mal ab, der Wert den ich Ausgegeben bekomme, sollte der sich 
nicht wenigstens beim erwärmen ändern? Das tut er leider nicht.

von Klaus (Gast)


Lesenswert?

@nicolai

Du Versuchst aus einem Integer ein float zu machen ist irgendwie nicht 
ganz richtig denke ich.

Ich habe den DS18S20 in Assembler laufen und da muss ich auch nichts 
dividieren eher multiplizieren mit  5.


Die ersten beiden Werte vom Scratchpad sind deine Freunde.
Dabei darf man das MSB vernachlässigen wenn Du nur positive Temperaturen
messen willst.

Zum Ablauf:
1. 1-Wire-Reset
2. 0xCC          ;Skip-ROM command
3. 0x44          ;Convert_T command ( Zeit beachten)

Nach dem zumindest einer der Sensoren fertig ist mit der Convertierung 
folgendes senden.

1. 1-Wire-Reset
2. 0x55         ;Match-Rom Command
3. Rom-Code 64bit senden.
4. 0xBE         ;Scratchpad command
5. ersten beide Bytes einlesen
6. dann für den abbruch 1-Wire-Reset.

Danach habe ich das LSB mit 5 multipliziert.

z.B 2Ch * 5 = DCh = 220d = 22 °C

das ganze noch in einen Ascii code gewandelt und auf dem LCD ausgegeben.

Sollte so ähnlich auch in C gehen denke ich.

von Nico H. (nico84)


Angehängte Dateien:

Lesenswert?

Ich hab nun beschlossen nochmal von ganz vorn zu beginnen. Da ich kein 
funktionierendes Speicheroszilloskop habe, lasse ich den Resetimpuls in 
einer Schleife ausgeben. Mit Pullup Widerstand und natürlich ohne den 
Sensor. Der low Reset Impuls sollte ja Min 480µs lang sein. Gemessen 
sind es nur ca 380µs. (siehe Bild 2VDIV, 0,2ms/DIV) Das kann doch gar 
nicht Funktionieren?
Der Atmega8 läuft mit den internen 8Mhz. Im AVR-Studio habe ich das auch 
angegeben. Ist der delay in dem Bereich so ungenau?
1
#include <avr/io.h>
2
#include <util/delay.h>
3
// #include "lcd-routines.h"
4
#include <stdlib.h>
5
6
/* Thermometer Connections (At your choice) */
7
#define THERM_PORT PORTB
8
#define THERM_DDR DDRB
9
#define THERM_PIN PINB
10
#define THERM_DQ PB1
11
/* Utils */
12
#define THERM_INPUT_MODE() THERM_DDR&=~(1<<THERM_DQ)
13
#define THERM_OUTPUT_MODE() THERM_DDR|=(1<<THERM_DQ)
14
#define THERM_LOW() THERM_PORT&=~(1<<THERM_DQ)
15
#define THERM_HIGH() THERM_PORT|=(1<<THERM_DQ)
16
17
18
int main( void )
19
{
20
 while( 1 ) {  
21
  uint8_t i;
22
  
23
  //Pull line low and wait for 480uS
24
  THERM_LOW();
25
  THERM_OUTPUT_MODE();
26
  _delay_us(480);
27
  
28
  //Release line and wait for 60uS
29
  THERM_INPUT_MODE();
30
  _delay_us(60);
31
  
32
  //Store line value and wait until the completion of 480uS period
33
  i=(THERM_PIN & (1<<THERM_DQ));
34
  _delay_us(420);
35
36
  
37
38
  }
39
return 0;
40
}

von Christopher G. (cbg)


Lesenswert?

Für die delay Loops der avr-libc muss man Optimierung einschalten beim 
Kompilieren.

von Nico H. (nico84)


Lesenswert?

Unter Project Options -> Optimization auf " -Os"  hab ich

von Christopher G. (cbg)


Lesenswert?

Richtige Frequenz angegeben? CLKDIV kanns ja eigentlich nicht sein, da 
wär der Unterschied etwas größer.
Sonst halt Konstanten für die Wartezeiten definieren und mit den Werten 
herumspielen, bis es passt oder gleich mit einem Timer realisieren.
Der interne Quarz ist normalerweise nicht so genau, wenn möglich 
versuchs mal mit einem externen.

von Nico H. (nico84)


Angehängte Dateien:

Lesenswert?

Ja, Frequenz ist richtig. Wenn ich die Werte *1.25 rechne sieht es ganz 
gut aus. ich glaub ich werde wo mal weiter probieren.

von Nico H. (nico84)


Angehängte Dateien:

Lesenswert?

Da war das Bild etwas klein...

von John (Gast)


Lesenswert?

Setzt Du den Wert für OSCCAL?

Nur für 1MHz wird dieser Wert nach Reset automatisch geladen. Für 2/4/8 
MHz musst Du den Wert selber setzen.

von Nico H. (nico84)


Lesenswert?

Ne hab ich nicht. Wie mach ich das?

von John (Gast)


Lesenswert?

Hier ist der entsprechende Auszug aus dem Datenblatt:

Calibration Byte
The ATmega8 stores four different calibration values for the internal RC 
Oscillator. These bytes resides in the signature row High byte of the 
addresses 0x0000, 0x0001, 0x0002, and 0x0003 for 1MHz, 2MHz, 4MHz, and 
8Mhz respectively. During Reset, the 1MHz value is automatically loaded 
into the OSCCAL Register. If other frequencies are used, the calibration 
value has to be loaded manually.

Oscillator Calibration Register – OSCCAL
Writing the calibration byte to this address will trim the Internal 
Oscillator to remove process variations from the Oscillator frequency. 
During Reset, the 1MHz calibration value which is located in the 
signature row High byte (address 0x00) is automatically loaded into the 
OSCCAL Register. If the internal RC is used at other frequencies, the 
calibration values must be loaded manually. This can be done by first 
reading the signature row by a programmer, and then store the 
calibration values in the Flash or EEPROM. Then the value can be read by 
software and loaded into the OSCCAL Register. When OSCCAL is zero, the 
lowest available frequency is chosen. Writing non-zero values to this 
register will increase the frequency of the Internal Oscillator. Writing 
0xFF to the register gives the highest available frequency. The 
calibrated Oscillator is used to time EEPROM and Flash access. If EEPROM 
or Flash is written, do not calibrate to more than 10% above the nominal 
frequency. Otherwise, the EEPROM or Flash write may fail.
Note that the Oscillator is intended for calibration to 1.0MHz, 2.0MHz, 
4.0MHz, or 8.0MHz. Tun-
ing to other values is not guaranteed.

von Nico H. (nico84)


Lesenswert?

hm..  Mit einem externen Quarz müsst ich das nicht machen oder?

von John (Gast)


Lesenswert?

Die Quarzfrequenz kann nicht direkt per Software verändert werden, nur 
durch variieren der Kondensatoren am Quarz. Aber die Grundgenauigkeit 
eines Quarzes ist so hoch, dass Du dir beim Timing eines 1-Wire Signals 
keine Sorgen über die Frequenzabweichung machen musst.

von Nico H. (nico84)


Lesenswert?

Daraus folgt dann, ich muss mir mit einem externen Quarz keine Gedanken 
um den OSCCAL machen.

von John (Gast)


Lesenswert?

Richtig.
Mit OSCCAL kann nur die Frequenz des internen RC-Oszillators verändert 
werden. Es hat keinen Einfluss auf den Quarz.

von Klaus (Gast)


Lesenswert?

@Nicolai!

Schliess auch deinen Sensor an sonst bekommst Du niemals den
 Presenceimpuls. Den der Sensor zieht nach 480µs den Bus auf Low den du 
dann nach 60µs abfragen kannst.

von Nico H. (nico84)


Lesenswert?

Den hatte ich ja nur zum Messen des Senders abgeklemmt. Der Reset 
klappt, den Presenceimpuls bekomme ich auch. Komischerweise bekomme ich 
beim einlesen der Temperatur immer nur 11111111. Da liegt der Verdacht 
nahe das mir der Sensor garnicht antwortet. (Auf den Resetimpuls schon.)

von Klaus (Gast)


Angehängte Dateien:

Lesenswert?

Den Familiencode brauch man nur senden wen mehrere Sensoren dran hängen.

Hier mal ein Beispiel nach dem Reset wie das erste Byte eines 
Familiencodes aus sehen könnte das nach dem Match-Command gesendet wird.

von Nico H. (nico84)


Lesenswert?

Dafür bräuchte ich ein Speicher Oszilloskop. Ich hab noch ein Tektronix 
11402, das blinkt leider nur noch beim einschalten. schade um das gute 
Stück.

von Klaus (Gast)


Lesenswert?

Nicolai Henrych schrieb:
> Da liegt der Verdacht
>
> nahe das mir der Sensor garnicht antwortet. (Auf den Resetimpuls schon.)

Das könnte noch am Timing liegen da muss man schn recht präziese sein 
was das einlesen und schreiben anbelangt.

Mit welchen Routinen arbeitest Du. Im Netz gibts da einiges zu finden.

von Nico H. (nico84)


Lesenswert?

So, ich habe mal etwas weiter experimentiert. Byte 0 steht immer auf 
11111111. Byte 1 immer auf 00000000  Ich kann Byte 2 und 3 problemlos 
beschreiben und auslesen. Sollte ein Fehler vorliegen sollte doch Byte 0 
laut Datenblatt 10101010 sein. Dann kann ich doch eigentlich davon 
ausgehen das der Sensor defekt ist? Habe leider kein 2. zum Testen da.

von Wolfgang (Gast)


Lesenswert?

Da ja offensichtlich noch erheblich Probleme bestehen mit dem 
Zeitverhalten des 1Wire-Busses, empfehle ich einfach mal dreist mein 
Mini-Projekt mit einem ATtiny13, der ein 1Wire-EEPROM von Dallas 
simuliert. Vielleicht läßt sich ja daraus etwas Sinnvolles ableiten. 
http://wpö.de/index.php?Projekte und hier Dell-OneWire.

Gruß - Wolfgang

von Nico H. (nico84)


Lesenswert?

Nach dem ich nun den Sensor getauscht habe funktioniert es nun ;)

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.