Forum: Mikrocontroller und Digitale Elektronik DS18B20: Mehrere Sensoren am Bus, nur letzte Temp. stimmt


von Mario F. (superdude)


Lesenswert?

Hallo,

es gibt ja oft Fragen zum DS18B20, aber zu diesem Problem hab ich leider 
keinen Thread gefunden:

Wenn ich mehrere Sensoren an einem Bus betreibe, stimmt nur beim zuletzt 
gewandelten die Temperatur.
Einzeln funktionieren meine Sensoren, insbedondere auch individuell 
addressiert (also mit CMD_MATCHROM statt CMD_SKIPROM) passt alles mit 
ID,Temperatur und CRC.
Via SEARCH_ROM baue ich ein Array mit den IDs zusammen, das funktioniert 
auch.

Zu jeder geraden Sekunde ewird ine Temperaturwandlung gestartet und zwar 
für alle Sensoren am Bus gleichzeitig:
RESET,CMD_SKIPROM,CMD_CONVERTTEMP.
(Das Datenblatt des DS18B20 schlägt das auch genauso vor)

Zu jeder ungeraden Sekunde werden dann alle Temperaturwerte eine 
Schleife durch das ID-Array ausgelesen:
for i ...: RESET,MATCHROM ID[i],READSCRATCHPAD.

Problem ist, dass die Temperaturen nur noch beim letzen Sensor in der 
Liste stimmen.
Mein Verdacht: RawTemp=0x0550 bedeutet ja nach Datenblatt 
default-Temperatur, also irgendwas in Richtung "Temperatur ausgelesen 
ohne vorher Wandlung anzustossen".
Ich hab doch aber für alle Sensoren eine Wandlung angestossen, und eine 
Sekunde später lese ich von jedem Sensor individuell addressiert die 
Temperatur. Wieso stört sich das ganze trotzdem?

Danke für Hinweise,
Mario
1
void OnEveryNewSecond(uint8_t second)
2
{
3
  if (second % 2)
4
  {
5
    onewire_reset();
6
    onewire_writebyte(ONEWIRE_CMD_SKIPROM);  
7
  }
8
  else
9
  {
10
    for (i=0; i<SensorsInList; i++)
11
    {
12
      onewire_reset();
13
      onewire_writebyte(ONEWIRE_CMD_SKIPROM);
14
      int16_t rawtemp = ds18b20_gettemp(ID[i]); // CMD_READSCRATCHPAD
15
      ... print i, ID[i], rawtemp, PhyTemp(rawtemp) ...
16
    }
17
  }
18
}
1
nur Sensor[0] angesteckt:
2
00: s00   28181ea200000094 0550 +85.0000 C
3
01: s01   28db11a20000003d ffff +127.9375 C
4
5
nur Sensor[1] angesteckt:
6
00: s00   28181ea200000094 ffff +127.9375 C
7
01: s01   28db11a20000003d 01a9 +26.5625 C
8
9
beide:
10
00: s00   28181ea200000094 0550 +85.0000 C
11
01: s01   28db11a20000003d 0196 +25.3750 C

von Peter D. (peda)


Lesenswert?

Mario Fischer schrieb:
> void OnEveryNewSecond(uint8_t second)
> {
>   if (second % 2)
>   {
>     onewire_reset();
>     onewire_writebyte(ONEWIRE_CMD_SKIPROM);
>   }
>   else
>   {
>     for (i=0; i<SensorsInList; i++)
>     {
>       onewire_reset();
>       onewire_writebyte(ONEWIRE_CMD_SKIPROM);
>       int16_t rawtemp = ds18b20_gettemp(ID[i]); // CMD_READSCRATCHPAD
>       ... print i, ID[i], rawtemp, PhyTemp(rawtemp) ...
>     }
>   }
> }

Was soll das?
Poste Deinen wirklichen Code (als Anhang).


Peter

von Mario F. (superdude)


Angehängte Dateien:

Lesenswert?

