Beiträge von miriki

    SQL
    INSERT INTO `werte`(`id`, `datum`,  `temp0`) VALUES ('',NOW(),3.7)


    Ich schätze, das Feld `id` ist ein automatisch generierter Wert? Dann laß es komplett weg aus dem INSERT.

    Außerdem gibt es Datums/Zeit-Felder, die sich bei Erzeugen/Update eines Datensatzes ebenfalls automatisch setzen. Das spart Dir dann ein weiteres Feld im INSERT Befehl.

    Gruß, Michael

    Und auch die Aesthetik von

    f.setMyProperty(g.getSomeProperty() * h.getOtherProperty())
    vs
    f.myProperty = g.someProperty * h.otherProperty
    ist in meinen Augen klar zum Vorteil des letzteren,

    Ich mußte jetzt erstmal kräftig ein paar Beiträge zurück blättern, um zu verstehen, daß (und warum) wir vermeintlich unterschiedliche Auffassungen haben. Eigentlich meinen wir (auch noisefloor) nämlich das Gleiche. Was aber in meiner ganz ursprünglichen Frage noch halbgar war, hatte ich schon lange erweitert, aber nicht weiter erwähnt.

    Ich hatte ursprünglich nur get/set in der Art:

    Code
    def getValue():
      return __Value
    def setValue( v ):
      __Value = v

    Das hatte ich zwischenzeitlich erweitert mit:

    Code
    property Value( getValue, setValue )

    Somit habe ich einen pseudo-direkten Zugriff auf die Attribute, kanalisiert aber über die get/set-Methoden, die nebenbei auch noch ggf. weitere Aktionen (oder wenigstens Prüfungen) durchführen.

    Ja, auch ich finde die 2. Methode übersichtlicher. Ich hatte die Diskussion mit

    Zitat

    Getter / Setter sind 'böse'


    nur insofern falsch verstanden, als daß ich es so aufgefaßt hatte, daß man immer lieber direkten Zugriff auf die Attribute zulassen soll und eben keine get/set-Methoden zwischenschalten soll (darf).

    Zitat

    idiomatisch Python programmieren lernen, oder eben dein Ding machen. Beides ist ok, wenn du dich mit letzterem bei mir bewirbst, wirst du abgelehnt :)


    Idiomatisch nur um der Idio(ma)tie Willen? Nein. Es "vernünftig" machen, aber ohne krampfhaft auf Teufel komm raus mir alles vorschreiben zu lassen? Ja. Mich woanders bewerben? Ganz sicher nicht. ;)

    Zitat

    ich moechte aber noch mal das Thread-Thema aufgreifen:


    Gut, daß Du es machst, denn ich hätte demnächst zu diesem Punkt hier eh nachgehakt. Mein aktuelles Projekt ärgert mich und ich will nicht ausschließen, daß "Threading" vielleicht einer der Auslöser für die Probleme ist, die ich gerade damit habe. Mir fehlt aber im Moment auch noch die Idee, wie ich es anders hinbekommen könnte.

    Zitat

    eine Bibliothek, die mich mit unkontrollierten Threads beglueckt, sehe ich kritisch.


    Naja, das würde ich nicht so sehen. Gerade auf dem relativ weit unten angesiedelten Niveau einer Interpreter-Sprache ist das "unkontrolliert" eigentlich in sehr enge Grenzen verwiesen. Ein Binary aus einem C-Kompilat, das seinerseits vielleicht auch noch weitere, fremde Binaries verwendet, ist für mich da schon sehr viel eher ein Grund für Skepsis.

    Ich sehe eine Bibliothek aber eben gerne als "black box", bei der ich mich von "außen" nicht darum kümmern muß, wie sie arbeitet. Das bedeutet, daß ich, am Beispiel dieser simplen Sensoren, mich eben auch nicht darum kümmern will, wie ein i2c-Bus funktioniert und wann / wie ich Werte aus dem Sensor auslesen kann. Ich will die Bib einfach nur benutzen, um ein Objekt zu erschaffen, das mir Werte auf Abruf liefert. Soweit aus Sicht des Anwendungs-Programmierers...

    Der Bibliotheks-Programmierer wiederum muß sich darum kümmern, mit den nur absolut notwendigen Parametern zumindest ein funktionierendes Objekt zu erschaffen. Dazu gibt's dann sinnvollerweise Default-Werte und alles darüber hinaus sind dann "Bonscher", die die Sache runder machen. Auch der Bib-Programmierer muß sich aber normalerweise nicht mehr um die Schicht darunter kümmern, sondern kann seinerseits auch wieder diese als "black box" betrachten. So muß die Bib z.B. nicht wissen, mit welchen Pegeln und welchen Timings der i2c-Bus arbeitet. Es gibt eine API, die regelt, mit welchem Befehl ich einen Modus setze, mit welchem ich einen Wert (oder Datenblock) auslese usw.

    Zitat

    Threads sind zum einen *hart*. Es sieht einfach aus, aber du bekommst zB eine beliebiege Reihenfolge von unzusammenhaengenden I2C-Aufrufen auf deinen Bus. Ob und welche Konsequenzen das hat, haengt jetzt von den intimen Details der smbus-Modul-Implementierung ab. Kennst du die?


    Nein, kann und will ich auch gar nicht. Wenn der low-level-Treiber spackt, gibt's eine Fehlermeldung an den Programmierer des Treibers. ;)


    Zitat

    Zeitpunkt der Ermittlung und Abfrage der Werte liegen auseinander. Wie lange haengt vom Zufall des Schedulings ab, und wird bei zunehmender Anzahl von Threads immer unvorhersehbarer.


    Das ist jetzt aber sehr allgemein und hat eigentlich mit dem "Spielkram", den der RasPi und z.B. ein DS18B20 liefert, nichts mehr zu tun. Eine Hochgeschwindigkeits-Präzisions-Temperaturmessung, bei der ich Werte mit 3 Nachkommastellen im Millisekunden-Intervall bekomme (ja, sowas führen wir bei uns in der Firma durch), führe ich garantiert nicht mit einem RasPi durch. Da bin ich schon froh, wenn er eine sleep(1000) nach nur 1100 abgearbeitet hat.

    Zitat

    Ich moechte vielleicht Sensor A schnell, und Sensor B nur ab und zu auslesen. Geht nicht.


    Klar geht das, aber noch nicht mit dem Source aus den Anfängen dieses Threads. Ich bin aber gerade dabei, die Sensoren als Klassen zu kapseln. Und da hindert mich ja niemand, 2 oder mehr Sensoren zu "erschaffen". Ob die Architektur des Bus-Systems oder die des low-level-Treibers das noch mitmachen, mag dann auf einem anderen Blatt stehen...


    Zitat

    - Der PI ist resourcen-beschraenkt. Mehrere Threads bedeuten ggf. langsamere Ausfuehrung deines Haupt-Threads, weil das Scheduling und Task-Switching halt nicht umsonst ist.
    - Ereignisbasierte Programmierung durch zB callbacks wird schwieriger - die laufen wenn man nicht aufpasst in verschiedenen Threads, und treten sich auf die Fuesse.
    Insgesamt finde ich dafuer eine gute Loesung zu finden wesentlich relevanter als die Frage, ob und wo man nun getter/setter nutzt oder wie privat etwas sein soll.

    Ich finde einen Hintergrund-Thread, der Meßwerte akzeptabel aktuell und mit Timestamp bereit stellt, quasi ähnlich einem Cache, im Moment noch die einzig sinnvolle Lösung. Wenn das "main" Programm die Parameter allerdings in irrsinnige Bereiche schiebt und z.B. den Sensor jede Millisekunde aktiviert, dann wird's blöd. Aber das kann die Bib ja in gewissen Grenzen durch die Setter eindämmen. Wenn der DHT22 z.B. nur alle 2 Sekunden einen Wert liefert, dann kann setInterval(v) prima dafür sorgen, daß das Polling nicht häufiger angeschubst wird.

    Ich hatte mich seinerzeit aber selbst ins Bockshorn gejagt: Ich schrieb sowas in der Art wie "threading oder mittels after()". Und dabei hatte ich vergessen, daß after() ja wohl nur in der GUI zur Verfügung steht, während man in der CLI darauf verzichten muß. Oder gibt's da eine Alternative?

    Und auf Ereignisse + Callback würde ich auch gerne verzichten. Die sind mir (zumindest in den anderen Sprachen, die ich bislang verwende) immer sehr suspekt und machen leider auch viel Probleme.

    Wie gesagt: Bislang (habe noch nichts Gegenteiliges feststellen können) ist mir ein Hintergrund-Thread noch am ehesten sympathisch. Die aktivierende Methode wird sauber durchlaufen und beendet (keine "while AppRunning:" Endlos-Schleife). Einzig die etwas aus der Hand gegebene Kontrolle beim threading ist mir nicht immer ganz geheuer. Führt dies doch auch mal dazu, daß das "main" mit einem Fehler abbricht und der Thread glatt weiter läuft. Irgendwie auch blöd... ;) Aber bisherige Versuche mit bis zu 6 Sensoren brachten den RasPi nun wirklich noch nicht an seine Leistungsgrenzen. Ich sehe eher die Echtzeit-Sprektum-Analyse eines internet-Radio-Streams als Problem, aber weiß Gott nicht die Sensor-Abfragen im 10-Sekunden-Takt. ;)

    Gruß, Michael


    `machwas()` ist eine Methode von `xxx`. Wenn du eine Instanz von xxx erzeugst, funktioniert das auch.


    Das war mir klar. Mir ging's mehr um die Verwendung von __yyy. Ich renn sonst immer gerne mal in die Fehlermeldung (wegen eines Vertippens), daß ich eine Variable vor Initialisierung benutzen würde. Und ich hätte jetzt auch erstmal gedacht, daß __yyy nur eine lokale Variable im __init__ bleibt und danach wieder weg ist, somit für machwas nicht (mehr) zur Verfügung steht.

    Anders formuliert: Eine Variable, die ich im __init__ mit einem Wert belege (und damit "erzeuge"), bleibt danach Klassen-weit verfügbar, auch wenn ich sie nicht vorher bereits im globalen Klassen-Teil deklariert habe?

    Mir ist auch klar, daß zzz mit z.B. return auch irgendwie weiter verarbeitet werden muß. Mir ging's nur um die Verwendung von __yyy.


    Zitat

    Wie gesagt, das mit den 2 Underscores ist nicht wirklich sinnvoll.


    Das sieht tutorialspoint aber etwas anders... ;)

    Zitat

    Python forciert das aber nicht, das ist "nur" eine gängige Konvention.


    Die _2_ Underscores werden da aber durchaus anders behandelt. Das geht über eine Konvention hinaus.

    Zitat

    An object's attributes may or may not be visible outside the class definition. You need to name attributes with a double underscore prefix, and those attributes then are not be directly visible to outsiders.
    [...]
    Python protects those members by internally changing the name to include the class name. You can access such attributes as object._className__attrName.


    Also auch hier kein echtes "private", aber schon ein bißchen verstecken und verschleiern.

    Gruß, Michael

    Dann ist aber kein Setter im eigentlichen Sinne, sondern eine Methode. [...]
    Das ist dann aber keine Getter, sondern entweder eine Methode oder eine Property - je nach dem, was / sinnvoll gewünscht ist.


    Ich würd mir eine klare Definition wie im VB.Net wünschen. Da hab ich durch "public property ..." geklärt, daß es eine Property ist, danach folgen get und/oder set Methoden. Ich find auch die klare Unterscheidung in "sub" und "function", also eine Methode, die einen Funktionswert zurückliefert, lesbarer. Aber man kann eben nicht alles haben... ;)


    Zitat

    Dann gehört alles in die __init__ Methode.


    Versteh ich das richtig: Ich brauch keine Deklaration im globalen Header, um im __init__ den Wert einer Variablen zu setzen und sie danach für alle Methoden in der Klasse verfügbar zu machen? Also verkürzt:


    Und das
    a) gibt keine Fehlermeldung bei Aufruf von z.B. "machwas( 3 )"?
    b) erzeugt eine _lokale_ Variable im Objekt
    c) ist auch eine (nur) halbwegs private Variable


    Zitat

    Und, wie gesagt, echt privat gibt's nicht. Beispiel:


    Yep, so hatte ich tutorialspoint, letzter Abschnitt "data hiding", verstanden.

    Gruß, Michael

    In Python sind getter und setter verpoent.


    Na, das kann man so pauschal auch nicht sagen. Eine Google-Suche nach "python @property" ergibt endlos viele Treffer auf Diskussionen, ob nun das eine oder andere "richtig" oder "besser" oder "stilvoller" oder was-auch-immer sei.

    Recht schön ist eine bei Stack Overflow.

    Was ich unterstütze: Keine Getter/Setter, die einfach nur die Werte durchreichen. Ohne weitere Prüfung oder Adaption der Werte kann man auch den direkten Zugriff auf die Variable zulassen. Besser _lesbar_ finde ich die Getter/Setter-Schnittstelle aber grundsätzlich immer. Schade nur, daß es eben in Python durch das fehlende "private" jederzeit ausgehebelt werden kann. Aber wie gesagt: Wenn jemand meint, von "außen" z.B. die __LoopThread Variable verändern zu müssen, dann ist das sein ureigenstes Problem.


    Zitat

    macht man *alles* *immer* in getter/setter, [...] Es ist also eine Schwaeche.


    Das kann man unterschiedlich sehen. Ich mag Java wirklich nicht besonders, aber ich war schon immer ein Freund von (im Kopf des Source, Stichwort "option explicit" in BASIC) deklarierten Variablen und finde die zwangsweise Schnittstelle über Getter/Setter zum Objekt eine sinnvolle Fortführung.

    Zitat

    Auch Mikrooptimierungen wie das setzen nur, wenn der Wert ungleich ist, sind fuer diesen Fall ueberkandidelt und im Zweifel sogar langsamer. Falls Geschwindigkeit hier Trumpf gewesen sein sollte.


    Nein, das war nur Vorbereitung für eigentlich weiterführende Aktionen. Wie gesagt: Nur Durchreichen ist eigentlich nicht meine Intention. Das "IF" sollte später also auch schon seinen "ELSE" Zweig bekommen.


    Zitat

    Statt permanent prints ein und auszukommentieren, bietet sich die Verwendung des logging-Moduls an.


    Ja, gesehen hatte ich das schon, aber mich noch nicht weiter mit beschäftigt. Bislang reicht mir ein simples "print", aber stimmt schon, für später ist das sicher sinnvoll.


    Zitat

    Es ist eine schlechte Idee, fuer jeden Sensor einen Thread zu starten.


    Das ist eben das, wo ich mir noch nicht so ganz sicher bin, warum...

    Letztendlich, was macht es für einen Unterschied, ob ich eine "while true" Schleife in einen Hintergrund-Thread verbanne oder eine "self.after" Schleife (etwas mehr) im Vordergrund laufen lasse? Ich finde es eigentlich sympathischer, wenn die Methoden im Objekt selbst "abgeschlossen" werden, also quasi das "exit sub" erreichen und nicht in einer Schleife hängen bleiben.

    Zitat

    Einfach eine Property zB "value", die einen float-Wert wiedergibt.


    Die "typische" Eigenschaft eines Objekts ist ja immer wieder gerne "Value". Ich bin mir noch nicht ganz sicher, ob ich das benutzen werde oder nicht. Ich tendiere eher zu "getLumen" in diesem Fall, weil es z.B. beim BME280 ganze 3 Werte gibt, die der Sensor liefert. Das könnte ich in Python natürlich auch per Tuple oder sonst irgendwie lösen. Aber "getTemperature", "getHumidity" und "getPressure" sind mir da irgendwie sympathischer.

    Gruß, Michael

    Kommst du aus der Java-Ecke? Stilistisch passt das eher dahin...


    Eher VB.Net, wenn auch mit Pascal (später Delphi) aufgewachsen. Aber ja, auch Java (Android) und ein wenig C#. (Der Rest wie Logo, Lisp, Natural, Cobol, Forth, Algol, Comal usw. spielt hier wohl weniger eine Rolle...)


    Zitat

    "Private" gibt's nicht in Python


    Ok, so hatte ich es verstanden, ist also bestätigt. Muß ich nicht gut finden, aber mich damit abfinden.

    Zitat

    Getter und Setter wie du sie nutzt, sind in Python komplett überflüssig.


    Sie sind, so wie sie jetzt da stehen, auch noch nicht endgültiges Stadium.

    Setter: Neben dem Test, ob der Wert sich ändert, sollen ggf. noch weitere Aktionen durchgeführt werden. Das kann vom einfachen Setzen eines "dirty" Flags bis hin zur kompletten Neu-Initialisierung so ziemlich alles sein.

    Getter: Ich will tlw. Werte erst dann berechnen / auslesen, wenn sie abgerufen werden. Andererseits setze ich tlw. gelesene Werte im Getter danach auf "None", um dem Hauptprogramm z.B. zu signalisieren, daß (noch) kein aktualisierter Wert vorliegt.

    Zitat

    Die __init__ Methode kommt normalerweise an den Anfang der Klasse und die Default-Wert werden nicht über setter zugewiesen, siehe oben.


    Ok, leicht umzusetzende Kosmetik.

    Zitat

    Du definierst außerdem eine Reihe von Variablen auf Klassenebene, die dann für _alle_ Instanzen der Klasse global gelten. Willst du aber vermutlich nicht?


    Richtig. Das hatte ich auch schon so gelesen, war mir aber nicht sicher, ob ich das so richtig verstanden hatte. In dem Beispiel wurde ein Mitarbeiter-Zähler global mitgeschleift. Ja, _so_ will ich die globalen Variablen eigentlich wirklich nicht haben. Sie sollen lokal (und privat, ja...) in der jeweiligen Instanz sein.


    Gruß, Michael

    In welcher Sprache bewegen wir uns denn jetzt? Pyhon? C? Bash?


    Nach wie vor Python. Aber das Python-Script wird über die Bash und den Python-Interpreter gestartet. Und wenn's da zum i/o-Error 5 kommt, ruf ich eben über die Bash auch noch schnell mal i2cdetect auf.

    Also so in der Art:

    - i2cdetect
    - python bh1750.py
    - Sensor-Werte (loop)
    - Ctrl-C
    - 5 Minuten am Prompt stehen
    - python bh1750.py
    - i/o-error 5
    - i2cdetect
    - python bh1750.py
    - Sensor-Werte (loop)

    Zitat

    Schreibst Du einen Resetbefehl in deinem Script?


    Es gibt folgende Schreib-Operation im Script - ziemlich am Anfang, vor dem ersten Auslesen:

    Code
    bus.write_byte_data( device, reg_control, control )


    device ist 0x76, reg_control ist 0xF4, control ist

    Code
    oversample_temp << 5 | oversample_pres << 2 | mode


    wobei die beiden oversample-Werte 2 und der mode 1 sind.

    Danach werden 3 Blöcke Daten (u.a. Kalibrierung) ausgelesen und in für mich noch nicht so ganz nachvollziehbarer Art verwurstet.

    Dann wird nochmals ein Block Daten (Rohdaten) ausgelesen und ebenfalls vergniesgnaddelt.

    Und das war's dann auch schon.

    Zitat

    Wenn man zwischen dem schreiben des Messbefehls und dem Lesen keine Pause macht liest man noch den alten Wert, weil der Sensor noch nicht mit der Messung fertig ist.


    Ja, hatte ich auch irgendwo gelesen. Deswegen hatte ich auch mit einer kleinen Zwangspause probiert.


    Zitat

    Hast Du schon eine Lösung gefunden?


    Leider noch nicht. Die Baudrate und die Zwangspause brachten bei den bisherigen Tests keine Änderung.

    Irgendwas macht i2cdetect an Initialisierung auf dem Bus, was ich auch gerne beim Start des Python-Scripts machen würde. Aber ich weiß eben nicht, was...

    Gruß, Michael

    Moinsens!

    Ich bastel mir gerade ein Klassen-Modul zum Auslesen eines Sensors. Für den Anfang hab ich mir mal den BH1750 (Helligkeit) genommen. Aber dieses Klassen-Modul soll quasi ein Template werden, um dann für andere Sensoren (BME280, DHT22, DS18B20, ... ) kopiert / angepaßt zu werden.

    Funktionieren tut's soweit. Aber da ich in Python noch nicht so firm bin, frage ich mal in die Runde, ob der u.a. Source-Aufbau so richtig und sinnvoll ist.

    Das Haupt-Programm, in dem der Sensor geladen und ausgewertet wird:
    classtest.py

    Und dann das Klassen-Modul zum Auslesen des Sensors:
    bh1750_class.py

    Ich versuche eigentlich grundsätzlich, globale Variablen nicht direkt anzusprechen, sondern immer über get/set-Routinen zu gehen. Sehe ich das richtig, daß Python aber kein echtes "private" kann, sondern das nur mit den '__' etwas verschleiert? Ich würd's eigentlich nicht so witzig finden, wenn jemand im Hauptprogramm direkt z.B. die __LoopThread Variable verändern kann. Ok, wäre sein Problem, aber ein echtes "private" wäre schon schön...

    Außerdem würde ich gerne einige Getter "public" und die zugehörigen Setter "private" haben. Das Objekt selbst soll ja durchaus in der Lage sein, die Werte über den Setter zu aktualisieren, aber das Hauptprogramm soll die Werte eigentlich nur noch über die Getter auslesen können.

    Ist Threading hier ok? Ich könnte das ja auch umstellen und mit self.after(... arbeiten. Das würde das Starten/Stoppen des Sensors auch vielleicht etwas einfacherer / sicherer machen, als irgendwo einen wilden Thread im Zaum zu halten.

    Gruß, Michael

    Ich habe auch ein RasPi 3.


    ;) Deswegen schrieb ich extra: Der Prompt zeigt nur meinen 2. oder 3. RasPi, es sind aber beides 2+ Modelle, keine 3er. (Und RasPi1, ebenfalls ein 2+, läuft seit einigen Monaten als Web- und Mud-Server hinterm Fernseher in einer Ecke im Wohnzimmer.)

    Zitat

    Wie sieht denn die Auslastung des RasPi aus wenn Du die Fehlermeldung bekommst? Ist dein RasPi übertaktet?


    Keine Übertaktung und Auslastung vernachlässigbar gering. Selbst 2 Sessions mit jeweils einer Python-Instanz und einem Dauerlauf-Script sowie einer 3. Session mit "top" bringen den RasPi kaum über 0,3us.

    Zitat

    Was Du noch versuchen könntest, ist probehalber mal die Baudrate des I2C Bus ändern


    Ok, ja, das werde ich mal angehen. Ja, sie steht bei mir auf 100000.

    Was mir aber heute abend so beim Herumprobieren aufgefallen ist:

    Ich hab mir ein Template zum allgemeinen Sensor-Auslesen geschrieben. Das funktioniert im Groben so:
    a) die "main" Schleife schaut im 1-Sekunden-Takt (einstellbar) in der globalen Variable "SensorValue" nach, ob etwas "ungleich None" drinsteht. Wenn ja, wird ein formatierter String ausgegeben und SensorValue auf "None" gesetzt.
    b) Ein Hintergrund-Thread liest im 10-Sekunden-Takt (einstellbar) den Sensor aus und speichert den Wert in der globalen SensorValue.
    c) Ein 2. Hintergrund-Thread, wenn aktiviert, schreibt im 10-Minuten-Takt (einstellbar) die gesammelten Werte in ein Log-File - Damit werden die Schreibzugriffe reduziert. (Liste aus CSV-Zeilen im Arbeitsspeicher, die nach dem Schreiben ins Log geleert wird)

    Beim BME280 scheint die Sensor-Schleife bei irgendwas zwischen 5 und 6 Sekunden kritisch zu werden. Nach ein paar Minuten bricht das Script mit dem altbekannten i/o-error 5 ab. Bei 7,5 Sekunden z.B. nach 2 Minuten, bei 7,0 Sekunden nach 3 bis 4 Minuten usw. Bei 5 Sekunden läuft das Script jetzt seit ca. 1/2 Stunde stabil durch.

    Jetzt das Merkwürdige:

    Ich hab eine 2. Session aufgemacht und dort den BH1750FVI mit dem entsprechenden Script (Ablauf s.o.) aufgerufen. Beide Sensoren stecken auf dem gleichen Breadboard und teilen sich den i2c. Der Helligkeits-Sensor wird im 10-Sekunden-Intervall ausgelesen.

    Beim Start des 2. Script scheint es auch Einfluß auf den 1. Sensor, also den BME280, zu haben. Jetzt wirft der mir nämlich plötzlich im Wechsel (fast genau abwechselnd, manchmal auch 2 gleiche Werte hintereinander) 640 bzw. 1015 für Luftfruck und entsprechend 19,5 bzw. 21,3 Grad für Temperatur aus. Der Wert für die Luftfeuchtigkeit bleibt bei 58 Prozent stabil. Nachdem ich jetzt das 2. Script in der anderen Session abgebrochen habe, liefert der BME280 wieder konstante Werte 58, 19,5 und 1015 zurück.

    Irgendwo hatte ich beim googeln noch einen Hinweis gefunden, wo jemand einfach auf die Adresse des BME280 ein 0xAA geschrieben hat und damit seine i/o-error behoben hatte. Das will ich noch ausprobieren, wenn ich weiß, was genau das eigentlich bewirken soll. Aber es klang so nach einem Timeout-Problem.

    Und woanders fand ich noch den Hinweis, zwischen den Lese- und ggf- Schreib-Operationen unbedingt noch eine kleine Zwangspause (0,5 Sekunden ca.) einzubauen, um ein "Verhaspeln" des Sensors zu verhindern. Auch das werde ich noch Ausprobieren.

    Gruß, Michael

    PS: Zu früh gefreut... Die 5-Sekunden-Schleife ist soeben nach 45 Minuten abgeschmiert mit dem i/o-error.

    Code
    sudo apt-get update
    sudo apt-get upgrade


    Das läuft hier auf allen RasPi schon per Cron-Job täglich, wenn sie über Nacht laufen.

    Zitat

    Das merkwürdige ist, dass die Kommunikation ja eigentlich funktioniert.


    Genau, hier scheint auf dem RasPi3 irgendwas geringfügig anders zu sein, als auf dem RasPi2 (also: mein 2. und 3. RasPi, es sind beides 2+). Was ich gerne herausfinden würde: Was macht i2cdetect mehr, als einfach nur die Sensoren zu scannen? Da scheint ja noch eine Art Initialisierung des i2c zu passieren, die beim i2cget oder i2cdump nicht passiert.

    Wenn man diese Initialisierung bei jedem Script am Anfang mit einbaut, wäre das Problem ja gelöst. Denn wenn das Auslesen erstmal funktioniert, dann läuft es auch durchgehend weiter.

    Gruß, Michael

    Der Druck entspricht nämlich ungefähr dem Druck auf der Zugspitze, oder Du hattest sehr schlechtes Wetter. ;)


    Naja, im norddeutschen Flachland herrscht dieser Druck normalerweise wohl eher nicht. Aber unser Wetter hier würden die meisten wohl trotzdem als "sehr schlecht" bezeichnen. ;)

    Zitat

    Doofe Frage: Du sagtest Du hast den Sensor zwei mal. Macht der zweite die gleichen Probleme?


    Ich hab den 2. noch nicht angeschlossen, aber ein anderer Sensor BH1750FVI (Helligkeit), der ebenfalls über i2c läuft, macht, wie ich mittlerweile festgestellt habe, genau das gleiche Problem. Nach i2cdetect funktioniert er klaglos stundenlang. Aber einmal paar Minuten Pause und dann gibt's den I/O-Error. Das scheint aber auf _diesem_ Pi symptomatisch, denn auf dem anderen, an dem der 1750 schon seit einigen Tagen läuft, hatte ich dieses Problem bislang noch nicht.

    Zitat

    Wie weit ist es vom Pi bis zum Sensor und was nimmst Du für Kabel? Die einfachen Jumper Kabel sollte es tun.


    Yep, einfache 20cm Jumper-Kabel.

    Zitat

    Achso. Und woher kommt eigtl. Die Ausgabe für MSB LSB und xLSB?


    Die hab ich mit eingebastelt auf die Schnelle.

    Gruß, Michael

    Hast Du auch das gleiche Problem, wenn Du mehrfach hintereinander mit I2Cget den Wert abfragst?


    Wenn der Sensor erstmal "weg" ist, bleibt es kontinuierlich beim "read error". Wenn ich i2cget in kürzeren Abständen aufrufe, scheint der Sensor aber "aktiv" zu bleiben. Nur, wenn ich dann länger mal den Prompt stehen lasse und es dann wieder versuche, gibt's den Fehler. Dann ist i2cdetect fällig und es geht wieder. ("länger" = ein paar Minuten)

    Zitat
    Code
    gcc -o main BME280_neu.c

    und führe sie aus.


    Jau, funktioniert, so grundsätzlich. Aber ich mußte mehrmals Mit Ctrl-C abbrechen und neu starten, bis die Temperatur einen sinnvollen Wert bekam. So nach dem 3. oder 4. Start paßte es dann:
    (Glaub mir: Bei 0,15°C würde ich hier nicht sitzen wollen... ;) )

    Ach, und übrigens: Wenn der Sensor "weg" ist, krieg ich mit Deinem Programm trotzdem wieder Werte raus. Und: Das erste i2cget danach liefert dann anscheinend jedesmal 0x80, jedes weitere dann wie gehabt 0x00.

    Gruß, Michael

    Hast Du mal versucht das Programm als root auszuführen, bzw. ist der Benutzer pi in der Gruppe i2c?

    Ich hab jetzt nochmal die ganze Seite von

    http://www.netzmafia.de/skripten/hardw…/RasPi_I2C.html

    durchgeackert. Das meiste war schon erledigt, aber einen Tippfehler in /etc/modules fand ich noch. i2x-dev war wohl nicht ganz richtig.

    Das alleine war's aber nicht. Und zwischenzeitlich ging sogar i2cget gar nicht mehr.

    Aber letztendlich, nach einem weiteren reboot dann endlich:

    Code
    pi@raspi3:~/python/sensors/bme280 $ python bme280.py
    Chip ID     : 96
    Version     : 0
    Temperature :  21.33 C
    Pressure :  639.116544721 hPa
    Humidity :  58.4384104504 %

    Ich weiß letzten Endes noch immer nicht, woran es nun genau lag. Aber was zählt ist ja das Ergebnis. ;)

    Gruß, Michael
    Automatisch zusammengefügt:

    Ich weiß letzten Endes noch immer nicht, woran es nun genau lag. Aber was zählt ist ja das Ergebnis. ;)

    Nachtrag:

    Von Zeit zu Zeit gibt's durch das Script wieder den i/o-error. Dann geht auch i2cget nicht mehr. Es sieht aber so aus, als wenn ich dann durch i2cdetect den Sensor wieder "aufgeweckt" kriege und dann das Script wieder funktioniert.

    Kann das irgendeine "standby"-Funktion sein, oder ist das jetzt nur Zufall?

    reproduzierbar:


    Gruß, Michael

    D0 ist das Chip ID Register


    Hmpf... Da hätte ich auch selbst drauf kommen können. Im Script steht ja eindeutig und klar verständlich:

    Code
    def readBME280ID(addr=DEVICE):
      # Chip ID Register Address
      REG_ID = 0xD0
      (chip_id, chip_version) = bus.read_i2c_block_data(DEVICE, REG_ID, 2)
      return (chip_id, chip_version)

    Ich hatte mir noch mit

    Code
    print DEVICE


    ausgeben lassen, ob auch wirklich die 118 ankommen. Ja, tun sie.

    Und auch ein

    Code
    global bus


    brachte keine Besserung.

    Zitat

    Hast Du mal versucht das Programm als root auszuführen, bzw. ist der Benutzer pi in der Gruppe i2c?


    Das Script mit

    Code
    sudo su
    python bme280.py


    brachte leider nach wie vor den gleichen Fehler. Und auch

    Code
    sudo usermod -aG i2c pi


    macht die Sache nicht besser.

    Gruß, Michael

    Versuche es mal mit

    Code
    i2cdump -y 1 0x76


    Da sollten alle Register ausgelesen werden und zumindest das ChipID Register sollte dann 0x60 sein. Drei weitere Register sollten 0x80 sein.

    Ich weiß ja jetzt nicht, welches das ChipId Register ist, aber einige 60er-Werte sehe ich, auch einige 80er:

    Gruß, Michael

    Kommentiere doch in main einfach mal deie Stelle aus.

    Naja, damit verlager ich das Problem nur auf die nächste Zeile:

    Code
    pi@raspi3:~/python/sensors/bme280 $ python bme280.py
    Traceback (most recent call last):
      File "bme280.py", line 163, in <module>
        main()
      File "bme280.py", line 156, in main
        temperature,pressure,humidity = readBME280All()
      File "bme280.py", line 74, in readBME280All
        bus.write_byte_data(addr, REG_CONTROL, control)
    IOError: [Errno 5] Input/output error

    Gruß, Michael

    Moinsens!

    Ich hab letztens als "Bonscher" bei einer Bestellung zusätzlich 2x den BME250 (blueberry) zugeschickt bekommen. Das ist ein kleines Breakout-Board mit 6 Pins. Wenn ich es richtig verstanden habe, dann sollte ich mit folgender Verkabelung hinkommen:
    1 (GND) mit schwarz an Pin 6 des RasPi
    4 (SDI/SDA) mit blau an Pin 3
    5 (SCK/SCL) mit gelb an Pin 5
    6 (3V3) mit rot an Pin 1

    Im Gegensatz zu anderen Modulen mit diesem Sensor unterscheidet sich dieser hier:
    a) Adresse ist 0x76 (sonst üblich wohl eher 0x77)
    b) ausdrücklich nur 3,3V (sonst üblich wohl 3,3 bis 5V)

    i2cdetect findet das Modul, ein Python-Script zum Auslesen der Sensor-Werte schmiert aber weg:

    (Nicht durch den Prompt verwirren lassen: Das ist kein RasPi3, sondern nur mein 3. RasPi.)

    Das komplette Script habe ich aus dem Beitrag auf der Seite
    http://www.raspberrypi-spy.co.uk/2016/07/using-…nsor-in-python/
    per

    Code
    wget -O bme280.py http://bit.ly/bme280py


    geholt.

    Mein Problem jetzt: Ich weiß nicht so recht, wo ich jetzt ansetzen soll, den Fehler zu beheben. Die Verkabelung scheint ja ok zu sein, wenn i2cdetect das Dng findet, oder? Und die Adresse 0x76 im Script ist das Einzige, was anzupassen wäre.

    Kann mir hier jemand helfen?

    Gruß, Michael

    Moinsens!

    Ich hab mir den Helligkeits-Sensor BH1750FVI (aka GY-30) zugelegt und auch bereits erfolgreich an den RasPi2 angeschlossen. Nun möchte ich aber für meine Dokumentation das auch gerne mit einem Fritzing-Projekt hinterlegen. Aber dort scheint es dieses Sensor-Modul irgendwie nicht zu geben.

    Was ich habe:

    Und was ich bislang nur immer wieder für Fritzing finde:

    Wenn man das Modul, wie im Bild, um 90° dreht, sind die Pins nicht mehr sauber über dem Breadboard. Und was viel mehr stört: Die Pin-Belegung an der Unterkante ist eine andere.

    Von daher: Gibt es ein Fritzing-Modul, das dem oberen Bild entspricht?

    Gruß, Michael
    Automatisch zusammengefügt:

    Wenn man das Modul, wie im Bild, um 90° dreht, sind die Pins nicht mehr sauber über dem Breadboard.


    Ok, das hat sich erledigt - Das Breadboard ist "krumm", nicht das Sensor-Modul. Hab ich vorhin übersehen, da ich das "kleine" Breadboard normalerweise nicht benutze.