Liebes Forum,
ich sitze jetzt schon knapp zwei Wochen an dem Problem, dass ich keine
Daten vom Temperatursensor DS18B20 erhalte.
Hardware-mäßig sollte alles passen (versorgt an Vcc, GND- Verbindung
vorhanden, und an Datenleitung Pull-Up-Widerstand mit 4,7kOhm).
Am Bus hängt auch nur ein solcher Temp-Sensor!
Den Code habe ich im Internet gefunden, welcher laut anderen Usern auch
funktionieren sollte. Bei mir jedenfalls leider nicht.
Nach einem Reset-Pulse vom uC antwortet mir der Temp-Sensor mit einem
Presence-Pulse.
Nachdem ich den Skip-Rom und anschließend den Convert-T Befehl schicke,
warte ich 750ms.
Danach schicke ich den Skip-Rom mit anschließendem Scratchpad Befehl.
Aber leider schickt mir der Sensor nichts zurück.
Ich weiß echt nicht, was ich falsch mache...
Bitte um Hilfe!
Hier der C-Code:
Frustrierter schrieb:> ... warte ich 750ms.
Hast du das nachgemessen oder steht das nur so im Programm?
Kennt dein Compiler die tatsächliche Taktfrequenz deines µC?
Fred F. schrieb:> Vieleicht das hier?> Beitrag "China Schrott - NPN Transistor als DS18B20 verkauft"
Nein, habe den Sensor bei RS bestellt!!
Außerdem kommt nach einem Reset-Puls vom uC ein Response-Puls vom
Sensor. Also gehe ich stark davon aus, dass es wirklich ein DS18B20
ist!!
Wolfgang schrieb:> Frustrierter schrieb:>> ... warte ich 750ms.>> Hast du das nachgemessen oder steht das nur so im Programm?> Kennt dein Compiler die tatsächliche Taktfrequenz deines µC?
Das passt. Habe ich nachgemessen!
Was liest Du denn vom Bus? Nur 1-en? Also 255 als uint8_t. Wenn ja,
deutet das daraufhin, dass der Sensor noch busy ist. Check mal die 750ms
... bzw. schau mal mit nem Oszi was passiert.
definiert. Ich schreibe die 9 Byte des Scratchpad in ein char-Array.
Für die Temperatur werte ich das das erste Byte aus (entspricht Deinem
tempL allerdings als unsigned char definiert). Das zweite Byte gibt nur
das Vorzeichen aus. Ist Byte 2 0 dann ist es eine positive Temperatur
und man erhält den Temperaturwert mit folgendem Code:
1
unsignedchartempL
2
floatT=tempL/2.0
Bei negativen Temperaturen ist es etwas aufwändiger. Byte 2 ist dann 1
und die Temperatur errechnet sich über das 2'er Komplement von Byte 0
Das passt auch nicht zusammen:
unsigned int i = 0; // declare a variable to store
i = (float) i * 6.25; //calcuation from the table provided
welche Table? calcuLation
zu den 750ms: warte halt mal länger, z.B. 1500ms
Ich vermute, die Abfrage des Presence-Pulses funktioniert so nicht:
if (Port_one_wire_bus == 0) // if there is a presence pluse
Fragst Du den ganzen Port ab oder nur ein Pin / Bit?
Evtl ausmaskieren.
> Aber leider schickt mir der Sensor nichts zurück.
Hast Du das mit dem Oszi kontrolliert?
Und das gibt eine Shift-Orgie:
if ((Cmd & (1 << i)) != 0)
Schiebe lieber das Cmd nach jeder Abfrage einmal nach rechts.
Oder verwende das i gleich als Schleifen"zähler":
uint8_t i=1;
do{
if(Cmd & i){send 1}
else {send 0}
}while(i <<= 1); // nach dem 8. Mal ist i == 0, also false
eProfi schrieb:> Ich vermute, die Abfrage des Presence-Pulses funktioniert so nicht:> if (Port_one_wire_bus == 0) // if there is a presence pluse
So wie es im Gesamtkontext da steht, also mit den 60ms delay davor
funktioniert das schon. Allerdings sind die 60ms die unterste Grenze.
Ich würde mindestens 65ms nehmen.
Er soll mal das von mir verlinkte PDF durcharbeiten. Dort ist das
Signalspiel detailiert beschrieben und wenn man sich daran hält dann
funktioniert das. Das entscheidente bei 1-Wire ist halt das Timing,
welches man schon gut einhalten sollte. Das ganze steht und fällt halt
mit der Güte des Delays. An dieser Stelle schreibt man sich am besten
selbst etwas.
Ach ja: Während eines kompletten 1-Wire-Zykluses sollten keine Interupts
aktiv sein.
Zeno
http://www.microchip.com/forums/m851710.aspx:
// ensure all the hardware port in zero initially
PORTA=0b00000000; //port a off
PORTB=0b00000000; //port b off
TRISA=0b11111111; //a as inputs
TRISB=0b00000000; //b as outputs
nicht nur den Kommentar (mit Tippfehler in --> is) kopieren,
sondern auch die Befehle danach.
In diesem Fall war es aber lehrreich, denn das hätte den eigentlichen
Fehler (dass das Bit herausmaskiert werden muss) verdeckt.
Im o.g. Link machen sie das z.B. so:
if(PORTBbits.RB7==1)
Bitte immer den gesamten Code angeben, es fehlen einige Definitionen.
> So wie es im Gesamtkontext da steht, also mit den 60ms> delay davor funktioniert das schon.
60ms --> 60µs
Nein, das funktioniert nicht, da undefiniert ist, wie die anderen 7 Bits
des Ports stehen.
> Ach ja: Während eines kompletten 1-Wire-Zykluses sollten keine> Interupts aktiv sein.
Interupts --> Interrupts Zykluses --> Zyklusses
Nein, das ist nicht nötig. Nur innerhalb eines Bits müssen die Zeiten
genau eingehalten werden.
Bitte mal alle generell mehr auf korrekte Rechtschreibung achten.
Wenn ich das so lese, wundert mich auch nicht, dass der Code nicht
funktioniert. Einfach vor dem Posten nochmal konzentriert durchlesen.
Vorn N. schrieb:> 60ms --> 60µs
OK das µ habe ich überlesen. Es ist dennoch der untere Grenzwert und man
sollte aus diesem Grund schon einen etwas höheren Wert wählen.
Vorn N. schrieb:> Nein, das funktioniert nicht, da undefiniert ist, wie die anderen 7 Bits> des Ports stehen.
Das funktioniert schon. Du weist doch gar nicht wie er seine Variablen
deklariert hat, da er dies nicht gepostet hat. Wenn sie so deklariert
sind, das damit der Pin, also das entsprechende Bit des Ports, direkt
angesprochen wird dann funktioniert es.
Vorn N. schrieb:>> Ach ja: Während eines kompletten 1-Wire-Zykluses sollten keine>> Interupts aktiv sein.> Interupts --> Interrupts Zykluses --> Zyklusses
OK Du hast 2 Rechtschreibfehler gefunden, Du darfst sie gern behalten.
Die Welt wird sich auch mit selbigen weiter drehen.
Vorn N. schrieb:> Nein, das ist nicht nötig. Nur innerhalb eines Bits müssen die Zeiten> genau eingehalten werden.
Hää? Zeiten innerhalb eines Bits einhalten? Interrupts kümmern sich
einen Scheißdreck darum was Du gerade in Deinem Programm machst. Die
hauen da einfach rein und unterbrechen das laufende Programm - ist ja
auch Sinn und Zweck eines Interrupt's. Wenn der Interrupt an einer
zeitkritischen Stelle dazwischen haut, dann war's das. Empfehle Dir
ebenfalls mal dies
http://pic-projekte.de/wordpress/wp-content/uploads/2015/09/1-Wire-Projekt-V1_3.pdf
zu lesen. Zitat aus genannter Quelle:
1
Während der Kommunikation über den 1-Wire-Bus darf der Mikrocontroller durch KEINE INTERRUPTS gestört
2
werden, alle Interrupts müssen also während der Kommunikation disabled sein !
3
Erst nach Beendigung der Kommunikation (eines kompletten Kommunikationszyklusses) sind Interrupts wieder zugelassen !
Ich habe mich daran gehalten und im Gegensatz zum TO funktioniert es bei
mir, sogar mit mehreren 1-Wire Devices. Bei aktiven Interrupts kommt es
immer wieder mal zu Fehlern.
Zeno
Zeno schrieb:>> Hää? Zeiten innerhalb eines Bits einhalten? Interrupts kümmern sich> einen Scheißdreck darum was Du gerade in Deinem Programm machst. Die> hauen da einfach rein und unterbrechen das laufende Programm - ist ja> auch Sinn und Zweck eines Interrupt's. Wenn der Interrupt an einer> zeitkritischen Stelle dazwischen haut, dann war's das. Empfehle Dir
Gemeint war wohl, dass die 1-bit Sequenz (write oder read) nicht durch
eine ISR unterbrochen werden darf. Zwischen den Bit-Sequenzen darf
beliebig viel Zeit verstreichen.
Wilhelm M. schrieb:> Zeno schrieb:>>>> Hää? Zeiten innerhalb eines Bits einhalten? Interrupts kümmern sich>> einen Scheißdreck darum was Du gerade in Deinem Programm machst. Die>> hauen da einfach rein und unterbrechen das laufende Programm - ist ja>> auch Sinn und Zweck eines Interrupt's. Wenn der Interrupt an einer>> zeitkritischen Stelle dazwischen haut, dann war's das. Empfehle Dir>> Gemeint war wohl, dass die 1-bit Sequenz (write oder read) nicht durch> eine ISR unterbrochen werden darf. Zwischen den Bit-Sequenzen darf> beliebig viel Zeit verstreichen.
Die Frage ist halt was man als Bitsequenz definiert. Wenn damit der
Gesamtzyklus, also vom 1.Masterreset bis zum Auslesen des letzten Bits
des Scratchpad gemeint ist, dann das richtig.
Zwischen den einzelnen write und read macht das keinen Sinn, weil
einfach die Zeiten zu knapp sind. Zwischen den Timeslots, also der Zeit
wo wirklich was passiert liegen ca. 15µs, da macht es keinen Sinn
irgendwelche Interrupts einzuschalten.
Das einzige Zeitintervall wo Zeit wären evtl. die minimal 750ms
Wandlerzeit beim DS1820. Ich habe es aber nicht ausprobiert.
Glaube mir es ist in jedem Fall besser die Interrupts während des
gesamten Zyklusses abzuschalten. Gerade wenn es noch nicht läuft ist das
die beste Lösung. Wenn es dann mal funktionieren sollte kann man ja
austesten an welchen Punkten Interrupts zugelassen werden könnten.
Zeno
@ Zeno (Gast)
>> Gemeint war wohl, dass die 1-bit Sequenz (write oder read) nicht durch>> eine ISR unterbrochen werden darf. Zwischen den Bit-Sequenzen darf>> beliebig viel Zeit verstreichen.
Eben.
>Die Frage ist halt was man als Bitsequenz definiert.
Das ist bei OneWire recht eindeutig. Der Schreib- oder Lesevorgang eines
einzigen Bits.
>>Wenn damit der>Gesamtzyklus, also vom 1.Masterreset bis zum Auslesen des letzten Bits>des Scratchpad gemeint ist, dann das richtig.
Nein.
>Zwischen den einzelnen write und read macht das keinen Sinn, weil>einfach die Zeiten zu knapp sind.
Nö.
> Zwischen den Timeslots, also der Zeit>wo wirklich was passiert liegen ca. 15µs, da macht es keinen Sinn>irgendwelche Interrupts einzuschalten.
Falsch. Genau anders herum wird ein Schuh draus. Eben WEIL zwischen dein
einzelnen Bits beliebig viel zeit liegen darf, MUSS man nahezu die
Interrupt zwischen den Bits freischalten, damit diese ggf. bedient
werden können, ohne ewig ausgebremst zu werden.
>Glaube mir es ist in jedem Fall besser die Interrupts während des>gesamten Zyklusses abzuschalten.
Nö. Damit legt man sich die CPU für mehrere Millisekunden lahm. Für ein
Trivialprogramm ist das OK, in einer echten Anwendung ist das meist
fatal.
Zeno schrieb:> Die Frage ist halt was man als Bitsequenz definiert. Wenn damit der> Gesamtzyklus, also vom 1.Masterreset bis zum Auslesen des letzten Bits> des Scratchpad gemeint ist, dann das richtig.
Sag ich doch (s.o. 1-Bit-Sequenz)
> Zwischen den einzelnen write und read macht das keinen Sinn, weil> einfach die Zeiten zu knapp sind.
Du meinst das low zum Initiieren einer 1-Bit-Sequenz und dem
anschließenden Sample für das read? Ja, hier muss das Timing stimmen.
Und dies ist eine 1-Bit-Sequenz
> Glaube mir es ist in jedem Fall besser die Interrupts während des> gesamten Zyklusses abzuschalten. Gerade wenn es noch nicht läuft ist das> die beste Lösung. Wenn es dann mal funktionieren sollte kann man ja> austesten an welchen Punkten Interrupts zugelassen werden könnten.
Nee, während des gesamten Zyklus (> 480ms wegen Reset) will / muss ich
doch noch was anderes machen ...
Wilhelm M. schrieb:> Nee, während des gesamten Zyklus (> 480ms wegen Reset) will / muss ich> doch noch was anderes machen ...
Der Resetimpuls ist 480µs lang. Danach kommen min. 15µs Wartezeit, dann
sollten die Slaves mit dem Presenseimpuls (max. 240µs) antworten. Dann
kann es losgehen. Slave wählen (wenn mehrere dran sind), Befehl senden
(1Byte = 8 Timeslots á 60s = 480µs + ca. 2µs Erholzeit zwischen den
Bits), wenn's ein Befehl mit Parametern war Parameter senden, Antwort
der Slaves abwarten und deren gesendete Bytes einlesen.
Beim Einlesen eines Bytes vom Slave bleibt zwischen den einzelnen Bits
definitiv keine Zeit groß was Anderes zu machen.
Es macht eigentlich nur beim DS1820 während der Converterzeit von min.
750ms Sinn etwas anderes zu machen, da würde ich mit gehen.
Wenn es auf die Verfügbarkeit des µC's ankommt, dann würde ich das Ganze
eh nicht mit Software machen, sondern einen Interfacechip, z.B. DS2482
benutzen. Dem sage ich per I2C was ich will und der macht dann die ganze
Kommunikation mit den 1-Wire-Slaves.
Ich bin mit dem Abschalten der Interrupts während des 1-Wire-Zugriffs
bisher gut gefahren und wenn der µC während der Zeit mal nichts macht
geht bei mir die Welt auch nicht unter zumal die Zugriffe auf den
1-Wire-Bus bei mir nur minimal nur alle 3 Minuten zur Messwertabfrage
erfolgen und da kommt es mir auf 750ms Convertertime definitiv nicht an.
Das kann ja in anderen Fällen durchaus anders sein, dann muß ich halt
eine andere Lösung finden. Dann sollte ich aber schon überlegen ob ich
es nicht doch besser mit Hardware oder sogar einen 2.µC mache.
Wenn ich wie der TO erst mal was aufsetze, dann versuche ich schon
Störeinflüsse so gering wie möglich zu halten. Wenn's dann läuft kann
ich immer noch optimieren oder auch mal mit Interrupts testen. Aber eben
erst wenn es sich sicher funktioniert, was ja beim TO nicht der Fall zu
sein scheint.
Zeno
Zeno schrieb:> Beim Einlesen eines Bytes vom Slave bleibt zwischen den einzelnen Bits> definitiv keine Zeit groß was Anderes zu machen.
Doch, denn man kann jedes Bit mit einer beliebigen Zeit dazwischen
schreiben/lesen. Und nochmal: nur für die 1-Bit-Sequenz muss das Timing
ziemlich genau eingehalten werden (inkl. recovery time).
Man kann also den 1-wire auch gut mit variabler Rate bedienen.
wolle g. schrieb:> Man könnte auch mittels I2C über einen DS2482 den DS18B20 betreiben.> Damit braucht man sich nicht um die Einhaltung von Zeiten kümmern (außer> 750ms)
Habe ich doch schon gesagt.
@wolle g. (wolleg)
>Man könnte auch mittels I2C über einen DS2482 den DS18B20 betreiben.>Damit braucht man sich nicht um die Einhaltung von Zeiten kümmern (außer>750ms)
Man kann auch mit Fahrradhelm in den Supermarkt gehen . . .
Bin ganz neu im one wire undeill das Protokoll selbst programmieren. An
deinem Code ist mir aufgefallen das die Low0 60-120us und Low1 1-15us
nicht passt. Habe ich eben im Datenblatt gesehen. Könnte es damit
zusammen hängen?