Hallo,

sorry, ich poste gerne den ganzen Code (Anhang).

Habe mich im ersten Post jedoch bewusst zurückgehalten mit dem Code, da 
die dort aufgerufenen Funktionen für sich ja alle korrekt sind.
Ich hatte einfach den Verdacht, dass es eher ein Problem der 
Kommandoreihenfolge ist.

Kurz zur übersicht (das Angehängte ist trotz Beschränkung aufs 
wesentliche recht lang),
oben stehen die OneWire basics (Read/Write/Bit/Byte),
dann das ganze ID-Handling (Read/Skip/SearchROM).
Dann die DS18-spezifischen Dinge, und ganz unten das Auslesen aller 
Sensororen.
In Letzterem vermute ich halt auch den Fehler.

Im Prinzip fahre ich diese Endlosschleife ab:
1
  OneWire Reset
2
  OneWire SkipROM
3
  OneWire StartConvertTemperature
4
5
  Warte 2 Sekunden
6
7
  für alle Sensoren ID[i]
8
    OneWire Reset
9
    OneWire MatchROM ID[i]
10
    OneWire ReadScratchpad // RawTemp = erste 2 Bytes davon
11
    
12
   Warte 2 Sekunden
und dabei treten oben beschriebene Effekte auf.

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

Hat zwar mir dem Problem nichts zu tun, aber:

Mario Fischer schrieb:
> Zu jeder geraden Sekunde ewird ine Temperaturwandlung gestartet
> Zu jeder ungeraden Sekunde werden dann alle Temperaturwerte ... ausgelesen

Das ist für die Sensorgen schon recht kritisch. Wenn sie so oft 
angesprochen werden, erzeugen sie selber zu viel Wärme. Die Temperaturen 
sind dann immer mindestens 5°C zu hoch.

von Mario F. (superdude)


Lesenswert?

Danke für den Hinweis! Werde die Sensoren dann in der Praxis nur alle 8 
oder 16 Sekunden abfragen, ist jetzt nur zum Testen.

von eProfi (Gast)


Lesenswert?

Um einem Sensor das Convert-Cmd zu schicken, muss er selektiert sein.

Der letzte ist noch durch die Search-Routine selektiert.
Es fehlt also ein Skip-Rom.

Der Code ist verbesserungswürdig.


Hast Du parasite-Power? Hoffentlich nicht, denn die Sensoren brauchen 
schon etwas Strom für die Wandlung.

von eProfi (Gast)


Lesenswert?

Das war jetzt ein Eigentor, denn SkipRom ist vorgesehen, aber ob es 
wirklich ausgesendet wird?
Stimmt die Quarzfrequenz, also die Wartezeiten?
Wenn mehrere Sensoren anschlossen sind, darf der PullUp stärker sein, 
z.B. 1 kOhm.

Warum wandelst Du jede Sekunde in jedem Sensor? Ich würde nur den Sensor 
wandeln lassen, den ich auch danach auslese.

von Mario F. (superdude)


Lesenswert?

Als Anfänger bin ich natürlich für konkrete Vorschläge wie "Der Code ist 
verbesserungswürdig" herzlich dankbar, da ich erst seit 15 Jahren C 
programmiere ;-)

Aber in Ernst, dass die Delays stimmen hab ich eigentlich schon anfangs 
gesagt (hab sogar mitm Oszi draufgeschaut), und es funktinieren ja alle 
onewire-Funktionen (sinnvolle Temperaturen, CRC ok, 
Search/Match/SkipROM, ...) korrekt.
Nur das startconvert und readscratchpad beeinflusst sich scheins 
irgendwie.

Die Methode mit dem startconvert-Broadcast ist eleganter als lauter 
einzelne startconverts, schliesslich will ich den BusTraffic bzw die 
delay_us() gering halten.
Ausserdem ist der Fall, dass man an vielen Messstellen die Temperatur 
exakt gleichzeitig messen will durchaus nicht ungewöhnlich und wird 
deshalb im DS18-Datenblatt auch explizit so erwähnt.

