Variable & Display

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Consti9_9
User
Beiträge: 24
Registriert: Dienstag 4. Dezember 2018, 09:09

Hallo zusammen,

ich habe gerade das Problem das ich eine Variable an meinem Display anzeigen will. Hierbei handelt es sich um Stromwerte nach einer ADC Messung. Das Programm hierfür ist schon fertig.
Jedoch möchte ich diese Variablen jetzt in einem anderen Programm in dem ich das Display ansteuere die Variablen importieren.
Mit dem Befehl:

from ADC_funkt import f,k

startet das Programm zwar, jedoch werden mir alle 8 Stromwerte angezeigt und das Programm startet nicht die Display Oberfläche.
Was könnte hier der Fehler sein?
Sirius3
User
Beiträge: 18268
Registriert: Sonntag 21. Oktober 2012, 17:20

@Consti9_9: da keiner Dein Programm kennt, kann man dazu nichts sagen. Es kommen auch plötzlich 8 Stromwerte vor, und Du verrätst nicht, woher die plötzlich kommen. Statt ›Programm‹ meinst Du wahrscheinlich ›Modul‹ und das sollte ohne Nebeneffekte importierbar sein, was wahrscheinlich dein Problem erklärt.

Für eine vollständige Fehlerbeschreibung fehlt der Code, die Fehlermeldung und der Traceback, falls einer auftritt und eben eine verständliche Erklärung.
Benutzeravatar
noisefloor
User
Beiträge: 4187
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

die Beschreibung ist ein bisschen schwer zu verstehen.

Grundsätzlich: wenn du eine Variable aus eine anderen Modul importierst, importierst du den Wert zum Zeitpunkt des Imports. Die Variable aktualisiert sich nicht auto-magisch. Für den Datenaustausch zwischen zwei unabhängigen Programmen läuft anders, da gibt es verschiedene Methoden, dass zu machen.

Besser wäre auch, wenn du mal deinen Quellcode zeigst, damit zu sehen ist, was du schon probiert hast.

Gruß, noisefloor
Consti9_9
User
Beiträge: 24
Registriert: Dienstag 4. Dezember 2018, 09:09

Das erste Programm berechnet Stromwerte mittels Strommesssensoren und einem AD-Wandler welche dann die Stromwerte anzeigt. Diese Werte will ich dann anschließend an dem Raspi-Display anzeigen jedoch in einem anderen Programm 2.

Programm 1(ADC_funkt):

Code: Alles auswählen

from mcp3208 import MCP3208 #import des MCP Moduls
import time #import des Zeitmoduls um Zeitverzögerungen zu erstellen
adc = MCP3208() #Namen um MCP ansprechen zu können und zu verkürzen
global  a #Definition Variable a
import numpy #Import der Bibliothek für Mittelwerte


while True: #Endlosschleife
    werte_0 = [] #Liste erstellen
    for i in range(32):
        werte_0.append(adc.read(0)) #Auslesen des 0. Kanals
    #print(werte_0) #Ausgabe der Werte in einer Liste aufgrund append
    a = 3103 - numpy.mean(werte_0) #Berechnen der Differenz
    j = (a/185)*1 #Berechnen des vorhandenen Stroms laut Berechnung
    print("Stromwert 1:",j.round(3)) #Ausgabe des Stromwerts
    werte_1 = [] #Liste erstellen
    for i in range(32):
        werte_1.append(adc.read(1)) #Auslesen des 0. Kanals
    #print(werte_0) #Ausgabe der Werte in einer Liste aufgrund append
    b = 3103 - numpy.mean(werte_1) #Berechnen der Differenz
    k = (b/185)*1 #Berechnen des vorhandenen Stroms laut Berechnung
    print("Stromwert 2:",k.round(3)) #Ausgabe des Stromwerts
    werte_2 = [] #Liste erstellen
    for i in range(32):
        werte_2.append(adc.read(2)) #Auslesen des 0. Kanals
    #print(werte_0) #Ausgabe der Werte in einer Liste aufgrund append
    c = 3103 - numpy.mean(werte_2) #Berechnen der Differenz
    l = (c/185)*1 #Berechnen des vorhandenen Stroms laut Berechnung
    print("Stromwert 3:",l.round(3)) #Ausgabe des Stromwerts
    time.sleep(1) 
