Serielle Schnittstelle liest Daten nicht mehr aus

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
HansAli
User
Beiträge: 1
Registriert: Donnerstag 25. Februar 2016, 21:50

Hallo,
ich habe ein script, welches einen Frequenzgenerator steuert und Daten ausliest. Bisher hat es auch alles sehr gut funktioniert und die ausgelesenen Daten wurden in der shell ausgegben aus einem mir unerklärlichen Grund funktioniert das nun nicht mehr, obwohl ich meiner Meinung nach nichts verändert habe. Die Ansteuerung funktioniert noch super und auch die Abschaltung nach dem sweep funktioniert wie bisher nur die Daten werden halt nicht ausgelesen oder nicht angezeigt. Habe leider wenig Ahnung von der Python Programmierung...
Ich hoffe irgendjemand hat eine Ahnung woran das ganze liegen könnte, wäre da über jeden Rat sehr dankbar. Vielleicht habe ich auch nur irgendwo ausversehen was umgestellt?

Gruß Ali

Code: Alles auswählen

run = 0
data = []
xdata = []
phase = []

def plot():
    global data
    global xdata
    y_data = np.array(data)
    x_data = np.array(xdata)
    plt.figure()
    plt.plot(x_data,y_data,'.')
    plt.ylabel('some numbers')
    #np_diff = np.diff(x_data)
    #print x_data[np.where(np_diff > 1)]
    plt.show()
    return

def save_data():
    global data
    global xdata
    np.savez('data7.npz', xdata=xdata, data=data,phase=phase)
    np.savetxt('data7.out', (xdata, data))
    DAT =  np.column_stack((xdata, data))
    np.savetxt('test7.txt', DAT, delimiter=" ", fmt="%s") 

# an exit procedure
def mQuit():
    # ask yes/no question to confirm exit
    mExit = tkMessageBox.askyesno(title = "Quit", message = "Do you really want to quit?")
    if mExit > 0:
        # close port
        ser.close()
        ser2.close()
        #f.close()
        # detsroy GUI
        root.destroy()
        return
 
# sending commands to the MWG
def mSend(command):
    try:
        ser.write(command)
    except:
        print "Could not send command. Port closed?"     
    return
def mSend2(command):
    try:
        ser2.write(command)
    except:
        print "Could not send command. Port closed?"     
    return

def serial_ports():
    """Lists serial ports

    :raises EnvironmentError:
        On unsupported or unknown platforms
    :returns:
        A list of available serial ports
    """
    if sys.platform.startswith('win'):
        ports = ['COM' + str(i + 1) for i in range(256)]

    elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
        # this is to exclude your current terminal "/dev/tty"
        ports = glob.glob('/dev/tty[A-Za-z]*')

    elif sys.platform.startswith('darwin'):
        ports = glob.glob('/dev/tty.*')

    else:
        raise EnvironmentError('Unsupported platform')

    result = []
    for port in ports:
        try:
            s = serial.Serial(port)
            s.close()
            result.append(port)
        except (OSError, serial.SerialException):
            pass
    return result

def onselect(event):
    w = event.widget
    index = w.curselection()[0]
    #print w.get(w.curselection())
    # open port if not already open
    try:
        ser.port = w.get(w.curselection())
        print w.get(w.curselection())
        if ser.isOpen() == False:
            ser.open()
        serial_stat.set("Serial port open: "+str(ser.isOpen()))
    except:
        print("Port '" + ser.port + "' konnte nicht geoeffnet werden...")
    #print "You selected: %d" % int(index)
    return int(index)


def sweep_thread():
    global run
    thread2 = myThread2("Sweep", ser,ser2)
    run = 1
    thread2.start()
    thread.start()
    return 1

def sweep_stop():
    global run
    run = 0
    data = []
    xdata = []
    return 1  