Und ja, ich hab Parasite-Power (also nicht ich sondern die Sensoren ;-) 
) - Einen kleineren Pullup werd ich mal probieren, für den Fall dass 2 
DS18er zusammen zuviel Strom saugen wenn sie gleichzeitig wandeln - 
könnte das echt der Fall sein? Die Leitungslängen sind gerade mal 30+30 
cm...
Trotzdem hab ich irgendwie den Verdacht dass es eine 
startconvert/readscratchpad-Beeinflussung sein könnte.

von eProfi (Gast)


Lesenswert?

Tut mir leid, hatte nur kurz Zeit, Deine sehr ausführlich gestellte 
Frage (Lob!) zu überfliegen.

Während der Wandlung (und bei anderen 1W-Bausteinen beim 
Eeprom-Schreiben) muss für Parasite-Power DQ aktiv hochgezogen werden, 
der PullUp reicht für die Versorgung i.d.R. nicht aus.
Ich schau mir Deinen Code gleich nochmal an.

Deshalb ist ja auch die Zeile, in der Busy überprüft wird, bei Parasite 
unwirksam. Vcc der DS18 muss mit Gnd verbunden sein, damit sie sicher im 
Parasite-Mode sind.

Kannst Du ein Oszillogramm vom Wandeln posten?

von Mario F. (superdude)


Lesenswert?

danke fürs Lob und nix für ungut :-)