Programm 2(Taster):

Code: Alles auswählen

from tkinter import *
import tkinter as tk
import tkinter.font
#import Imagetk
import RPi.GPIO as GPIO
from ADC_funkt import j,k
          
GPIO.cleanup()
GPIO.setmode(GPIO.BCM)

GPIO.setup(23, GPIO.OUT)
GPIO.output(23, GPIO.LOW)
GPIO.setup(24, GPIO.OUT)
GPIO.output(24, GPIO.LOW)
GPIO.setup(19, GPIO.OUT)
GPIO.output(19, GPIO.LOW)
GPIO.setup(25, GPIO.OUT)
GPIO.output(25, GPIO.LOW)

#Erstellen des Fenster
win = Tk()
#image = PhotoImage(file="hintergrund.jpg")
win.attributes("-fullscreen",True)
#background=Label(win, image=image)
#background.place(x=0,y=0,relwidth=1, relheights=1)


#Erstellen eines Hintergrunds
#image = PhotoImage(file="background.jpg")
#background=Label(win, image=image)
#background.place(x=0,y=0,relwidth=1, relheight=1)

#Erstellen einer Schrift
myFont = tkinter.font.Font(family = 'Helvetica', size = 20, weight = 'bold')

#Buttons 
def ScheinwerferON():
        print("Scheinwerfer eingeschaltet")
        if GPIO.input(23) :
            GPIO.output(23,GPIO.LOW)
            ScheinwerferButton["text"] = "Scheinwerfer an"
        else:
            GPIO.output(23,GPIO.HIGH)
            ScheinwerferButton["text"] = "Scheinwerfer aus"

def LuftpumpeON():
        print("Luftpumpe eingeschaltet")
        if GPIO.input(24) :
            GPIO.output(24,GPIO.LOW)
            LuftpumpeButton["text"] = "Luftpumpe an"
        else:
            GPIO.output(24,GPIO.HIGH)
            LuftpumpeButton["text"] = "Luftpumpe aus"

def LautsprecherON():
        print("Lautsprecher eingeschaltet")
        if GPIO.input(25) :
            GPIO.output(25,GPIO.LOW)
            LautsprecherButton["text"] = "Lautsprecher an"
        else:
            GPIO.output(25,GPIO.HIGH)
            LautsprecherButton["text"] = "Lautsprecher aus"
            
            
def KühlboxON():
        print("Kühlbox eingeschaltet")
        if GPIO.input(19) :
            GPIO.output(19,GPIO.LOW)
            KühlboxButton["text"] = "Kühlbox an"
        else:
            GPIO.output(19,GPIO.HIGH)
            KühlboxButton["text"] = "Kühlbox aus"

def exitProgram():
        win.destroy()
        print("Exit Button pressed")
        GPIO.cleanup()

#Name und Groese des Fensters
win.title("BeachBuggy")
win.geometry('800x480')

#Definition des Exit Buttons
exitButton = Button(win, text = "Exit", font = myFont, command = exitProgram, height = 2, width = 5)
exitButton.place(x=300, y=200)

#Definition des Luftpumpe Buttons
LuftpumpeButton = Button(win, text = "Luftpumpe ein", font = myFont, command = LuftpumpeON, height = 2, width = 14)
LuftpumpeButton.place(x=525, y=50)

#Definition des Kühlbox Buttons
KühlboxButton = Button(win, text = "Kühlbox ein", font = myFont, command = KühlboxON, height = 2, width = 14)
KühlboxButton.place(x=525, y=150)

#Definition des Lautsprecher Buttons
LautsprecherButton = Button(win, text = "Lautsprecher ein", font = myFont, command = LautsprecherON, height = 2, width = 14)
LautsprecherButton.place(x=525, y=350)

#Definiton des LED Buttons
ScheinwerferButton = Button(win, text = "Scheinwerfer ein", font = myFont, command = ScheinwerferON, height = 2, width = 14)
ScheinwerferButton.place(x=525, y=250)