# A thread that continously request the status of the MWG
class myThread2 (threading.Thread):
    # initialize class
    def __init__(self, name, ser, ser2):
        threading.Thread.__init__(self)
        # Name of thread
        self.name = name
        # Serial port information
        self.ser  = ser
        self.ser2 = ser2
        # the request commands
 
    # gets called when thread is started with .start()
    def run(self):
        global run
        t_step = float(D_sendvar.get());
        f_step = float(G_sendvar.get());
        f_start = float(F_sendvar.get());
        f_stop = float(E_sendvar.get());
        f_akt = f_start
        mSend("FUNC SIN\n")
        time.sleep(0.01)
        mSend("VOLT "+ H_sendvar.get() + "\n")
        time.sleep(0.01)
        mSend("FREQ "+ F_sendvar.get() + "E+0\n")
        time.sleep(0.01)
        mSend("OUTP 1\n")
        time.sleep(1)
        for i in np.arange(f_start,f_stop+f_step,f_step):
            if not run:
                break
            time.sleep(t_step)
            mSend("FREQ "+ "{:.2f}".format(f_akt) + "E+0\n")
            mSend2("SNAP?3,4,9\n")
            m_var.set("{:.2f}".format(f_akt)) # Voltage
            f_akt += f_step
        time.sleep(t_step)
        mSend("OUTP 0\n")
        time.sleep(t_step)
        run = 0
        return 1

# A thread that continously request the status of the MWG
class myThread (threading.Thread):
    # initialize class
    def __init__(self, name, ser2):
        threading.Thread.__init__(self)
        # Name of thread
        self.name = name
        # Serial port information
        self.ser  = ser2
        # the request commands     
        #self.queue = queue #the received data is put in a queue   
        self.serBuff = ''
        self.buffer = ''
        #self.f = f
        #self.diff_var = diff_var
 
    # gets called when thread is started with .start()
    def run(self):
        # counter of the while loop
        self.update_count = 0
        
        while self.ser.isOpen():
            if run:     
                #self.buffer += self.ser.read(self.ser.inWaiting()) #read all char in buffer
                self.buffer += self.ser.read(102) #read all char in buffer
                while '\r' in self.buffer: #split data line by line and store it in var
                    var, self.buffer = self.buffer.split('\r', 1)
                    #print len(var)
                    #self.queue.put(var) #put received line in the queue
                    data_tmp = var.split(',')
                    print data_tmp
                    if len(data_tmp)==3:                    
                        data.append(float(data_tmp[0]))
                        xdata.append(float(data_tmp[2]))
                        phase.append(float(data_tmp[1]))
            else:
                time.sleep(0.1)
                
# ===========================
# Begin of the main program
# ===========================
 
# provide information for serial port
ser = serial.Serial()
ser.port = '/dev/ttyS0'
ser.baudrate = 57600
ser.timeout = 0

ser2 = serial.Serial()
ser2.port = 'COM8'
ser2.baudrate = 9600
ser2.timeout = 0
 
# set up root window
root = tk.Tk()
root.geometry("550x350")
root.title("ME-Messaufbau Control")
 
# variables (explanation see below)
a_var = tk.StringVar()
b_var = tk.StringVar()
c_var = tk.StringVar()
d_var = tk.StringVar()
e_var = tk.StringVar()
f_var = tk.StringVar()
g_var = tk.StringVar()
h_var = tk.StringVar()
k_var = tk.StringVar()
l_var = tk.StringVar()
m_var = tk.StringVar()
n_var = tk.StringVar()
serial_stat = tk.StringVar()
 
A_sendvar = tk.StringVar()
B_sendvar = tk.StringVar()
C_sendvar = tk.StringVar()
D_sendvar = tk.StringVar()
E_sendvar = tk.StringVar()
F_sendvar = tk.StringVar()
G_sendvar = tk.StringVar()
H_sendvar = tk.StringVar()
I_sendvar = tk.StringVar()
Z_sendvar = tk.StringVar()
 
