Hallo,
seit einigen Tagen beschäftige ich mich mit der Pythonista und in einer Sache komme ich nicht weiter.
Mein Ziel ist, die Logdaten (Temperatur/Zeit-Werte) eines Reflow-Ofens über Bluetooth in ein IOS Gerät (iPad) graphisch zur Anzeige bringen und den Temperaturerlauf zu animieren.
Hierfür habe ich zwei Teilprogramme geschrieben (genauer: das gefundene im Netz modifiziert), die für sich laufen.
Eins davon stellt die Bluetoothverbindung mit dem Ofen her und liefert die Logdaten zeilenweise (ascii) als ‚line’ ab. Mit Print(line) kann ich die Korrektheit des Empfanges kontrollieren.
Das zweite Programm ist in der Lage, ähnliche ‚line‘ daten, die zum Test aus einem File gelesen wurden, grafisch darzustellen.
Ich habe die Textkörper beider Programme so in ein Programm zusammen gefasst, dass beide bei ‚run‘ laufen. Es gelingt mir nicht, dass die ‚line’-Ausgabe des Bluetooth-Teils als ‚line’-Eingabe vom Grafikmodul verstanden und weiter verarbeitet wird, obwol ich die Variabe ‚line‘ für beide als global definiert habe.
Irgend eine Lösungsidee?
Datenaustausch zweischen zwei laufenden Prozessen
Das mit dem Anstoßen verstehe ich nicht ganz.
Beide Scripts verwenden innerhalb ihrer Funktionen den Namen „line“ für die gleich aufgebaute Datenzeile. Ich habe jeweils innerhalb deren Funktionen versucht, mit „global line“ eine Verbindung mit der ‚line=„“ außerhalb der Funktionen als eine Brücke sozusagen aufzubauen, ohne Erfolg.
Kein Problem mit der Offenlegung des Codes. Ich muss nur herausfinden, wie man hier etwas anhängt und hochlädt.
Beide Scripts verwenden innerhalb ihrer Funktionen den Namen „line“ für die gleich aufgebaute Datenzeile. Ich habe jeweils innerhalb deren Funktionen versucht, mit „global line“ eine Verbindung mit der ‚line=„“ außerhalb der Funktionen als eine Brücke sozusagen aufzubauen, ohne Erfolg.
Kein Problem mit der Offenlegung des Codes. Ich muss nur herausfinden, wie man hier etwas anhängt und hochlädt.
- __blackjack__
- User
- Beiträge: 14033
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Dymo: Na wenn die eine Funktion den globalen Wert von `line` ändert muss die andere Funktion ja irgendwie mitbekommen das sich der Wert geändert hat und das sie etwas damit machen soll. Und das passiert halt nicht auf magische Weise. Du musst das der anderen Funktion schon irgendwie mitteilen. Wobei das dann impliziert das die Funktionen auch gleichzeitig, nebenläufig abgearbeitet werden, irgendwie voneinander wissen, und irgendwie synchronisiert auf die globale Variable zugreifen. Das ist zwar möglich so zu programmieren, aber *viel* zu kompliziert, also sich mal hinzusetzen und die *nicht* über eine globale Variable kommunizieren zu lassen, sondern das ganz normal durch Funktionsaufrufe oder Generatorfunktionen zu lösen.
Dazu muss man allerdings Python verstehen und programmieren können.
Dazu muss man allerdings Python verstehen und programmieren können.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
@__blackjack__: Danke für die Antwort. Ich beschäftige mich erst seit ein paar Tagen mit Python, also ein absoluter newbe. Ich dachte, ‚global‘ wäre am einfachsten. Was ist mit pipe- oder fifo- Funktion. Ich denke, die Prozesse müssen nicht synchron laufen.
Wenn man mir verrät, wie ich den Code an meinen Beitrag anhängen kann, komme ich vielleicht leichter zu einer Lösung.
Wenn man mir verrät, wie ich den Code an meinen Beitrag anhängen kann, komme ich vielleicht leichter zu einer Lösung.
Einkopieren und das code Tag drum rum machen.
Und unter iOS ist nix mit Fifos etc. Mit wenigen Ausnahmen gibts keine IPC, denn es läuft immer nur eine Anwendung. Ich sehe aber auch keinen Grund, warum du das brauchst. Prinzipiell ist
das muster, mit dem du deine beiden Funktionalitäten verbindest.
Und unter iOS ist nix mit Fifos etc. Mit wenigen Ausnahmen gibts keine IPC, denn es läuft immer nur eine Anwendung. Ich sehe aber auch keinen Grund, warum du das brauchst. Prinzipiell ist
Code: Alles auswählen
while True:
daten = hole_daten()
stelle_daten_dar(daten)
- __blackjack__
- User
- Beiträge: 14033
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Wenn Du zwei einzelne Programme hast, kannst Du die natürlich auch mit einer Pipe verbinden. Die Standardein- und ausgaben stehen im `sys`-Modul als `stdin`, `stdout`, und `stderr` zur Verfügung.
Die Programme müssen schon synchron laufen, denn sie sind ja über die Zeilen synchronisiert. Immer wenn Programm A eine Zeile generiert, muss Programm B diese verarbeiten. Oder anders: Programm B kann nichts zeichnen solange Programm A nichts geliefert hat. Die können also nicht asynchron ablaufen.
Generatorfunktionen/Iteratoren in Python sind so etwas ähnliches wie Pipes, nur das das innerhalb des gleichen Prozesses läuft.
Anhängen kann man hier nichts. Nicht zu lange Programmstücke kann man hier einfach mit den [ code ]-Tags direkt in den Beitrag schreiben. Für längeres kann man Dienste wie Pastebin oder Gist verwenden und hier einen Link darauf veröffentlichen. Für ganze Projekte bieten sich Plattformen wie Bitbucket, Github, Gitlab, Pikacode, … an.
Die Programme müssen schon synchron laufen, denn sie sind ja über die Zeilen synchronisiert. Immer wenn Programm A eine Zeile generiert, muss Programm B diese verarbeiten. Oder anders: Programm B kann nichts zeichnen solange Programm A nichts geliefert hat. Die können also nicht asynchron ablaufen.
Generatorfunktionen/Iteratoren in Python sind so etwas ähnliches wie Pipes, nur das das innerhalb des gleichen Prozesses läuft.
Anhängen kann man hier nichts. Nicht zu lange Programmstücke kann man hier einfach mit den [ code ]-Tags direkt in den Beitrag schreiben. Für längeres kann man Dienste wie Pastebin oder Gist verwenden und hier einen Link darauf veröffentlichen. Für ganze Projekte bieten sich Plattformen wie Bitbucket, Github, Gitlab, Pikacode, … an.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
hier ist der Code
..
Ich habe in Programmteil Bluetooth zu viele sinn- und wirkungslose 'global line' in die einzelnen Funktionen eingeführt und dabei vergessen, sie in dieser Ausgabe zu löschen. Also bitte ignorieren!
Code: Alles auswählen
# coding: utf-8
#-----z.T. verwendete Module-----------------
import cb
import time
import struct
import sys
import console
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import style
console.set_color()
#----- Programm für das Lesen von 'line' und Darstellen der Kurven und derer Animation
style.use('fivethirtyeight')
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
tz =''
zeile = ''
line = ''
def animate(i):
x = 0
sp = 0
global line
#global line #line =''
titel =''
tim = []
tc0 = []
tc1 = []
tx0 = []
tx1 = []
sol = []
ist = []
hot = []
fan = []
ovn = []
reflow = []
# Bluetooth-Verbindung herstellen und zeilenweise Log-Daten lesen (von hier)
mngr = MLT_BT05_Manager()
cb.set_central_delegate(mngr)
print('Scanning for peripherals...')
cb.scan_for_peripherals()
# bis hier als ersatz von lines = open('file','r') .read() und for line in lines:....
if line != []:
print('ANI=',line) #-Test-Ausgabe, ob eine line übergeben wurde
# ab hier die Interpretation des line-Inhaltes zum Aufbau der Grafik
if len(line) == 39:
titel = line
sp = 217
if len(line) == 48:
titel = line
sp = 217
if len(line) == 47:
titel = line
sp = 136
if 'AMTECH' in line: sp = 217
if len(line) == 44:
titel = line
sp = 183
if len(line) >= 75: # Log-Daten, Zeit, Temperaturen usw.
x = x + 1
zeile = line[0:67]
if len(zeile) > 1:
s1, s2, s3, s4, s5, s6, s7, s8, s9, s10 = zeile.split(',')
tim.append(float(s1))
tc0.append(float(s2))
tc1.append(float(s3))
tx0.append(float(s4))
tx1.append(float(s5))
sol.append(float(s6))
ist.append(float(s7))
hot.append(float(s8))
fan.append(float(s9))
ovn.append(float(s10))
reflow.append(float(sp))
ax1.clear()
ax1.plot(tim, hot, 'r', linewidth=0.1, label='Heizung/B/')
ax1.plot(tim, fan, 'b', linewidth=0.1, label='Ventilator/B/')
ax1.plot(tim, ovn, linewidth=0.5, label='Ofen-Temp.')
ax1.plot(tim, tc0, linewidth=2.5, label='TC0-links')
ax1.plot(tim, tc1, linewidth=2.5, label='TC1-rechts')
ax1.plot(tim, sol, linewidth=2.5, label='Soll-Temp.')
ax1.plot(tim, ist, linewidth=2.5, label='Ist-Temp.')
ax1.plot(tim, tx0, linewidth=2.5, label='ExTC2')
ax1.plot(tim, tx1, linewidth=2.5, label='ExTC3')
ax1.plot(tim, reflow, linewidth=1.5, label='Schmelzpunkt')
plt.xlabel('Zeit [s]', fontsize=10) # Bezeichnung der X-Achse
plt.ylabel('Temperatur [°C]', fontsize=10) # Bezeichnung der Y-Achse
plt.title(titel, fontsize=12) # Plot-Titel
plt.legend(loc=2, prop={'size': 8}) # Legende einblenden
# plt.xlim(0,380)
# plt.ylim(0,250)
plt.xticks([0,20,40,60,80,100,120,140,160,180,200,220,240,260,280,300,320,340,360],fontsize=10)#,[0,20,40,60,80,100,120,140,160,180,200,220,240,260,280,300,320,340,360])
plt.yticks([0,25,50,75,100,125,150,175,200,225,250],fontsize=10)#,[0,25,50,75,100,125,150,175,200,225,250])
#-----Ende von def animate()-------
#ani = animation.FuncAnimation(fig, animate, interval=5000)
#plt.show()
tz = ''
line = ''
#---Programm zur Bluetooth-Verbindung und zeilenweise lesen
class MLT_BT05_Manager (object):
def __init__(self):
self.peripheral = None
print('\n Init')
def did_discover_peripheral(self, p):
if p.name == 'MLT-BT05' and not self.peripheral:
print('Discovered ' + p.name)
self.peripheral = p
cb.connect_peripheral(p)
def did_connect_peripheral(self, p):
print('Connected Peripheral ' + p.name)
p.discover_services()
def did_fail_to_connect_peripheral(self, p, error):
print('Failed to connect: %s' % (error,))
def did_disconnect_peripheral(self, p, error):
global line
print('*Disconnected, error: %s' % (error,))
self.peripheral = None
def did_discover_services(self, p, error):
global line
for s in p.services:
if s.uuid =='FFE0':
p.discover_characteristics(s)
def did_discover_characteristics(self, s, error):
global line
for c in s.characteristics:
if c.uuid == 'FFE1':
self.peripheral.set_notify_value(c, True)
def did_update_value(self, c, error):
global tz
global zeile
global line
input = (c.value) # <class 'bytes'>
lt1 = input.decode('ascii')
if '\r\n' not in lt1 or len(lt1) <3: # Teilzeilen zusammensetzen! Neue Zeile?
tz += lt1
else:
zeile = tz[2:]
tz = lt1
print('BT',zeile) # Test-Ausgabe, ob Bluetooth-Zeile gelesen wurde
line = zeile
#return line
#return line
'''
#----Ursprüngliche Aufruf-Zeilen des obigen Bluetooth-Moduls
mngr = MLT_BT05_Manager()
cb.set_central_delegate(mngr)
print('Scanning for peripherals...')
cb.scan_for_peripherals()
try:
while True: pass
except KeyboardInterrupt:
cb.reset()
'''
#----------
ani = animation.FuncAnimation(fig, animate, interval=5000)
plt.show()
Ich habe in Programmteil Bluetooth zu viele sinn- und wirkungslose 'global line' in die einzelnen Funktionen eingeführt und dabei vergessen, sie in dieser Ausgabe zu löschen. Also bitte ignorieren!
Ich hab mir das mal kurz auf meinem iPad angeschaut was Pythonista so für Beispiele mitbringt. Keines davon ist animiert. Sucht man nach animations Code, findet man
https://forum.omz-software.com/topic/43 ... -animation
Der Typ scheint sich halbwegs auszukennen, und empfiehlt, sich das selbst zu programmieren. Was sich mit meinem Eindruck von matplotlib deckt. So richtig geil für Animationen ist das nicht.
Leider ist dein Code so verfrickelt, da sich den nicht zum laufen kriege, um das selbst mal zu prüfen, ob der Stand der Dinge besser ist. Woher hast du denn dein original animations Skript?
https://forum.omz-software.com/topic/43 ... -animation
Der Typ scheint sich halbwegs auszukennen, und empfiehlt, sich das selbst zu programmieren. Was sich mit meinem Eindruck von matplotlib deckt. So richtig geil für Animationen ist das nicht.
Leider ist dein Code so verfrickelt, da sich den nicht zum laufen kriege, um das selbst mal zu prüfen, ob der Stand der Dinge besser ist. Woher hast du denn dein original animations Skript?
Die Grundidee für das Diagramm habe ich von hier:
https://pythonprogramming.net/live-grap ... -tutorial/
Und das mit dem Bluetooth von hier:
http://omz-software.com/pythonista/docs/ios/cb.html
Den Rest habe ich selbst dazu geschrieben.
https://pythonprogramming.net/live-grap ... -tutorial/
Und das mit dem Bluetooth von hier:
http://omz-software.com/pythonista/docs/ios/cb.html
Den Rest habe ich selbst dazu geschrieben.
Also ich habe die Animation mal ausprobiert:
Und alles was da passiert ist, das ein leerer Plot gezeichnet wird. Bzw dann habe ich unten die anderen animate Aufrufe eingeführt, und dann kommen Daten. Aber nur einmal.
Wie ich oben schon schrieb, das scheint so nicht zu gehen. Da musst du viel tiefer einsteigen, und mit den iOS scene APIs von Pythonista arbeiten. Dazu muss man aber programmieren können, durch Copy, Paste und Hammerschlag geht da nix.
Code: Alles auswählen
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import style
style.use('fivethirtyeight')
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
xs = []
ys = []
def animate(i):
xs.append(i)
ys.append(len(xs))
ax1.clear()
ax1.plot(xs, ys)
ani = animation.FuncAnimation(fig, animate, interval=1000)
animate(0)
for i in range(100):
animate(i)
plt.show()
Wie ich oben schon schrieb, das scheint so nicht zu gehen. Da musst du viel tiefer einsteigen, und mit den iOS scene APIs von Pythonista arbeiten. Dazu muss man aber programmieren können, durch Copy, Paste und Hammerschlag geht da nix.
Wenn Du das ausprobiert hast, was Du oben upgeloadet hast, dann kein Wunder, dass nur ein leerer Plot dargestellt wird. Dazu müssen Daten eingelesen werden, wie in dem Tutorialbeispiel von dem File 'example.txt'. Dann braucht man deine 100-er Schleife unten nicht.
Beim Bedarf lade ich mein Programm mit dem entsprechenden Datenfile hoch, damit Du siehst, dass der oben dargestellte Plot auch ohne eine Schleife ausgegeben wird. Und wenn die Daten an der "read line " -Stelle seriell von der USB-Schnittstelle kommen, wird der Plot einmalig aufgebaut und die Skalierung der Abzisse (Zeitachse) mit den fortlaufenden Dateneingängen dichter wird und die Kurvenlinien zusammenschrumpfen unabhänlig von der Pythonversion, sowohl auf Windows, als auch auf Mac und IOS, wo ich auf die Bluetooth-Verbindung angewiesen bin.
Dass ich nach knapp einer Woche kein Python-Programmierer sein kann, ist keine Frage. Man fängt alles im Leben klein an;)
Wie schon geschrieben, beide Programmteile funktionieren. Nur die Übergabe von Daten von Bluetooth-Leseprogramm zum Plot-Animate-Programm funktioniert nicht. Wenn keiner hier eine Lösung weißt und meine erste Schritte als Copy & Paste und Hammerschlagmethode (fast beleidigend) kritisiert, dann bin ich hier im falschen Forum.
Beim Bedarf lade ich mein Programm mit dem entsprechenden Datenfile hoch, damit Du siehst, dass der oben dargestellte Plot auch ohne eine Schleife ausgegeben wird. Und wenn die Daten an der "read line " -Stelle seriell von der USB-Schnittstelle kommen, wird der Plot einmalig aufgebaut und die Skalierung der Abzisse (Zeitachse) mit den fortlaufenden Dateneingängen dichter wird und die Kurvenlinien zusammenschrumpfen unabhänlig von der Pythonversion, sowohl auf Windows, als auch auf Mac und IOS, wo ich auf die Bluetooth-Verbindung angewiesen bin.
Dass ich nach knapp einer Woche kein Python-Programmierer sein kann, ist keine Frage. Man fängt alles im Leben klein an;)
Wie schon geschrieben, beide Programmteile funktionieren. Nur die Übergabe von Daten von Bluetooth-Leseprogramm zum Plot-Animate-Programm funktioniert nicht. Wenn keiner hier eine Lösung weißt und meine erste Schritte als Copy & Paste und Hammerschlagmethode (fast beleidigend) kritisiert, dann bin ich hier im falschen Forum.
Dafür das du wenig Ahnung hast, erklärst du mir mit großer Inbrunst was ich falsch mache. Und erzählst dabei Unfug. Es ist selbstverständlich völlig unerheblich, ob die Daten aus einer Datei kommen, oder wie bei mir generiert werden. Oder per Bluetooth eingelesen, wo sie dann ebenfalls nicht in einer Datei landen. Wozu denn auch? Sie müssen für matplotlib in einer Liste stehen. WIE die Liste erzeugt wird, ist unerheblich.
ich habe aber rausgefunden, woran es liegt. Jeder Aufruf von plt.show() produziert ein Bild in der Konsole. Folgender Code ist auch bei mir animiert:
Wenn dir diese Form der Ausgabe reicht, dann lies deine Daten in der while Schleife ein, und plotte halt jedes mal neu.
ich habe aber rausgefunden, woran es liegt. Jeder Aufruf von plt.show() produziert ein Bild in der Konsole. Folgender Code ist auch bei mir animiert:
Code: Alles auswählen
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import style
import time
import random
style.use('fivethirtyeight')
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
xs = []
ys = []
def animate():
#print(i)
xs.append(random.random())
ys.append(len(xs))
ax1.clear()
ax1.plot(ys, xs)
while True:
animate()
plt.show()
time.sleep(1)
@Dymo: Ein wenig "Hammerschlag" ist schon dabei. Hast Du Dich einmal gefragt, wofür das "i" in 'def animate(i):' steht? Du verwendest es nicht und scheinst auch die API für FuncAnimation nicht korrekt zu nutzen. Der Parameter Frames nimmt auch eine data-generation Function entgegen um neue oder geänderte Daten dann periodisch an die animate-Function zu senden. Jedenfalls verstehe ich so die Dokumentation:
https://matplotlib.org/_modules/matplot ... cAnimation
Bevor ich mich auf möglicherweise zweitklassige Tutorials verlasse, würde ich mich dort erst einmal einlesen wollen.
https://matplotlib.org/_modules/matplot ... cAnimation
Bevor ich mich auf möglicherweise zweitklassige Tutorials verlasse, würde ich mich dort erst einmal einlesen wollen.
@kbr: das animation feature gibts eh nicht in Pythonista. Jedenfalls nicht ohne ein eigenes Rendering backend zu schreiben, das hier nicht zum Einsatz kommt.
Was Pythonista macht ist, einfach ein Full Screen Rendering in die Konsole zu schreiben. Das ist ja völlig prima, aber hat mit der animations api nix zu tun.
Was Pythonista macht ist, einfach ein Full Screen Rendering in die Konsole zu schreiben. Das ist ja völlig prima, aber hat mit der animations api nix zu tun.
@__deets__: ok. Ich bezog mich auf den geposteten Code, in dem FuncAnimation() Verwendung findet und dann eben auf die Doku dazu. Mögliche Einschränkungen durch Pythonista habe ich nicht gesucht – wenn animation dort nicht unterstützt wird, ist der ursprüngliche Ansatz mit FuncAnimation ohnehin sinnlos.
Mensch __deets__, wir verstehen uns offenbar miss, oder besser Du mich. Es ging nicht um das Plot-Modul, denn das läuft richtig, wenn die Bluetooth-Ausgaben dort ankommen, wo Du deine Zufallgeneratoren hin gepackt hast.
Ich bin zwar neu in Phython, aber nicht doof im logischen Denken.
Ich bin zwar neu in Phython, aber nicht doof im logischen Denken.
Bei mir laeuft dein Tutorial-Beispiel nicht. Bei mir laeuft auch in Pythonista MEIN Beispiel nicht. Es laeuft aber problemlos auf meinem Desktop PC und animiert. Die offizielle Dokumentation
http://omz-software.com/pythonista/matp ... index.html
sagt "Most examples in this documentation should "just work" in Pythonista, interactive charts (with GUI) and animation are not supported though. "
Die Leute im Forum von Pythonista sagen es geht nicht.
So. Wie kommen wir nun weiter? Dein Animations-Tutorial laeuft bei mir nicht, und es bringt auch nichts, denn ich habe keine Datei, und brauche auch keine. Wie soll die sich auch automitsch aendern (so wie es dein Tutorial vorsieht).
Laeuft MEIN Beispiel (das erste)? Wenn ja, dann hast du irgendwas anderes in deiner Pythonista-Umgebung gemacht, woran das liegt. Das normale kann es nicht.
Und wenn wir das etabliert haben, dann sehen wir weiter.
http://omz-software.com/pythonista/matp ... index.html
sagt "Most examples in this documentation should "just work" in Pythonista, interactive charts (with GUI) and animation are not supported though. "
Die Leute im Forum von Pythonista sagen es geht nicht.
So. Wie kommen wir nun weiter? Dein Animations-Tutorial laeuft bei mir nicht, und es bringt auch nichts, denn ich habe keine Datei, und brauche auch keine. Wie soll die sich auch automitsch aendern (so wie es dein Tutorial vorsieht).
Laeuft MEIN Beispiel (das erste)? Wenn ja, dann hast du irgendwas anderes in deiner Pythonista-Umgebung gemacht, woran das liegt. Das normale kann es nicht.
Und wenn wir das etabliert haben, dann sehen wir weiter.