mainloop()
Möchte es an dem Display anzeigen an welchem schon Taster zu sehen sind und Ausgänge ein und ausgeschaltet werden können.
Hierbei soll dann neben dem Ausgang der jeweilige Stromwert zu sehen sein.
Consti9_9
User
Beiträge: 24
Registriert: Dienstag 4. Dezember 2018, 09:09

Und das Problem ist schätze ich das Programm 1 eine Endlosschleife ist und somit das Programm 2 nie weiter machen kann. Nur wie kann ich das verhindern weil die Werte müssen ja immer neu berechnet werden und dann in Programm 2 sich ändern
Sirius3
User
Beiträge: 18268
Registriert: Sonntag 21. Oktober 2012, 17:20

@Consti9_9: Du redest immer von Programmen, aber es gibt immer nur ein Programm, das aus verschiedenen Modulen zusammengesetzt werden kann. Ein Modul besteht aus Funktionen, Du mußt also „Programm1” in eine Funktion umschreiben, die genau einmal mißt, keine Endlosschleife. Diese Funktion kannst Du dann regelmäßig in Deinem Tk-Inter-Programm aufrufen, z.B. per after.
Sirius3
User
Beiträge: 18268
Registriert: Sonntag 21. Oktober 2012, 17:20

Zum Programm selbst: `global` solltest Du nicht verwenden, macht auch, wie Du es benutzt, keinen Sinn. In der while-Schleife wird drei mal das selbe gemacht, was man gut in eine Funktion, die man drei mal aufruft, auslagern kann. Die Kommentare sind allesamt überflüssig, da sie nur beschreiben, was sowieso im Code steht, außer dass im Kommentar nicht die Änderungen beim Kopieren gemacht wurden, die im Code gemacht wurden, so dass die beiden sich widersprechen.
›ADC_funkt‹ ist ein seltsamer Name, denn da funkt ja gar nichts, sondern es wird nur eingelesen.

Für GUI-Programme braucht man relativ schnell Klassen, weil es sonst unübersichtlich wird. Funktionen sollten nur das benutzen, was sie per Argumente bekommen. Eingerückt wird immer mit 4 Leerzeichen pro Ebene, nicht mal 8 und mal 4.
Consti9_9
User
Beiträge: 24
Registriert: Dienstag 4. Dezember 2018, 09:09

Und wie schaffe ich es jetzt dann das obere in eine Funktion zu schreiben und diese dann in einem Label im unteren (welches noch nicht vorhanden ist) zu schreiben das es dann am Display angezeigt wird?
Sirius3
User
Beiträge: 18268
Registriert: Sonntag 21. Oktober 2012, 17:20

Wie Funktionen geschrieben werden, hast Du scheinbar schon verstanden. Wo ist das konkrete Problem?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Den Code, den du hast, in eine Funktion stecken. Und die while-Schleife entfernen, ebenso wie die ueberfluessigen weil falschen Kommentare. Oder liest du wirklich 3mal ADC Kanal 0 aus? Sieht mir nicht so aus...
Consti9_9
User
Beiträge: 24
Registriert: Dienstag 4. Dezember 2018, 09:09

Das untere "Programm" oder wie man es nennen mag zeigt mir ja bis jetzt die Taster an. Jetzt weis ich nicht wie ich die beiden zusammenfügen soll bzw. wie ich es schaffe das in einem Label der Stromwert eines Kanals angezeigt wird. Also konkret weis ich gerade nicht wie und wo ich jetzt die Berechnung der Stromwerte einfüge das es das andere "Programm" nicht stört
Benutzeravatar
__blackjack__
User
Beiträge: 14036
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Consti9_9: Du schreibst erst einmal das obere ”Programm” so um, das es ein Modul mit einer Funktion ist, die die Stromwerte ermittelt, vielleicht auch besser nur einen, und man per Argument wählen kann welchen. Die Funktion muss den/die Stromwert(e) an den Aufrufer zurückgeben. Diese Funktion kannst Du dann im unteren Programm importieren und regelmässig aufrufen und das Ergebnis in einem Label darstellen. Dazu brauchst Du die `after()`-Methode. Nun könnte man dort natürlich das/die Label auch immer mit durchreichen, aber sauberer wäre eigentlich ein objektorientierter Ansatz.