UpdateC   = tk.StringVar()
rec_file  = tk.StringVar()
rec_stat  = tk.StringVar()
rec_stat.set("not recording")
row_start = 4
 
global f       # save file
 
 
# headlines
mHeader    = ttk.Label(root, text = "ME-Messaufbau Control").grid(row=0, column=1)


mStatus    = ttk.Label(root, textvariable = serial_stat).grid(row=1, column=1)
mQButton   = ttk.Button(root, text = "close port and quit", command = mQuit).grid(row=1, column=2)
mUpdateC   = ttk.Label(root, textvariable = UpdateC).grid(row=1,column=3)
mSeperate  = ttk.Label(root, text = "===========================").grid(row=2, column=1)
mSubhead_l = ttk.Label(root, text = "STATUS").grid(row=3, column=1)
mSubhead_r = ttk.Label(root, text = "SET").grid(row=3, column=2)
 

Lb1 = tk.Listbox(root, height = 3)
Lb1.grid(row=row_start+1, column=2)
parentlist = serial_ports()

for item in parentlist:
    Lb1.insert('end', item)

Lb1.insert('end', '/dev/pts/8')

Lb1select = Lb1.bind('<<ListboxSelect>>',onselect)
Lb1.selection_set(2)

# open port if not already open
try:
    ser.port = Lb1.get(Lb1.curselection())
    if ser.isOpen() == False:
        ser.open()
    serial_stat.set("Serial port open: "+str(ser.isOpen()))
except:
    print("Port '" + ser.port + "' konnte nicht geoeffnet werden...")

try:
    if ser2.isOpen() == False:
        ser2.open()
    #serial_stat.set("Serial port open: "+str(ser.isOpen()))
except:
    print("Port '" + ser2.port + "' konnte nicht geoeffnet werden...")

s = ttk.Separator(root, orient="horizontal").grid(row=row_start+3, columnspan=4, sticky="ew")
 
d_Label = ttk.Label(root, text = "Time Step").grid(row=row_start+4, column=0)
d_Show  = ttk.Label(root, textvariable = d_var).grid(row=row_start+4, column=1)
d_Entry = ttk.Entry(root, textvariable = D_sendvar).grid(row=row_start+4, column=2)
#d_Button = ttk.Button(root, text ="send", command = lambda: mSend("STOP "+ D_sendvar.get() + "\n")).grid(row=row_start+4, column=3)
 
f_Label = ttk.Label(root, text = "Freq Start").grid(row=row_start+5, column=0)
f_Show  = ttk.Label(root, textvariable = f_var).grid(row=row_start+5, column=1)
f_Entry = ttk.Entry(root, textvariable = F_sendvar).grid(row=row_start+5, column=2)
#f_Button = ttk.Button(root, text ="send", command = lambda: mSend("START "+ F_sendvar.get() + "\n")).grid(row=row_start+5, column=3)

e_Label = ttk.Label(root, text = "Freq Stop").grid(row=row_start+6, column=0)
e_Show  = ttk.Label(root, textvariable = e_var).grid(row=row_start+6, column=1)
e_Entry = ttk.Entry(root, textvariable = E_sendvar).grid(row=row_start+6, column=2)
#e_Button = ttk.Button(root, text ="send", command = lambda: mSend("STOP "+ E_sendvar.get() + "\n")).grid(row=row_start+6, column=3)

g_Label = ttk.Label(root, text = "Freq Step").grid(row=row_start+7, column=0)
g_Show  = ttk.Label(root, textvariable = g_var).grid(row=row_start+7, column=1)
g_Entry = ttk.Entry(root, textvariable = G_sendvar).grid(row=row_start+7, column=2)
#g_Button = ttk.Button(root, text ="send", command = lambda: mSend("STEP "+ G_sendvar.get() + "\n")).grid(row=row_start+7, column=3)

