Temperatursteuerung mit Anzeige und verschiedene Sensoren

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo zusammen,

    zu erst ein mal ich Habe noch nie mit Python programmiert aber mit Visual Basic 6.

    ich versuche gerade mein Raspb. welches mit Raspbian Stretch with desktop läuft. Alles zusammen zu bekommen.

    Derzeit läuft jeder Sensor / Aktor für sich. in sogenannte Beispieldateien.

    Ich habe es geschafft, dass die Zeit sekündlich auf dem Display erscheint und nun sollen aber auch die anderen Temperaturfühler angezeigt werden.

    Und zwar dann, wenn sie ausgelesen sind das dauert bei den 1 Draht mitunter länger als eine Sekunde.

    Bei den i2c bekomme ich denn Quellcode nicht zusammengesetzt (Imports)

    Weil es noch nicht kompliziert genug ist soll das Programm auch noch automatisch starten, was es auch schon macht ABER irgendwie macht er für die i2c Beispiele bei den Importen was falsch da liegen die Dateien nicht im Home Verzeichnes was (ich denke) ihn aus dem Takt bringt.

    Derzeit ist der Autostart über eine launcher.sh welche im crontab eingetragen worden ist.

    Irgend wann möchte ich das auch noch Grafisch darstellen. Thema (from tkinter import *):huh:

    Das ist leider eine Menge Holz

    Danke für eure Tips

    :danke_ATDE:

  • Temperatursteuerung mit Anzeige und verschiedene Sensoren? Schau mal ob du hier fündig wirst!

  • Hallo,

    also ehrlich gesagt verstehe ich aus deiner Beschreibung nicht wirklich, was jetzt konkret dein Problem ist... außer das was nicht so läuft, wie du es dir vorstellt.

    Grundsätzlich: wenn ein Sensor "langsam" ist, dann kannst du ihn halt nicht sekündlich abfragen. Limits in der Hardware lassen sich durch Software nun mal nicht umgehen.

    Was du machen könntest ist, jeden Sensor in einem Thread abfragen und den Abfragewert in eine Queue schreiben, aus der der Hauptprozess, der für die Anzeige zuständig ist, liest. Wenn du Python >= 3.5 verwenden würdest ginge das vielleicht / wahrscheinlich auch mittels asyncio.

    Und da du Python 2.7 verwendest: du darfst _nicht_ `file` als Variablennamen benutzen. `file` ist eine Build-in Funktion bei Python 2, die du so überschreibst. Das kann "lustige" Nebeneffekt bis hin zu nicht nachvollziehbaren Fehlermeldungen haben. Bei Python 3 ginge das, da ist `file` kein Build-in mehr.

    Gruß, noisefloor

  • Hallo noisefloor,

    Danke für deine Tips File Variable ist abgeändert derzeit verwende ich die Python 3.5.3.

    Wie bereits geschrieben ich habe mit Python keine erfahrung für die implementierung feines asyncio Aufrufes bräuchte ich noch mal starthilfe.

    Danke Gruß Robert

  • Hallo,

    Zitat

    Wie bereits geschrieben ich habe mit Python keine erfahrung für die implementierung feines asyncio Aufrufes bräuchte ich noch mal starthilfe.

    Da muss ich auch immer noch ein bisschen rumprobieren. Bzw. asyncio ist kooperatives Multitasking für Python. Damit man das nutzen kann, müssen sich a) externe Module auch kooperativ verhalten und b) muss man (als Programmierender) verstanden, wie Coroutines unter Python funktionieren, also vom Prinzip her. Das ist für Einsteiger vielleicht ein bisschen viel.

    Von daher würde ich an deiner Stelle erstmal mit Threads und Queues zur Kommunikation anfangen.

    Gruß, noisefloor

  • Hallo,

    Da muss ich auch immer noch ein bisschen rumprobieren. Bzw. asyncio ist kooperatives Multitasking für Python. Damit man das nutzen kann, müssen sich a) externe Module auch kooperativ verhalten und b) muss man (als Programmierender) verstanden, wie Coroutines unter Python funktionieren, also vom Prinzip her. Das ist für Einsteiger vielleicht ein bisschen viel.

    Von daher würde ich an deiner Stelle erstmal mit Threads und Queues zur Kommunikation anfangen.

    Gruß, noisefloor

    OK gesagt getan habe jetzt das Projekt mit import _thread erweitert.

    aber wie bekomme ich jetzt für jeden "einkabelsensor" den er aus den Datein ausließt die Werte auf die Anzige? da die Anzeige in einer while True Schleife gefüttert wird und die Senoren über _thread.start_new_thread( einkabelsensor, ("Thread-1"), ) ) aufgerufen werden.

    im Sensor Thread steht nur ein Print für x Sensoren ich verwende auch mehrere.

  • Ich verstehe nicht, wie Multithreading irgendwelche Performanzgewinne bringen sollte?

    Wenn die gesharte Ressource ein Bus ist, dann ist er so schnell, wie er eben ist. Parallele Prozesse (synchronisiert) bringen rein gar nichts, mit Ausnahme von Codeoverhead und Komplexität. Unsynchronisiert bringt Parallelisierung nur Probleme.

    Bitte erst mal das Problem genau umreißen.

  • Moin!

    Ich mische mich ja ungern ein.. Ja, ich mache es trotzdem.

    Es wird irgendwie nebulös über Sensoren geschrieben.

    Macht es dir viel aus mal die Sensoren zu benennen?

    Ich finde den Vorschlag von noisefloor im Beitrag #2 schon logisch.

    Bei einem Display kann eh nur einer zur Zeit schreiben, sonst Kuddelmuddel.

    Darum ist es eigentlich wurscht wie lange die Sensoren brauchen.

    Meine Meinung

    Gruss Bernd

    Ich habe KEINE Ahnung und davon GANZ VIEL!!
    Bei einer Lösung freue ich mich über ein ":thumbup:"
    Vielleicht trifft man sich in der RPi-Plauderecke.
    Linux ist zum Lernen da, je mehr man lernt um so besser versteht man es.

  • Hallo,

    RobertHQ : das ist das falsche Modul... `_thread` ist die Low-Level API, die man nicht nutzen möchte. Du möchtest das `threading` Modul mit der High-Level API nutzen.

    schnasseldag : es geht auch nicht um Performance-Gewinn im eigentlichen Sinn - dann wäre auch threading unter (C)Python die (völlig) falsche Wahl, Stichwort: GIL

    Es gebt um nebenläufige Programmierung, um quasi Non-Blocking I/O zu erhalten. Durch die sequentielle Ausführung im Ausgangspost wartet das Programm permanent auf I/O, wodurch die Aktualisierung des Displays ausgebremst wird. Wenn du 2 Sensoren in 2 Threads ausliest (oder, bei asyncio in zwei Tasks auslagerst), blockieren sich die Abfragen schon mal nicht gegenseitig, weil diese nebenläufig ausgeführt werden. Die Abfrage jedes Sensors an sich wird natürlich nicht schneller - das ist ein eigenes Thema.

    Kurzfassung: das Ausgangsproblem des TE ist "I/O bound" und solche Probleme kann man unter Python mittels asyncio oder Threading angehen.

    Gruß, noisefloor

  • RobertHQ = Anfänger ... ich bin froh das ich das _thread eingebunden bekommen habe. die derzeitige Version kann ich gerne noch mal hoch laden.

    Aber als Elektroniker verstehe ich eure Frage Warum überhaupt threading ... ja weil ich NICHT nur I²C Sensoren verwende sonder 1Wire (DS18B20) die gefühlt sich erst nach 5 Sekunden zurück melden.

    Mein Plan ist diese bei Programmstart auszulesen und mit den werten anfangen zu rechnen und im späteren verlauf bei Änderungen darauf entsprechend zu reagieren.

    Derzeit bekomme ich die Werte von den "Einkabelsensor" nicht einzeln aus der schleife auf mein Display :/

    Der Print Befehl im _thread aufruf funktioniert nur halt leider auf der Shell.

    Weiß wer ob ich die Sensoren "Direkt" ohne über Datei öffnen schließen öffnen schließen ... gehen muss?

    Danke Gruß Robert

  • Hallo,

    Zitat

    RobertHQ = Anfänger ... ich bin froh das ich das _thread eingebunden bekommen habe.

    Und deshalb nimmt man nicht das low-level Modul `_thread`, sondern `threading`. Der führende Unterstrich _ zeigt auch an, dass das Modul zur internen Verwendung (von Python) ist und nicht zur öffentlichen Nutzung gedacht ist.

    Zitat

    Derzeit bekomme ich die Werte von den "Einkabelsensor" nicht einzeln aus der schleife auf mein Display

    Deine Funktion hat auch keinen Rückgabewert, sprich kein `return` Statement. Heißt, die Funktion wird aufgerufen, läuft 1x durch, liefert aber nichts an den Aufrufer zurück.

    Zitat

    Weiß wer ob ich die Sensoren "Direkt" ohne über Datei öffnen schließen öffnen schließen ... gehen muss?


    Unter Linux ist alles eine Datei -> das Öffnen / Schließen ist notwendig.

    Gruß, noisefloor

  • Der führende Unterstrich _ zeigt auch an, dass das Modul zur internen Verwendung (von Python) ist und nicht zur öffentlichen Nutzung gedacht ist.

    ...und im Fall von CPython sind die Module mit einem führenden Unterstrich oftmals die in C geschrieben (/Modules)und werden von anderen (in Python geschiebenen) Modulen (/Lib) in der Standardbibliothek verwendet, die ein ein high-level API anbieten (https://hg.python.org/cpython/file/tip/Modules).

  • Hey danke für die Erklärungen also ist das Datei öffnen = dem Aufruf die 1 Wire Fühler auszulesen. OKAY wenn das so sein soll bitte :)

    okay das ich nicht die _thread Funktion nehmen soll okay aber kann mir jemand für mein Programm das richtige anpassen? habe echt schon viel probiert auch mit Class aber bitte ich weiß nicht was ich da mache. Das heißt klappt es von Anfang an nicht habe ich keine Changs es gerade zu bügeln. Die Schönen Beispiele bringen mir nix da ich den Code nicht auf mein Programm ummünzen kann. Dafür fehlt mir einfach noch etwas Verständnis.

    Gruß Robert

  • Hallo,

    Demo-Programm:

    • Die Funktion `fake_reader` steht für deinen Sensor, nur das halt aus (dem Linux Kernel Device) /dev/urandom gelesen wird und das `sleep` die langsame Geschwindigkeit des Sensors simuliert.
    • Die Funktion `printer` gibt die Werte von `fake_reader` aus. Hier mit `print()`, ginge aber auch auf ein Display.
    • Zwei Sensoren werden in zwei Threads gestartet, die Daten laufen in eine Queue, aus der `printer` liest.
    • Das Zeugs mit dem Event ist dafür da, dass die Threads beendet werden können und nicht endlos laufen.

    Die Anpassung auf dein konkretes Problem obliegt dann dir :)

    Gruß, noisefloor

  • Durch die sequentielle Ausführung im Ausgangspost wartet das Programm permanent auf I/O, wodurch die Aktualisierung des Displays ausgebremst wird. Wenn du 2 Sensoren in 2 Threads ausliest (oder, bei asyncio in zwei Tasks auslagerst), blockieren sich die Abfragen schon mal nicht gegenseitig, weil diese nebenläufig ausgeführt werden.

    Blockierende IO Operationen sollte man natürlich vermeiden. Das bedeutet aber bei n Sensoren nicht n oder n+1 Threads sondern genau 2. Einen für den Vordergrundthread, der flüssig laufen sollte und einen für die Sensoren, der diese sequentiell über den Bus ausliest. Oder, um ganz genau zu sein, sollte jedes eigenständige Bussystem einen Thread erhalten plus einem Vordergrundthread.

    Für n-Sensoren eines Busses n-Threads vorzuhalten wäre der falsche Ansatz. Bestenfalls werden die Threads vom Treiber synchronisiert, solange eine Anfrage in sich semantisch noch atomar ist. Schlimmstenfalls gibt es Buskollisionen oder man ordnet Datenpakete der Sensoren falsch zu.

  • Hallo,

    Zitat

    Für n-Sensoren eines Busses n-Threads vorzuhalten wäre der falsche Ansatz.

    Richtig. Nur hier ist es nach meinem Verständnis so, dass die Daten jedes 1-Wire Sensors aus einer eigenen Datei gelesen werden, womit sich die Sensoren parallel abfragen lassen. Oder sehe ich da was falsch?

    Gruß, noisefloor

  • Hallo,

    Richtig. Nur hier ist es nach meinem Verständnis so, dass die Daten jedes 1-Wire Sensors aus einer eigenen Datei gelesen werden, womit sich die Sensoren parallel abfragen lassen. Oder sehe ich da was falsch?

    Gruß, noisefloor

    Das siehst du korrekt

  • Ich sage mal jein. Zunächst haben wir es doch mit zwei unterschiedlichen Sensortypen zu tun. Einmal I2C Sensoren und dann 1wire Sensoren. Beides sind serielle Busse. Egal also, ob irgendein Treiber Werte der Sensoren in das Filesystem schreibt (hier 1wire) er macht dies sequentiell und im Falle der allseits beliebten DS18x20 Sensoren auch noch recht langsam. Je nach Auflösung des Temperatursignales bis zu einer knappen Sekunde. Bei Busfehlern auch schon mal mehrere Sekunden. Natürlich kann ich nun die Dateien beliebig oft/schnell und parallel abfragen - nur zu welchem Zweck? Um 5 mal denselben Wert zu lesen? Und selbst wenn - ich kann die Dateien ebensogut in einer Pollloop nacheinander abfragen. Dazu braucht's immer noch keine n Threads. Was ich eher für angebracht hielte, wäre ein Filechanged-Event zu abonnieren, um sich von einer Dateiänderung (innerhalb eines Verzeichnisses) informieren zu lassen. Dieser (eine) Thread sollte dann gegen den Mainthread synchronisiert werden, mehr aber auch nicht. Ich würde mal in der Ecke "inotify" nachlesen. >> Hier << gibt's eine schöne Erklärung für C-Liebhaber. Für Python findet sich aber sicher auch etwas (vermutlich sogar schöner aufbereitet).

  • Hallo,

    es gibt in der Tat inotify-Binding für Python.

    Danke für die Erklärung, die technischen Hintergründe zu diversen Sensoren sind mir nicht soooo geläufig. Wenn der Sensor bzw. der Bus einfach lahm und sequentiell ist, dann machen Threads in der Tat nicht viel Sinn. Wobei es dann auch keine Sinn macht, jede Sekunden einen (neuen) Wert anzeigen zu lassen ;)

    Gruß, noisefloor

  • Hallo File Change Event macht für mich auch Sin bzw. kling das Logisch. Den Sekundentakt gibt die Anzeige mit Uhrzeit und Sekunden vor. Ich wollte nur nicht die Sekunden erst wieder in das Display schreiben, wenn sich alle Sensoren zurückgemeldet haben. Ich bin den link von schnasseldag gefolgt. … Ja super -> Ich keine Ahnung von Python <- also wäre eine Einbindung in den Code schon erforderlich. Ach ja ich Habe ja auch den 16x12 Bit Servo Trebier dran der später auch noch ins Spiel kommt, wenn die Temps. Im Programm sind.

    Die 4 Pin PC PWM Lüfter (NF-P14S redux-1200 PWM) die zwar mit 24,5 kHz vom Mainboard getaktet werden, laufen aber auch mit dem Adafruit Servo Shild Board über 1 kHz PWM genauso gut bzw. besser ?! Steuerbar von 140 U/min bis max.

    Bei max. hat der Lüfter 1308 U/min das entspricht 43,6 Hz (Hallsensor doppelte Taktung).

    Nur mal zur INFO könnt auch andere Bastler interessieren.

    Ich hänge noch mal den aktuellen Code ran.

    Gruß Robert Danke ;)

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!