`numpy` um den Mittelwert von 32 Werten zu berechnen ist vielleicht ein kleines bisschen overkill. Ich würde da ja das `statistics`-Modul aus der Standardbibliothek für verwenden. :-)
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Benutzeravatar
noisefloor
User
Beiträge: 4187
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

im allerersten Schritt würde ich dir auch dringend dazu raten, die GUI in eine Klasse zu packen, sonst ist es mega-unübersichtlich. In dem Zuge kannst du auch die doppelten Importe rauskicken, weil die tkinter 1x komplett in dem globalen Namensraum importierst (schlecht) und 1x in den Namensraum tk (richtig).

Die Funktionsnamen deiner GUI sind schlecht, weil z.B. "ScheinwerferON" ja lt. Code den Scheinwerfer aus ausschalten kann. Funktionsnamen schreibt man per Konvention klein_mit_unterstrich. Und besser auch komplett in einer Sprache, also z.B. "scheinwerfer_an" und nicht in denglisch.

Wenn du die Messung des Stromwerts in eine Funktion _ohne_ while-Schleife packst, dann stört da gar nichts, weil du die Funktion ja explizit aufrufen musst, damit diese "läuft". Jeder Aufruf gibt dann die drei Werte zurück, die zeigst du dann als Label in Tkinter an.

Wenn dir das mit Funktionen und Rückgabewerten nicht klar ist, solltest du die entsprechende Sektion im Python-Tutorial nochsmal durcharbeiten.

Gruß, noisefloor
Consti9_9
User
Beiträge: 24
Registriert: Dienstag 4. Dezember 2018, 09:09

Danke schonmal, okay also ich versuche jetzt das erste Programm in eine Funktion bzw als Modul zu definieren. Jedoch stellt sich dann mir hier die Frage ob ich in dem unteren Programm dann eine Schleife brauche oder wie ich das löse das die Werte alle 2 Sekunden erneut ausgelesen und berechnet werden?
Benutzeravatar
__blackjack__
User
Beiträge: 14036
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Consti9_9: In dem GUI-Programm brauchst Du die `after()`-Methode. Schleife geht nicht, denn immer wenn diese Schleife laufen würde, könnte die GUI-Hauptschleife nicht laufen.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Consti9_9
User
Beiträge: 24
Registriert: Dienstag 4. Dezember 2018, 09:09

Okay danke nur ich finde nichts wie ich die Methode anwende oder was diese Bezweckt
Consti9_9
User
Beiträge: 24
Registriert: Dienstag 4. Dezember 2018, 09:09

root.after(0, add_letter) # add_letter will run as soon as the mainloop starts.
root.mainloop()

Muss ich hier meine Funktion eintragen die ich erstellt habe um die Stromwerte auslesen zu können. Was dann bedeutet das ich die Variablen verwenden kann und in ein Label schreiben kann?
Benutzeravatar
__blackjack__
User
Beiträge: 14036
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Consti9_9: Ich würde den `after()`-Aufruf ans Ende der Methode setzen, die das macht und die am Anfang einmal aufrufen, denn Du willst das ja nicht nur einmal und sofort, sondern immer wieder, mit einer gewissen Verzögerung.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Sirius3
User
Beiträge: 18268
Registriert: Sonntag 21. Oktober 2012, 17:20

Nein, Du mußt eine Funktion angeben, die die Funktion mit den Stromwerten aufruft und diese dann in einem Label darstellt.
Consti9_9
User
Beiträge: 24
Registriert: Dienstag 4. Dezember 2018, 09:09

Also einfach nur "after()" ans Ende des Programms:

Code: Alles auswählen

from mcp3208 import MCP3208 #import des MCP Moduls
import time #import des Zeitmoduls um Zeitverzögerungen zu erstellen
adc = MCP3208() #Namen um MCP ansprechen zu können und zu verkürzen
global  a #Definition Variable a
import numpy #Import der Bibliothek für Mittelwerte