Also "StrongHi" schalte ich den OneWire nie.
Es gibt nur (angelöteter 4k7 nach VCC) und am OneWirePin die Zustände
DriveLo := {PortBit=0; DdrBit=1; }
oder
Release := {DdrBit=1; }.
Das hab ich so aus der Atmel-Applicationnote für OneWire-Master
( http://www.atmel.com/dyn/resources/prod_documents/doc2579.pdf )
und der onewire.c aus dem Ethersex-Projekt übernommen.
Ob dort Parasite gefahren wird schreiben beide leider nicht.

Es funktioniert ja auch nahezu alles bei meinem Code, also auch mit 
mehreren Sensoren am Bus.
Insbesondere sensorlist_searchrom() und ds18b20_test() liefern korrekte 
Ergebnisse - keine davon benutzt allerdings einen 
startconvert-broadcast.
Es könnte schon sein, dass ein startconvert-broadcast zu viel Strom 
zieht, ich schau mir das morgen mal aufm Oszi an.
Laut Datasheet ist der grösste Strom, den ein DS18 ziehen kann 1,5mA. 
Liegt zwar auch für 2 Sensoren weit unter den 20mA die ein AtmelPin 
kann, aber der ist ja nie "StrongHi" sondern immer nur HiZ(Relase) oder 
GND(DriveLo). Mein Pullup ist 4k7, also das was das Dataseet für einen 
Sensor empfiehlt. Für MehrSensorBetrieb hab ich keine empfohlenen Werte 
gefunden.

von eProfi (Gast)


Lesenswert?

in Zeile 249 fehlt eine Klammer:
  if (eeprom_read_byte((uint8_t*)&(e_onewire_sensors[i].name[0]) != 
0x00)
--->
  if (eeprom_read_byte((uint8_t*)&(e_onewire_sensors[i].name[0])) != 
0x00)


> Also "StrongHi" schalte ich den OneWire nie.
Solltest Du aber, wenn Du Parasite verwendest.
8. Active current refers to supply current during active temperature 
conversions or EEPROM writes.

> Laut Datasheet ist der grösste Strom, den ein DS18 ziehen kann 1,5mA.
und woher sollen die kommen? Der 4,7k begrenzt den Strom auf 1,0mA, wenn 
DQ ganz low ist. Der DS braucht die max. 1,5mA jedoch im High-Zustand.

Auf StrongHi kannst Du nur verzichten, wenn keine Parasite-Versorgung 
verwendet wird.

Versorge doch testweise die DS18 mit 5V.

Außerdem wäre es recht hilfreich, wenn Du ein lauffähiges Projekt posten 
könntest, also mit main(), PRINTHEX  etc.

Viel Erfolg

von Peter D. (peda)


Lesenswert?

Mario Fischer schrieb:
> Und ja, ich hab Parasite-Power (also nicht ich sondern die Sensoren ;-)
> )
> Also "StrongHi" schalte ich den OneWire nie.

Warum sagste das denn nicht gleich, daß Du das Datenblatt mißachtest.
Läßt lieber die Leute wie blöd rumraten.

Aus meinem Code:
Beitrag "DS1820, DS18B20 in C"
1
void start_meas( void ){
2
  if( W1_IN & 1<< W1_PIN ){
3
    w1_command( CONVERT_T, NULL );
4
    W1_OUT |= 1<< W1_PIN;
5
    W1_DDR |= 1<< W1_PIN;      // parasite power on
6
7
  }else{
8
    uputsnl( "Short Circuit !" );
9
  }
10
}


Peter

von (prx) A. K. (prx)


Lesenswert?

Mario Fischer schrieb:

> Also "StrongHi" schalte ich den OneWire nie.

Und das dann auch noch mit mehreren gleichzeitig messenden Sensoren. 
Ergibt bei 2 Stück bis zu 3mA und bei 1K also bis zu 3V Spannungsabfall 
- von 4K7 ganz zu schweigen.

von Mario F. (superdude)


Lesenswert?

Peter Dannegger schrieb:
> Warum sagste das denn nicht gleich, daß Du das Datenblatt mißachtest.
> Läßt lieber die Leute wie blöd rumraten.

Sorry, ich hab das mit dem Parasite nicht absichtlich verschwiegen, um 
die Leute in eine falsche Richtung zu locken.
Hatte eben den starken Verdacht, dass das Problem auf Ebene der 
Kommando-Reihenfolge liegt und hab es auch deswegen eher in diese 
Richtung detaillierter beschrieben.

Aber, um aufs Thema zurück zu kommen: Ich hab das ganze mit einem 
kleineren Pullup ausprobiert (470 Ohm => 10 mA max), und siehe da, alle 
Sensoren wandeln gleichzeitig korrekt. Aktiv auf Hi mit dem AVR-Port zu 
ziehen wollte ich nicht, da er sonst kaputt gehen kann wenns mal einen 
permanenten Kurzschluss auf dem Bus gibt.

Insofern also Danke an allen hier, die mir geholfen haben!

Da ich nicht schon wieder das Datenblatt missachten will hab ich 
nachgesehen, ob die Sensoren die 10mA denn sinken können, wenn sie die 
Leitung auf GND ziehen beim Senden einer 0.
Das Datenblatt listet aber bei Sink Current nur einen _Minimal_Wert von 
4mA auf - das verstehe ich nicht: Ich dachte limitierend wäre eher, 
wieviel Amp der Sensor maximal nach Gnd runterleiten kann ohne Schaden 
zu nehmen (oder auch nur zu warm zu werden und damit die nächste Messung 
evtl zu verhageln).

Sind die 470 Ohm denn ok? Insbesondere wenns mehr Sensoren und eine 
lange Leitung werden?
Wo liegt mein Denkfehler, dass es für den SinkCurrent des DS18 nur einen 
Min-Wert gibt?

von eProfi (Gast)


Lesenswert?

Das ist so zu verstehen: es können mindestens 4 mA gedrained werden, 
ohne dass die Spannung über 0,4 V steigt.

Wenn Du um Dein Port besorgt bist: schalte einen 100 Ohm in Reihe zum 
Portpin. 50mA hält er sicher aus, auch wenn das Datenblatt nur 20mA 
angibt (diese gelten ja über den gesamten Temp-Bereich). Dadurch wird 
nebenbei das Ringing gedämpft, was bei einer langen Leitung ein großer 
Vorteil ist.

Einge stabile Versorgung (über active PullUp) verbessert die Genauigkeit 
der Wandlung:
Auszug aus dem DS1820-Datasheet:
PARASITE POWER
The block diagram (Figure 1) shows the parasite powered circuitry.
This circuitry "steals" power whenever the I/O or VDD pins are high.
I/O will provide sufficient power as long as the specified timing and 
voltage requirements are met (see the section titled "1-Wire Bus 
System").

The advantages of parasite power are two-fold:
1) by parasiting off this pin, no local power source is needed for 
remote sensing of temperature, and
2) the ROM may be read in absence of normal power.

