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...
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.
>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.
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?
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
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
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.
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 ;(
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.
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.
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.
@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.
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?
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.
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.
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.
@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.
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.)
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.
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.
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.
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