def Stromwert():
        werte_0 = [] #Liste erstellen
        for i in range(32):
            werte_0.append(adc.read(0)) #Auslesen des 0. Kanals
        #print(werte_0) #Ausgabe der Werte in einer Liste aufgrund append
        a = 3103 - numpy.mean(werte_0) #Berechnen der Differenz
        j = (a/185)*1 #Berechnen des vorhandenen Stroms laut Berechnung
        print("Stromwert 1:",j.round(3),"A") #Ausgabe des Stromwerts
        werte_1 = [] #Liste erstellen
        for i in range(32):
            werte_1.append(adc.read(1)) #Auslesen des 0. Kanals
        #print(werte_0) #Ausgabe der Werte in einer Liste aufgrund append
        b = 3103 - numpy.mean(werte_1) #Berechnen der Differenz
        k = (b/185)*1 #Berechnen des vorhandenen Stroms laut Berechnung
        print("Stromwert 2:",k.round(3),"A") #Ausgabe des Stromwerts
        werte_2 = [] #Liste erstellen
        for i in range(32):
            werte_2.append(adc.read(2)) #Auslesen des 0. Kanals
        #print(werte_0) #Ausgabe der Werte in einer Liste aufgrund append
        c = 3103 - numpy.mean(werte_2) #Berechnen der Differenz
        l = (c/185)*1 #Berechnen des vorhandenen Stroms laut Berechnung
        print("Stromwert 3:",l.round(3),"A") #Ausgabe des Stromwerts
        werte_3 = [] #Liste erstellen
        for i in range(32):
            werte_3.append(adc.read(3)) #Auslesen des 0. Kanals
        #print(werte_0) #Ausgabe der Werte in einer Liste aufgrund append
        d = 3103 - numpy.mean(werte_3) #Berechnen der Differenz
        m = (d/185)*1 #Berechnen des vorhandenen Stroms laut Berechnung
        print("Stromwert 4:",l.round(3),"A") #Ausgabe des Stromwerts
        werte_4 = [] #Liste erstellen
        for i in range(32):
            werte_4.append(adc.read(4)) #Auslesen des 0. Kanals
        #print(werte_0) #Ausgabe der Werte in einer Liste aufgrund append
        e = 3103 - numpy.mean(werte_4) #Berechnen der Differenz
        n = (e/185)*1 #Berechnen des vorhandenen Stroms laut Berechnung
        print("Stromwert 5:",l.round(3),"A") #Ausgabe des Stromwerts
        werte_5 = [] #Liste erstellen
        for i in range(32):
            werte_5.append(adc.read(5)) #Auslesen des 0. Kanals
        #print(werte_0) #Ausgabe der Werte in einer Liste aufgrund append
        f = 3103 - numpy.mean(werte_5) #Berechnen der Differenz
        o = (f/185)*1 #Berechnen des vorhandenen Stroms laut Berechnung
        print("Stromwert 6:",l.round(3),"A") #Ausgabe des Stromwerts
        werte_6 = [] #Liste erstellen
        for i in range(32):
            werte_6.append(adc.read(6)) #Auslesen des 0. Kanals
        #print(werte_0) #Ausgabe der Werte in einer Liste aufgrund append
        g = 3103 - numpy.mean(werte_6) #Berechnen der Differenz
        p = (g/185)*1 #Berechnen des vorhandenen Stroms laut Berechnung
        print("Stromwert 7:",l.round(3),"A") #Ausgabe des Stromwerts
        werte_7 = [] #Liste erstellen
        for i in range(32):
            werte_7.append(adc.read(7)) #Auslesen des 0. Kanals
        #print(werte_0) #Ausgabe der Werte in einer Liste aufgrund append
        h = 3103 - numpy.mean(werte_7) #Berechnen der Differenz
        q = (h/185)*1 #Berechnen des vorhandenen Stroms laut Berechnung
        print("Stromwert 8:",l.round(3),"A") #Ausgabe des Stromwerts
        time.sleep(2)
setzen? Und in dem zweiten Programm welches schon die Taster beinhaltet, rufe ich das Programm mit welchem Befehl auf?
Antworten