1-Wire Reset Impuls?

OP Persönliche Seite #2065014
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
}
#2065028
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.
#2065035
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?
Gast #2065080
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
Angehängte Dateien:
OP Persönliche Seite #2066774
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
Angehängte Dateien:
#2089789
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.
#2090398
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.
Angehängte Dateien:
#2090432
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.
Gast #2090477
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.
#2091233
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
}
Angehängte Dateien:
#2091259
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.
Gast #2091361
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.
Gast #2091403
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.
#2091987
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.)
#2096898
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren