Untersuchung und Verbesserung des Timings bei der Ansteuerung der DS18B20 Sensoren unter MicroPython

Für den Einbau der neuen DS18B20-Treiber in hiverize/FiPy brauche ich etwas Hilfe. Die Testprogramme nur mit DS18B20 und OLED laufen, aber in der BOB-Firmware gibt es Instabilitäten.
Im Testprogramm BOB-DS18B20.zip (24,2 KB) gibt es 3 Varianten:
onewire_a.py und ds18x20_a.py von @vinz,häufige Fehlwerte, CRC-Fehler nicht abgefangen
onewire_b.py und ds18x20_b.py von @robert-hh, häufige CRC-Fehler
onewire_c.py und ds18x20_c.py von @andreas, sehr seltene Messfehler, aber häufige Reboots in Hiverize/FiPy.
Leider sind x_c.py nicht ganz softwarekompatibel zu x_a.py und x_b.py

1 Like

Wir haben hier in Berlin ja nen kleinen Labor-Teststand eines Bob-Hats und im Dezember dort mal die neuste Firmware von @Andreas, FiPy-1.20.1.r1-0.7.0-vanilla-dragonfly-onewire-i2s.tar.gz, drauf getan: Das Ding lief 4.5 Wochen ohne Reboot durch! Denn ist vor ca. 2.5 Wochen jemand gegen das Kabel gekommen; seit dem gab es aber auch keinen weiteren Reboot.

ps.: Ja, dashboard-or-it-didn’t-happen: Grafana

1 Like

Bei mir taucht der Fehler auf, wenn ich versuche, die Treiber in hiverize/fipy der Uni Bremen (@Diren, @vinz und @caro ) einzubauen.
Ebenso wenig schaffe ich es, das Webinterface zur Konfiguration anzupassen.
Frage: mit welcher Software bearbeitet man die *.js, *.html und *.css Dateien für den Webserver?
Die *.py bearbeite ich mit Atom und pymkr.

So weit ich das weiß sind die “Webserver-Dateien”, also *.js, *.html und *.css, autogenerated von irgendeinem Framework das @vinz verwendet hat. Die sind nur komisch formatiert, daher doof in Atom zu bearbeiten, aber im Prinzip sollte man Atom dafür genausogut verwenden können. Die Frage ist nur, müssen wir sie händisch anpassen oder sollen / können wir das tool nehmen, da @vinz auch verwendet hat.

Sie sind viel zu unübersichtlich und vermutlich auch aufgebläht mit unnützem Zeug, da sie sehr gross sind.

1 Like

Hatte mir das Mal vor ein paar Monaten angeschaut.

Das verwendete Framework ist vue.
Gibt glaube ich dafür ein Plugin für Atom.
Für VisualStudio auf alle Fälle.
Das meißte davon ist das Framework. Das eigentliche von @vinz geschriebene Teil ist gar nicht so groß aber in unformatierten Text. Gibt aber Tools, die das wieder übersichtlicher und lesbar machen kann.

Gruß Micha

ImTestprogramm nur mit DS18B20 und OLED taucht kein CRC-Fehler auf, in hiverize/fipy dagegen alle paar Minuten:

67 . Messung
   DS18B20: Messung gestartet...
   BME280:  16.4 C 1022.4 mbar 38.8 %
   HX711:   6.7 kg
   DS18B20: 15.6 15.8 15.7 15.7 15.8 16.0
14:14:18 Prep: 3ms Init: 4ms Connect: 34ms SSL: 1797ms Header: 45ms Data: 1798ms Response: 245ms
{'t_i_1': 15.7, 't_i_2': 16.0, 't_i_3': 15.8, 't_i_4': 15.8, 't_i_5': 15.6, 'h': 38.8, 'weight_kg': 6.7, 'p': 1022.4, 't': 16.4, 't_o': 15.7, 'key': 'E421ET8aqCTmPBz2'}
stack: 896 out of 11264
GC: total: 2561344, used: 84912, free: 2476432
 No. of 1-blocks: 1541, 2-blocks: 361, max blk sz: 161, max free sz: 153467
#67, Seconds elapsed: 3.270s,time until next measurement: 1.730s
DS1820: 753ms + 153ms, BME280: 56ms, HX711: 756ms Log: 2970ms, GC: 300ms

68 . Messung
   DS18B20: Messung gestartet...
   BME280:  16.4 C 1022.3 mbar 38.8 %
   HX711:   6.8 kg
   DS18B20: 15.6 15.9 15.8 15.7 Error, dumping memory
### Fehler bei 5. Sensor
(, Exception('CRC error',), None)
stack: 656 out of 11264
GC: total: 2561344, used: 87616, free: 2473728
 No. of 1-blocks: 1689, 2-blocks: 368, max blk sz: 161, max free sz: 153467
GC memory layout; from 3f94eae0:
00000: MDFhhhhhhhh===hh=FFFMDFFFFhFSSSh=======h=====DMDSBMh==Dh==hDFFhS
00400: DDh====DhShSDhSh=======BBBhMDSBBBBShSMSBBhShB=BSDSShBBBh=======S

Der Fehler wird nicht sauber abgefangen in ds18x20_c.py

   def read_temp(self, rom):
        try:
            buf = self.read_scratch(rom)
            if rom[0] == 0x10:
                if buf[1]:
                    t = buf[0] >> 1 | 0x80
                    t = -((~t + 1) & 0xff)
                else:
                    t = buf[0] >> 1
                return t - 0.25 + (buf[7] - buf[6]) / buf[7]
            elif rom[0] in (0x22, 0x28):
                t = buf[1] << 8 | buf[0]
                if t & 0x8000: # sign bit set
                    t = -((t ^ 0xffff) + 1)
                return t / 16
            else:
                return None
        except AssertionError:
            return None

In main.py kommt dann die Fehlermeldung und Abbruch:

log("Starting measurement setup...")
wdt.feed()
try:
    if _config.get_value('networking', 'wlan', 'enabled'):
        log("WLan is enabled, trying to connect.")
        _wm.enable_client()
        _beep = logger.beep

        if _wlan.mode() == network.WLAN.STA and _wlan.isconnected():
            try:
                rtc.ntp_sync("pool.ntp.org")
            except:
                pass

            start_measurement()
        else:
            log("No network connection.")
            if ((_config.get_value('networking', 'accesspoint', 'enabled')
                    or _csv is None)
                    and not _config.get_value('general', 'general', 'button_ap_enabled')):
                enable_ap()
            else:
                start_measurement()
    else:
        log("No network connection.")
        _wlan.deinit()
        start_measurement()

except:
    log("Error, dumping memory")                              ##### hierher springt er
    log(sys.exc_info())
    micropython.mem_info(True)
    #machine.reset()

Software: FiPy-2001test.zip (88,9 KB)

Ich habe die Varianten a), b) und c) untersucht und bin auf folgende Probleme gestossen:

  • Timing:

In Variante a) und b) wird das Timing in onewire.py bestimmt:

def readbit(self):

sleep_us = time.sleep_us
pin = self.pin
pin(1) # half of the devices don't match CRC without this line
i = self.disable_irq()
pin(0)
# skip sleep_us(1) here, results in a 2 us pulse.
pin(1)
sleep_us(5) # 8 us delay in total
value = pin()
self.enable_irq(i)
sleep_us(40)
return value

Das führt zu häufigen Messfehlern.

Variante c) überlässt das Timing dem eingebauten MicroPython:

def readbit(self):
return _ow.readbit(self.pin)
Damit werden die CRC-Fehler sehr viel weniger.

  • Fehler-Erkennung

In Variante a) gibt es keinen CRC-Check. Damit werden auch fehlerhafte Bit weitergereicht und man wundert sich (nicht) über seltsame Messwerte. Das sind keine gültigen Werte.

In Variante b) und c) gibt es einen CRC-Check in ds18x20.py:

if self.ow.crc8(self.buf):
    raise Exception('CRC error')
  • Fehler-Behandlung

In Variante c) gibt es bei CRC-Error eine Exception, die abgefangen wird:

try:
    tmp = ds18b20.read_temp(rom)    # Messwerte auslesen
    ds18b20tmp = int(tmp*10)/10     # 1/10 °C
except:                             # CRC-Fehler
    ds18b20tmp =  9999              # Dummy-Wert

Ein gültiger Wert wird auf 1/10 °C begrenzt, da eine grössere Auflösung unsinnig ist.
Bei CRC-Fehler gibt es einen Dummy-Wert.

Ich habe ein kleines Testprogramm geschrieben :FiPy-DS18B20.zip (9,5 KB)

mit onewire_b.py kann man die CRC-Fehler gut erkennen.

  • Timing


Mit dem LogicAnalyzer erkennt man das
Starten der Messungen
Warten 750 msec
Auslesen von 6 Sensoren

Starten der Messungen : ds18b20.convert_temp()

Auslesen von 6 Sensoren : tmp = ds18b20.read_temp(rom)

Daten von einem Sensor

1 Like

Z.Z. traten im Testprogramm bei 24500 Zyklen * 6 Sensoren = 147000 Messungen ganze 3 CRC-Fehler auf.
nun sind es bei 40000 Zyklen * 6 Sensoren = 240000 Messungen 7 CRC-Fehler

Ergänzung am 1.2.2020

Beim Einbau der Treiber in Hiverize/FiPy erhöht sich die Anzahl der CRC-Fehler deutlich, vermutlich weil der Pozessor noch nebenbei andere Dinge wie WLAN usw. zu tun hat:
bei 7500 Zyklen * 6 Sensoren = 45000 Messungen sind es 97 CRC-Fehler.
Die werden durch eine Exception abgefangen ( siehe oben ).
Es gibt aber noch eine weitere Exception mit (noch) unbekannter Herkunft, die früher zu Reboots geführt hat. Sie taucht bei der Ausgabe bei OLED auf, immer nach einem CRC-Fehler, obwohl DS18B20 mit Onewire-Bus und OLED mit I2C-Bus in Hardware und Software nichts miteinander zu tun haben.
Ich kann sie dort abfangen:

...

         try:
            _oled.fill(0)                                         # alles aus
            _oled.text(str(cycle), 0, 0)
           ....
        except:
            print('OLED Fehler',end=' ')

Erklären kann es nicht.

Ergänzung am 2.2.2020

Die Software läuft ziemlich stabil, aber beim Start kann es vorkommen, dass nicht alle DS18B20 gefunden werden. Vielleicht kann jemand bei der Fehlersuche helfen?
FiPy-2001test.zip (88,9 KB)

2 Likes

Noch was zum 85 °C-Problem gefunden unter GitHub - cpetrich/counterfeit_DS18B20: How to tell original from fake DS18B20 temperature sensors.

Solution to the 85 °C-Problem

There is a simple, undocumented, way to discriminate between the power-up 85 °C-reading and a genuie temperature reading of 85 °C in authentic DS18B20 [5]: <byte 6> of the scratchpad register. If it is 0x0c , then the 85 °C-reading is a power-up reading, otherwise it is a true temperature measurement. Does not work with clones of Families B, C, or D, though.

1 Like

Dieses Problem wird in der Praxis kaum vorkommen: in allen mir bekannten Programmen wird

  1. conversion gestartet
  2. 750 msec gewartet
  3. Werte ausgelesen

Hi Clemens.

Das ist interessant, vielen Dank! Gib es doch bitte auch an @robert-hh weiter, am besten direkt bei GitHub - robert-hh/Onewire_DS18X20: Classes for driving the DS18x20 sensor with the onewire protocol for Pycom MicroPython.

Viele Grüße,
Andreas.

wird kaum nötig sein: er höchstselbst hatte dieses Fundstückt verlinkt. ;)

… es sei denn, Du wolltest ihn speziell auf die Möglichkeit der Unterscheidung zwischen Original und Fälschung per Treiber hinweisen. Ob er allerdings ein undokumentiertes feature dafür einbauen wollen würde?!

1 Like

Wir hatten die Diskussion bei den 85 °C-Werten, die ja nicht durch die CRC-Checks rausgefiltert werden, sondern als valide Messungen in der Datenbank landen. Mein damaliger Vorschlag war Werte mit 85 einfach zu ignorieren, d.h. statt dessen missings einzutragen. Für unsere Domäne wäre das kein Problem, weil wir weder beim Wetter noch bei den Bienen auf so hohe Temperaturen kommen. Robert wollte diese Ersetzung aber nicht generell machen, zu Recht, da es ja Anwendungsdomänen gibt, die schon mal auch genau 85,00 °C messen könnten. Nun ist die Frage, ob wir mit diesem Fundstück “richtige” Messungen von Fehlercode-85 unterscheiden können und die dann nicht als Messwerte behandeln.

1 Like

Wie denn? Das ginge nur bei den Originalen, - und die hat hier ohnehin keiner: wir brauchen uns nichts vormachen, praktisch alle vergossenen 18B20 in Hülsen aus China zum Preis des Einzelbauteil-Originals sind Fälschungen / clones. Bei diesen funktioniert dieser Test ohnehin nicht, also ist er lediglich dazu geeignet, Original von Fälschung zu unterscheiden - immerhin.

1 Like

Ahh, so pessimistisch war ich bisher noch nicht, hab auch die “teuren” für 5 EUR gekauft. :-) Aber ja, du wirst leider richtig liegen mit der Annahme … Das würde dann aber doch dafür sprechen, dass wir die 85,00 °C als missing definieren, weil sie vermutlich nur seeehr selten real auftreten und deutlich wahrscheinlicher als Fehlercode aufkommen.

@didilamken hast du bei deinen Messungen nach Einführung der CRC-Checks die realen Werte aufgezeichnet – im BOB backend werden Ausreißer ja seit einiger Zeit gefilter, d.h. ein Blick darauf bringt bei meinen Daten nichts – und kannst sagen wie häufig die 85,00 °C noch auftauchen?

Die 85.00 °C Fehler ohne CRC-Check tauchen (vermutlich) bei mir nie auf, da ich immer

aufrufe. Die realen Werte zeichne ich auf SD-Karte auf.

1 Like

Some note about using a GPIO pin instead of the 3V rail for supplying power…

Perhaps DS18B20 has been “reseted” every time before reading due to power cycle and so it seems to be more stable under an unstabel (software) driver but I see really no need to use a GPIO pin for power especially for the DS18B20 because it consumes – even in deep sleep and in ultra low power relations – nearly no power! So it’s a workaround for bad software but not a solution!

Weiter unten steht ja auch

After further investigation it seems like output current of 3V3 is not enough to supply all sensors on the board or the chinese prototype circuit board is just so thin that it is limiting the current. We moved the 5V to be supplied the battery directly and now it works, so clearly hardware related.

Finde so ein posting hier ist eher missleading und hat mit unserem Problem hier nichts zu tun. Didi hatte ja auch schon berichtet, dass es mit gleicher Hardware und dem Arduino-Sketch stabile Daten gibt, muss also ein Software-Problem sein!

Hi Clemens,

das Timing-Problem ist ja schon seit hundert Jahren dank Support modonewire from vanilla MicroPython by amotl · Pull Request #356 · pycom/pycom-micropython-sigfox · GitHub gelöst worden. Ich wollte nur drauf hinweisen, dass andere auch ihre Problemchen haben und niemanden in die Irre führen.

Viele Grüße,
Andreas.