Jump to content

adeuring

Members
  • Gesamte Inhalte

    10
  • Benutzer seit

  • Letzter Besuch

adeuring's Achievements

Newbie

Newbie (1/14)

0

Reputation in der Community

  1. So ist das Leben -- manchmal kommt einem was dazwischen, das einen darn hindert, mit hübscher Hardware zu basteln Diese Antwort kommt reiseverursacht auch recht spät... Ich weiß ja nicht, was genau Du versucht hast, aber ich mutmaße mal, dass Dein Hauptproblem hier liegt: if __name__ == "__main__": log.info('Weatherstaion: Start\n') Weatherstation = weatherstation() if sys.version_info < (3, 0): input = raw_input # Compatibility for Python 2.x user_input = input('Press enter to exit.\n') "Weatherstation = weatherstation()" initialisiert die "gesamte Maschinerie", inclusive Callbacks. Danach kommt der [raw_]input() call, und hier bleibt das Script stehen, bis eben die Enter-Taste gedrückt wird. Damit muss alles in den Callbacks stattfinden, die von der IPConnection-Instanz in einem eigenen Thread ausgeführt werden, sobald die brick[lets] "etwas zu melden" haben. Da Du das Script letztlich als daemon ausführen willst, kannst Du diesen input()-call aus einfach rausnehmen und durch ungefähr folgendes ersetzen [nicht getestet...]: next_call_time = time.time() while True: Weatherstation.update_display() next_call_time += 1 time.sleep(next_call_time - time.time()) update_display() könnte dann die aktuelle Zeit anzeigen, und natürlich auch die ganzen Sensordaten, je nachdem, welcher Button las letztes gedrückt wurde. Das Script kannst Du bei Testaufrufen vom Terminal aus immer noch mit ctrl-C stoppen. Bleibt das Problem, das LCD beim Beenden abzuschalten. Das ginge so: next_call_time = time.time() try: while True: Weatherstation.update_display() next_call_time += 1 time.sleep(next_call_time - time.time()) finally: Weatherstation.lcd_off() ...das ginge in der oben gezeigten while-Schleife problemlos. Das würd ich den Temperatursensor nehmen, der am nächsten am Drucksensor liegt, Das Problem sind die logging-Aufrufe und der input()-Call, wenn kein Terminal vorhanden ist: Der input()-Call dürfte bei geschlosenem stdin einfach sofort einen Leerstring zurückliefern; die logging-Aufrufe gehen nach, was ist es normalerweise, stdout oder stderr? Wenn diese geschlossen sind, bricht das Script recht bald mit einem Fehler ab. Ein recht schlichter Trick, eine Terminal-Nutzung zu vermeiden, wäre der Aufruf per nohup: nohup /usr/bin/python /usr/local/bin/weatherstation.py ( info coreutils 'nohup invocation' liefert weitere Details). Ohne weitere Parameter leitet nohup stdout und stderr in einen Datei namens nohup.out um -- da müsstest Du in dem systemd file noch das passende work directory angeben (sorry, keine Ahnung, wie das geht...); vielleicht funktioniert auch ein Aufruf in der Art nohup /usr/bin/python /usr/local/bin/weatherstation.py >> /home/pi/wstation.log -- aber ob das Sinn hat, hängt davon ab, wie genau systemd diesen Aufruf macht, d.h.: Wird diese Zeile wie bei einer normalen shell ausgewertet, oder hat systemd da seine eigene Logik?
  2. Wow, für einen ersten Gehversuch in Python sieht das Script sehr sauber aus! Threads dürften nicht nötig sein. Was der Kern Deines Problems sein dürfte: Die "while True"-Schleife in update_queues(). Wenn Du genau diese Zeile rausnimmst, und auch das sleep() am Ende dieser Methode, sollte das Script schon um einiges besser laufen. Dann kann die "while True"-Scheife im "if __name__ = '__main__'"-Block des Scripts update_queues() einmal pro Sekunde aufrufen, und Du hast aktualisierte Werte in Deinen queues. Dann fehlt nur noch der Aufruf einer Methode, die die aktualiserten Daten auf das Display bringt. Das ginge in update_queues() selbst, kann aber natrlich auch in der Hauptschleife mit einem Aufruf einer geeigneten Methode nach dem call von update_queues() erfolgen.
  3. Das hast Du mich erwischt: Ich hatte mir die Schaltpläne von IO4 und AnalogIn nicht angeschaut… Wie auch immer – ich meinte eigentlich "nur" eine galvanisch getrennte I²C-Schnittstelle. Hat natürlich kleinere Einschränkungen hinsichtlich Nutzbarkeit, aber dafür überschaubaren Aufwand.
  4. Stimmt, mit den direkten I/O-Signalen würd's aufwendig – aber ich meinte eigentlich nur die Signale für den I²C-Bus, also SCL, SDA, Adresse, select. Das würdet Ihr doch auch auf den geplanten Bricklets mit galvanischer Trennung brauchen. Aber sechs Optokoppler sind auf jeden Fall nötig, weil SCL und SDA bidirektional sind -> zusammen 4 Optokoppler, dann noch Adresse un Select.
  5. OK, die vorhandenen bzw. geplanten Bricklets sind in der Tat eine Alternative. Aber trotzdem: So ein kleines Adapter zu galvanischen Trennung vorhandener Bricklets fänd ich einfach praktisch.
  6. Es gibt ja eine ganze Reihe Bricklets mit analogen oder digitalen Ein- oder Ausgängen: IO-16, IO-4, AnalogIn/-Out, Voltage/Current fallen mir grade ein. Gemeinsam ist allen, dass sie galvanisch mit "ihrem" Brick verbunden sind und häufig dann vom Brick über ein USB-Kabel mit dem Steuerrechner. Häufig stört das nicht weiter, aber es gibt viele Szenarien, wo die gemeinsame Masse die Nutzung verhindert. Was mir grade in den Sinn kommt: Messung von zwei Spannungen mit Voltage/Current- oder AnalogIn-Bricklets, wobei eine positiv gegen Masse und die andere negativ gegen Masse ist Steuerung eines schlichteren Labornetzteils mit analogen Steuereingängen, die ihrerseits nicht galvanisch vom Rest der Netzteils getrennt sind, wo aber eine andere galvanische Verbindung mit dem Steuerrechner existiert Vermeidung von Masseschleifen Ich hab mir einen "galvanischen I²C-Bus-Trenner" schon selbst gebastelt, in Anlehnung an AN460 für den Philips/NXP-Chip P82B96 (http://www.zlgmcu.com/philips/iic/P82B96/I2C_AN460_1.pdf). Läuft auch bisher sehr ordentlich – aber es gibt aufregendere Dinge, die sich auf Lochrasterkarten aufbauen lassen OK, es lässt auch ersatzweise pro "Trennstelle" ein MasterBrick in Kombination mit einen Raspberry + WLAN-Stick oder einer WLAN-Extension – aber das ist doch recht aufwendig... [edit: link zu AN460 korrigiert]
  7. Guten Abend, hab bei meinen ersten Hardware- und Python-Basteleien mit dem schönen Spielzeug von Tinkerforge ein paar Dinge gebaut, die vielleicht auch für andere Leute von Interesse sind. 1. Ein kleines Programm namens "lstf". Das listet einfach die mit dem angegebenen Host verbundenen Bricks/Bricklets auf, und zwar in Form des Namens der Python-Klasse, die mit dem jeweiligen Brick(let) etwas anfangen kann, sowie die UID des Elements. 2. Einen Datenlogger für die Kommandozeile. Kann im Augenblick Daten als schlichten Text und im CSV-Format ausgeben. Beispielnutzung: tflogger BrickletAmbientLight:illuminance BrickletBarometer:air_pressure,altitude BrickletHumidity:humidity BrickletTemperature:temperature -o test.csv text:- liest die Daten der Bricklets AmbientLight, Barometer, Humidity, Temperature aus und schreibt sie in die Daten test.csv und gibt sie außerdem auf der Konsole aus. Die ersten Parameter sind also die Python-Klassennamen, wobei hinter einem ':' noch die Namen von einem oder mehrere Messwerten folgen. Die Messwert-Namen entsprechen den get_.*-Methoden der brick(let)-Klassen, d.h., "BrickletAmbientLight:illuminance" funktioniert deshalb, weil die Klasse BrickletAmbientLight eine Methode namens get_illuminance() hat. Der obige Aufruf funktioniert nur dann, wenn genau _ein_ Bricklet des angegebenen Typs vorhanden ist. (Dürfte in vielen Anwendungsfällen zutreffen, denke ich.) Wenn kein passendes Brick(let) vorhanden ist, gibt's eine Fehlermeldung, ebenso, wenn mehr als eines vom gewünschten Typ vorhanden ist. In letzterem Fall kann man aber die UID mit angeben, z.B. so: tflogger BrickletAmbientLight(i9K):illuminance -o ... Der Parameter -o muss _immer_ angegeben werden, und er muss, weil er mehrere Werte haben kann, als _letztes_ angegeben werden. (Zu weiteren Details an Parametern probieren Sie "tflogger -h" (leider noch etwas unvollständig...), lesen Sie die Dokumentation des Python-library "getargs" oder den Quelltext von tflogger (inbesondere die unit tests), oder schicken Ihren Arzt zum Apotheker. Oder frag in diesem Forum. 3. Mir ist es auf die Nerven gegangen, dass ich immer den UID eines Brick(let) raussuchen muss, bevor ich es verwenden kann -- auch wenn nur ein Brick(let) des jeweiligen Typs vorhanden ist. Deshalb hab ich eine Klasse BrickFactory geschrieben, die für eine oder mehrere IPConnections Infos über alle angeschlossenen Brick(let) einsammelt; anschließend kann man die Methode make_brick() aufrufen, die für eine übergebene Bríck/Brícklet-Klasse das passende Brlick(let) raussucht und eine Instanz der Klasse zurückgibt. Funktioniert natürlich nur, wenn genau ein Brick(let) des jeweiligen Typs vorhanden ist. 4. Das VoltageCurrent-Bricklet ist wirklich prima -- hat aber nicht so ganz meine Wünsche erfüllt. Der Strom-Messbereich von 20A ist mir in manchen Fällen einfach zu groß. Ich hab es deshalb so umgebaut, dass sich der Shunt auswählen lässt. Zur Zeit mit einer sehr schlchten Verdrahtung: Eine Seite jedes Shunt hat ihre eigene Mess-Klemme; mittels Jumper lässt sich wählen, welcher Shunt mit dem Bricklet verbunden wird. Software-seitig ergibt dieser Aufbau das Problem, dass jeder Shunt seine eigenen Kalibrierdaten braucht, was mit der normalen Firmware nicht so schlicht zu lösen ist. Ein Patchen der Firmware war mir bisher zu aufwendig -- als schlichte Lösung hab ich eine Klasse BrickletVoltageCurrentVariableShunt von der normalen BrickletVoltageCurrent abgeleitet, die die Kalibrierdaten aus einer INI-Datei holt. Den ganzen Kram gibt's für Interessierte im Anhang; ansonsten gibt es auch einen Bazaar branch: https://code.launchpad.net/~adeuring/+junk/tftools (das "+junk" bedeutet nur, dass ich für das Paket bisher kein Launchpad-Projekt angelegt habe -- dann muss ich das Pfad-Element "+junk" verwenden ) Installation: Python-üblich mit "./setup.py install" tftools benötigt das eine oder andere library, das nicht Teil der Standard-libraries von Pyhton ist. Welche das genau sind, muss ich noch dokumentieren. Bis dahin: trial & error tftools-0.1.tar.gz
  8. Ah, Danke, Photron. Da hatt ich die DOkumentation missverstanden: Dass die "Änderungsbedingung" sich nur auf die threshold-callbacks bezieht.
  9. Gutan Abend loetkolben, Danke, gute Idee -- hat leider nix gehlfeen. Aber das Bricklet ist jetzt auf FW 2.02
  10. Tag zusammen, folgendes kleines Script arbeitet prima für die Feuchte-, Druck- und Licht-Bricklets -- nur mit dem Temperatur-Bricklet gibt es "Aussetzer": from functools import partial from time import sleep, time from tinkerforge.bricklet_ambient_light import AmbientLight from tinkerforge.bricklet_barometer import Barometer from tinkerforge.bricklet_humidity import BrickletHumidity from tinkerforge.bricklet_temperature import Temperature from tinkerforge.ip_connection import IPConnection def cb_gen(what, val): print '%6.4f %s %s' % (time() - start, what, val) REPEAT = 500 conn = IPConnection() conn.connect('localhost', 4223) try: light = AmbientLight('i9K', conn) bar = Barometer('fTv', conn) hum = BrickletHumidity('hR7', conn) temp = Temperature('dPm', conn) temp.set_response_expected_all(True) start = time() light.register_callback( light.CALLBACK_ILLUMINANCE, partial(cb_gen, 'illum')) bar.register_callback( bar.CALLBACK_AIR_PRESSURE, partial(cb_gen, 'press')) hum.register_callback( hum.CALLBACK_HUMIDITY, partial(cb_gen, 'humid')) temp.register_callback( temp.CALLBACK_TEMPERATURE, partial(cb_gen, '--------temp ')) light.set_illuminance_callback_period(REPEAT) bar.set_air_pressure_callback_period(REPEAT) hum.set_humidity_callback_period(REPEAT) temp.set_temperature_callback_period(REPEAT) sleep(10) finally: conn.disconnect() Beispiel-Output: 0.0276 --------temp 2137 0.1046 press 997716 0.2777 humid 400 0.3774 illum 778 0.5280 --------temp 2131 0.6047 press 997715 0.7778 humid 399 0.8776 illum 774 1.1047 press 997716 1.2778 --------temp 2137 1.3777 illum 776 1.4777 humid 398 1.6048 press 997713 1.8774 illum 775 2.1049 press 997711 2.1777 humid 400 2.3779 illum 776 2.6049 press 997707 2.6779 humid 397 2.9278 illum 778 3.1048 press 997708 3.1778 humid 398 3.4279 illum 776 3.6779 humid 399 3.9779 illum 777 4.0251 press 997707 4.1779 humid 398 4.2780 --------temp 2131 4.4779 illum 776 4.7780 --------temp 2137 4.8050 press 997706 4.8779 humid 399 4.9780 illum 777 5.3252 press 997705 5.3780 humid 398 5.4780 illum 776 5.8250 press 997704 5.9780 humid 400 6.0281 illum 775 6.3251 press 997707 6.5281 illum 777 6.5781 humid 397 6.8251 press 997705 7.0284 illum 775 7.0781 humid 399 7.3251 press 997706 7.5282 --------temp 2131 7.5781 humid 398 7.6281 illum 774 7.8251 press 997707 8.0282 --------temp 2137 8.0782 humid 400 8.1281 illum 775 8.3251 press 997705 8.5780 humid 399 8.6782 illum 774 8.8252 press 997706 9.0782 humid 400 9.2282 illum 775 9.3253 press 997704 9.5783 humid 399 9.8783 illum 774 10.0054 press 997705 Wie zusehen, werden Helligkeit, Feuchte und Druck sehr regelmäßig ausgegeben -- nur die Temperaturdaten fehlen recht häufig. Hab verschiedene Varianten probiert: Kabel gewechselt, Stecker am Master Brick gewechselt, und auch mal einen StepperBrick gewechselt (mit modifiziertem Script -- ohne die anderen Bricklets). Das Problem bleibt. (Nebenbei: Ich weiß, dass es eigentlich Unsinn ist, solche phyiskalischen Größen sooo häufig zu messen -- aber zum Testen ist das unterhaltsamer als Minuten zu warten [Edit] Was ich vergessen habe: der MasteBrick hat FW 2.1.2, das TemperatureBricklet die FW Version 2.0.0
×
×
  • Neu erstellen...