In order for the DS1820 to be able to perform accurate temperature 
conversions, sufficient power must be provided over the I/O line when a 
temperature conversion is taking place.
Since the operating current of the DS1820 is up to 1 mA, the I/O line 
will not have sufficient drive due to the 5K pull-up resistor.
This problem is particularly acute if several DS1820’s are on the same 
I/O and attempting to convert simultaneously.

There are two ways to assure that the DS1820 has sufficient supply 
current during its active conversion cycle.
The first is to provide a strong pull-up on the I/O line whenever 
temperature conversions or copies to the E2 memory are taking place.
This may be accomplished by using a MOSFET to pull the I/O line directly 
to the power supply as shown in Figure 2.
The I/O line must be switched over to the strong pull-up within 10 ms 
maximum after issuing any protocol that involves copying to the E2 
memory or initiates temperature conversions.When using the parasite 
power mode, the VDD pin must be tied to ground.

Another method of supplying current to the DS1820 is through the use of 
an external power supply tied to the VDD pin, as shown in Figure 3.
The advantage to this is that the strong pull-up is not required on the 
I/O line, and the bus master need not be tied up holding that line high 
during temperature conversions.
This allows other data traffic on the 1-Wire bus during the conversion 
time.
In addition, any number of DS1820’s may be placed on the 1-Wire bus, and 
if they all use external power, they may all simultaneously perform 
temperature conversions by issuing the Skip ROM command and then issuing 
the Convert T command.
Note that as long as the external power supply is active, the GND pin 
may not be floating.

The use of parasite power is not recommended above 100°C, since it may 
not be able to sustain communications given the higher leakage currents 
the DS1820 exhibits at these temperatures.
For applications in which such temperatures are likely, it is strongly 
recommended that VDD be applied to the DS1820.

For situations where the bus master does not know whether the DS1820’s 
on the bus are parasite powered or supplied with external VDD, a 
provision is made in the DS1820 to signal the power supply scheme used.
The bus master can determine if any DS1820’s are on the bus which 
require the strong pull-up by sending a Skip ROM protocol, then issuing 
the read power supply command.

After this command is issued, the master then issues read time slots.
The DS1820 will send back "0" on the 1-Wire bus if it is parasite 
powered; it will send back a "1" if it is powered from the VDD pin.
If the master receives a "0", it knows that it must supply the strong 
pull-up on the I/O line during temperature conversions.
See "Memory Command Functions" section for more detail on this command 
protocol.

von Peter D. (peda)


Lesenswert?

Mario Fischer schrieb:
> Aktiv auf Hi mit dem AVR-Port zu
> ziehen wollte ich nicht, da er sonst kaputt gehen kann wenns mal einen
> permanenten Kurzschluss auf dem Bus gibt.

Schau Dir meinen Code doch einmal an.
Ich teste vorher, ob ein Kurzschluß vorliegt.

Und falls genau wärend der Wandlung ein Kurzschluß erfolgt, der AVR 
sollte die 1s überstehen.
Kannst aber noch nen Pin-Change-Interrupt aufsetzen, der bei Kurzschluß 
sofort abschaltet.

Das mit dem 470R Widerstand ist Murx. Weder ist damit die Wandlung 
garantiert, noch ausreichender Low-Pegel vom Slave.


Peter

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.