h_Label = ttk.Label(root, text = "Voltage").grid(row=row_start+8, column=0)
h_Show  = ttk.Label(root, textvariable = h_var).grid(row=row_start+8, column=1)
h_Entry = ttk.Entry(root, textvariable = H_sendvar).grid(row=row_start+8, column=2)
#h_Button = ttk.Button(root, text ="send", command = lambda: mSend("H"+H_sendvar.get())).grid(row=row_start+8, column=3)

#m_ButtonB = ttk.Button(root, text ="Send All", command = lambda: sendall()).grid(row=row_start+9, column=3)
 
#k_Label = ttk.Label(root, text = "start mode").grid(row=row_start+8, column=0)
#k_Show  = ttk.Label(root, textvariable = k_var).grid(row=row_start+8, column=1)
#k_Entry = ttk.Entry(root, textvariable = G_sendvar).grid(row=row_start+8, column=2)
#k_Button = ttk.Button(root, text ="send", command = lambda: mSend("G"+G_sendvar.get())).grid(row=row_start+8, column=3)
 
#l_Label = ttk.Label(root, text = "generator state").grid(row=row_start+9, column=0)
#l_Show  = ttk.Label(root, textvariable = l_var).grid(row=row_start+9, column=1)
     
m_Label = ttk.Label(root, text = "Akt. Freq").grid(row=row_start+10, column=0)
m_Show  = ttk.Label(root, textvariable = m_var).grid(row=row_start+10, column=1)
m_ButtonA = ttk.Button(root, text ="Start Sweep", command = lambda: sweep_thread()).grid(row=row_start+10, column=2)
m_ButtonB = ttk.Button(root, text ="Stop Sweep", command = lambda: sweep_stop()).grid(row=row_start+10, column=3)
 
 
#rec_Label = ttk.Label(root, text = "Dateiname: File name").grid(row=row_start+12, column=0)
#rec_Entry = ttk.Entry(root, textvariable = rec_file).grid(row=row_start+12, column=1)
plot_Button = ttk.Button(root, text = "Plot", command = lambda: plot()).grid(row=row_start+12, column=2)
save_Button = ttk.Button(root, text = "Save", command = lambda: save_data()).grid(row=row_start+12, column=3)
#rec_ButtonC = ttk.Button(root, text = "Status", command = lambda: mSend("STATUS?\n")).grid(row=row_start+13, column=2)
#rec_LabelS  = ttk.Label(root, textvariable = rec_stat).grid(row=row_start+14, column=1)
#rec_LabelF  = ttk.Label(root, textvariable = rec_file).grid(row=row_start+14, column=2)

# wait
#time.sleep(1)
# call and start update-thread
thread2 = myThread2("Sweep", ser, ser2)
thread = myThread("amp", ser2)

#thread2.start()
mSend("STATUS?\n")
# start GUI
root.protocol("WM_DELETE_WINDOW", mQuit)
root.mainloop()

BlackJack

@HansAli: Das könnte daran liegen das man bei so einem grossen Programm mit globalen Variablen schnell den Überblick verliert, selbst wenn man selber der Autor ist, und das man da auch kaum etwas isoliert testen kann um Fehler zu finden. Das das Programm dann auch noch Threads verwendet, macht es noch problematischer.

Schreib das am besten noch mal neu. Ohne ``global``, nur mit Definitionen von Konstanten, Funktionen, und Klassen auf Modulebene, mit dem Hauptprogramm in einer Funktion, und Funktionen die den Namen auch wirklich verdient haben. Werte, ausser Konstanten, sollten Funktionen (und Methoden) als Argumente betreten und gegebenfalls als Rückgabewerte verlassen. Ausserdem sollte man die Programmlogik sauber von der GUI trennen. Dann kann man sich das Programm auch betrachten ohne die kompletten ≈350 Zeilen Quelltext auf einmal im Blick zu haben. Und auch einzelne Funktionen einfach testen.
Antworten