Kapazitätsmessgerät mit dem NE555, pyaudio und tkinter

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo,

habe ein Kapazitätsmessgerät zum Messen von kleinen Kapazitäten gebastelt.

Nachbau der Schaltung auf Platine zur Messung über die Soundkarte:
http://www.elexs.de/radio4.htm

Erklärung zur Berechnung der Kapazität am NE555 als astabile Kippstufe:
http://www.elektronik-kompendium.de/sit ... 310131.htm

Code: Alles auswählen

#/usr/bin/env python
# -*- coding: utf-8

import tkinter as tk
import numpy as np
from functools import partial
import pyaudio

WIDTH = 270
HEIGHT = 100

RA = 1 # kOhm
RB = 5 # kOhm
RESISTANCE = (RA + RB * 2) * 0.69


class Capacitance_NE555(object):
    def __init__(self, 
                 resistance, 
                 rate = 44100,
                 frames_per_buffer = 1024):
        self.py_audio = pyaudio.PyAudio()
        self.resistance = resistance
        self.rate = rate
        self.frames_per_buffer = frames_per_buffer
        self.cap_reference = None
        
    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.release()
    
    def start_stream(self):
        self.stream = self.py_audio.open(format= pyaudio.paInt16,
                                         channels = 1,
                                         rate = self.rate,
                                         frames_per_buffer = \
                                         self.frames_per_buffer,
                                         input = True)
                                             
    def stop_stream(self):
        self.stream.stop_stream()
        self.stream.close()
        
    def get_frequency(self, stream_data):
        past_mean = False
        f = 0
        for data in stream_data:
            if  data >= np.mean(stream_data) and past_mean== False:
                past_mean = True
                f=f+1
            elif data <= np.mean(stream_data):
                past_mean = False
        return f / (len(stream_data) / self.rate)
    
    def measure(self):
        data = list()
        for i in range(0, int(self.rate/ self.frames_per_buffer)):
            result = 1 / self.get_frequency(
                         np.frombuffer(
                         self.stream.read(1024), 
                         dtype=np.int16)
                         ) / self.resistance * 100000000
            result = result - self.cap_reference if self.cap_reference else\
                result
            data.append(result)
            
        if self.cap_reference:
            return np.mean(data)
        else:
            self.cap_reference = np.mean(data)
            
    def release(self):
        self.stream.stop_stream()
        self.stream.close()
        self.py_audio.terminate()
        

class CapacitanceUI(tk.LabelFrame):
    
    UPDATE_INTERVAL = 2000
    CALIBRATION = 50
    
    def __init__(self, parent, capacitance_ne555, width, height):
        tk.LabelFrame.__init__(self, parent, text = "CAPACITANCE", 
            relief = "solid")
        self.capacitance = capacitance_ne555
        self.width = width
        self.height = height
        self.parent = parent
        self.calibration = True
        self.display_conf = {"cap" : (
                             self.width / 2, 
                             self.height / 2, 
                             "{0:2.2f} pf",
                             "system 18 bold", 
                             "blue",
                             "cap"),
                             "info" :(
                             self.width / 2, 
                             self.height / 2,
                             "{0}",
                             "system 18 bold",
                             "magenta",
                             "info")}
        self.display = tk.Canvas(self, width = width, height = height,
            bg="cyan")
        self.display.pack(padx = 5, pady = 5)
        self.update_cap_display(0, "cap")
        self.start_button = tk.Button(self, text="START", width = 7,
            command = self.measure)
        self.start_button.pack(side = tk.LEFT, padx = 30)
        self.calibrate_button = tk.Button(self, text = "CALIBRATE", width = 7,
            command = partial(self.measure, True))
        self.calibrate_button.pack(side = tk.RIGHT, padx = 30)
        self.measure(True)
            
    def update_cap_display(self, text, tag):
        width, height, text_conf, font, color, tag = self.display_conf[tag]
        self.display.delete(tag)
        self.display.create_text(width, height, text = text_conf.format(text), 
            font = font, fill = color,tag = tag)
            
    def measure(self, calibrate = False):
        self.display.delete("all")
        self.update_cap_display("", "info")
        self.capacitance.start_stream()
        if calibrate:
            self.capacitance.cap_reference = None
        frequency = self.capacitance.measure()
        display_text = ["CALIBATRED", "info"] if calibrate else\
            [frequency, "cap"]
        self.update_cap_display(display_text[0], display_text[1])
    
    def release(self):
        self.parent.destroy()
        
def main():
    root = tk.Tk()
    root.title("CAPACITANCE")
    with Capacitance_NE555(RESISTANCE) as capacitance_ne555:
        capacitance_ui = CapacitanceUI(root, capacitance_ne555, WIDTH, HEIGHT)
        capacitance_ui.pack(expand=tk.YES, padx=5, pady=5)
        root.protocol("WM_DELETE_WINDOW",capacitance_ui.release)
        root.mainloop()
    
if __name__ == '__main__':
    main()
Gruß Frank
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo,

noch Fehler gefunden - Stream nach dem Messen nicht gestoppt.

Code: Alles auswählen

#/usr/bin/env python
# -*- coding: utf-8

import tkinter as tk
import numpy as np
from functools import partial
import pyaudio

WIDTH = 270
HEIGHT = 100

RA = 1 # kOhm
RB = 5 # kOhm
RESISTANCE = (RA + RB * 2) * 0.69


class Capacitance_NE555(object):
    def __init__(self, 
                 resistance, 
                 rate = 44100,
                 frames_per_buffer = 1024):
        self.py_audio = pyaudio.PyAudio()
        self.resistance = resistance
        self.rate = rate
        self.frames_per_buffer = frames_per_buffer
        self.cap_reference = None
        
    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.release()
    
    def start_stream(self):
        self.stream = self.py_audio.open(format= pyaudio.paInt16,
                                         channels = 1,
                                         rate = self.rate,
                                         frames_per_buffer = \
                                         self.frames_per_buffer,
                                         input = True)
                                             
    def stop_stream(self):
        self.stream.stop_stream()
        self.stream.close()
        
    def get_frequency(self, stream_data):
        past_mean = False
        f = 0
        for data in stream_data:
            if  data >= np.mean(stream_data) and past_mean== False:
                past_mean = True
                f=f+1
            elif data <= np.mean(stream_data):
                past_mean = False
        return f / (len(stream_data) / self.rate)
    
    def measure(self):
        data = list()
        for i in range(0, int(self.rate/ self.frames_per_buffer)):
            result = 1 / self.get_frequency(
                         np.frombuffer(
                         self.stream.read(1024), 
                         dtype=np.int16)
                         ) / self.resistance * 100000000
            result = result - self.cap_reference if self.cap_reference else\
                result
            data.append(result)
            
        if self.cap_reference:
            return np.mean(data)
        else:
            self.cap_reference = np.mean(data)
            
    def release(self):
        self.stream.stop_stream()
        self.stream.close()
        self.py_audio.terminate()
        

class CapacitanceUI(tk.LabelFrame):
    
    def __init__(self, parent, capacitance_ne555, width, height):
        tk.LabelFrame.__init__(self, parent, text = "CAPACITANCE", 
            relief = "solid")
        self.capacitance = capacitance_ne555
        self.width = width
        self.height = height
        self.parent = parent
        self.display_conf = {"cap" : (
                             self.width / 2, 
                             self.height / 2, 
                             "{0:2.2f} pf",
                             "system 18 bold", 
                             "blue",
                             "cap"),
                             "info" :(
                             self.width / 2, 
                             self.height / 2,
                             "{0}",
                             "system 18 bold",
                             "magenta",
                             "info")}
        self.display = tk.Canvas(self, width = width, height = height,
            bg="cyan")
        self.display.pack(padx = 5, pady = 5)
        self.update_cap_display(0, "cap")
        self.start_button = tk.Button(self, text="START", width = 7,
            command = self.measure)
        self.start_button.pack(side = tk.LEFT, padx = 30)
        self.calibrate_button = tk.Button(self, text = "CALIBRATE", width = 7,
            command = partial(self.measure, True))
        self.calibrate_button.pack(side = tk.RIGHT, padx = 30)
        self.measure(True)
            
    def update_cap_display(self, text, tag):
        width, height, text_conf, font, color, tag = self.display_conf[tag]
        self.display.delete(tag)
        self.display.create_text(width, height, text = text_conf.format(text), 
            font = font, fill = color,tag = tag)
            
    def measure(self, calibrate = False):
        self.display.delete("all")
        self.update_cap_display("", "info")
        self.capacitance.start_stream()
        if calibrate:
            self.capacitance.cap_reference = None
        frequency = self.capacitance.measure()
        display_text = ["CALIBRATED", "info"] if calibrate else\
            [frequency, "cap"]
        self.update_cap_display(display_text[0], display_text[1])
        self.capacitance.stop_stream()
    
    def release(self):
        self.parent.destroy()
        
def main():
    root = tk.Tk()
    root.title("CAPACITANCE")
    with Capacitance_NE555(RESISTANCE) as capacitance_ne555:
        capacitance_ui = CapacitanceUI(root, capacitance_ne555, WIDTH, HEIGHT)
        capacitance_ui.pack(expand=tk.YES, padx=5, pady=5)
        root.protocol("WM_DELETE_WINDOW",capacitance_ui.release)
        root.mainloop()
    
if __name__ == '__main__':
    main()
Gruß Frank
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo,
Zeile 59 kann auch in --> "for i in range(0, int(self.rate / self.frames_per_buffer * 0.5)):" geändert werden. Die Verkürzung hat bei meinen Versuchen keinen Unterschied erzeugt.

Gruß Frank
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo,
jetzt mit Frequenzanzeige.

Code: Alles auswählen

#/usr/bin/env python
# -*- coding: utf-8

import tkinter as tk
import numpy as np
from functools import partial
import pyaudio

WIDTH = 270
HEIGHT = 100

RA = 1 # kOhm
RB = 5 # kOhm
RESISTANCE = (RA + RB * 2) * 0.69


class Capacitance_NE555(object):
    def __init__(self, 
                 resistance, 
                 rate = 44100,
                 frames_per_buffer = 1024):
        self.py_audio = pyaudio.PyAudio()
        self.resistance = resistance
        self.rate = rate
        self.frames_per_buffer = frames_per_buffer
        self.cap_reference = None
        self.ref_frequency = None
        self.measure_frequency = None
        
    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.release()
    
    def start_stream(self):
        self.stream = self.py_audio.open(format= pyaudio.paInt16,
                                         channels = 1,
                                         rate = self.rate,
                                         frames_per_buffer = \
                                         self.frames_per_buffer,
                                         input = True)
                                             
    def stop_stream(self):
        self.stream.stop_stream()
        self.stream.close()
        
    def get_frequency(self, stream_data):
        past_mean = False
        f = 0
        for data in stream_data:
            if  data >= np.mean(stream_data) and past_mean== False:
                past_mean = True
                f=f+1
            elif data <= np.mean(stream_data):
                past_mean = False
        return f / (len(stream_data) / self.rate)
    
    def measure(self):
        frequencyies = list()
        for i in range(0, int(self.rate / self.frames_per_buffer * 0.5)):
            frequency  = self.get_frequency(
                                     np.frombuffer(
                                     self.stream.read(self.frames_per_buffer), 
                                     dtype=np.int16)) 
            frequencyies.append(frequency)
        if self.ref_capacity:
            self.measure_frequency = np.mean(frequencyies)
            return 1 / self.measure_frequency / self.resistance * 100000000 \
                - self.ref_capacity , self.measure_frequency 
        else:
            self.ref_frequency = np.mean(frequencyies)
            self.ref_capacity = 1 / self.ref_frequency / self.resistance \
                * 100000000
            return None, self.ref_frequency 
            
    def release(self):
        self.stream.stop_stream()
        self.stream.close()
        self.py_audio.terminate()
        

class CapacitanceUI(tk.LabelFrame):
    def __init__(self, parent, capacitance_ne555, width, height):
        tk.LabelFrame.__init__(self, parent, text = "CAPACITANCE", 
            relief = "solid")
        self.capacitance = capacitance_ne555
        self.width = width
        self.height = height
        self.parent = parent
        self.display_conf = {"cap" : (
                             self.width / 2, 
                             self.height / 2, 
                             "{0:2.2f} pf",
                             "system 18 bold", 
                             "blue",
                             "cap"),
                             "freq" : (
                             self.width / 2, 
                             20,
                             "{0:2.2f} Hz",
                             "system 10 bold", 
                             "green",
                             "freq"),
                             "info" :(
                             self.width / 2, 
                             self.height / 2,
                             "{0}",
                             "system 18 bold",
                             "magenta",
                             "info")}
        self.display = tk.Canvas(self, width = width, height = height,
            bg="cyan")
        self.display.pack(padx = 5, pady = 5)
        self.update_cap_display(0, "cap")
        self.start_button = tk.Button(self, text="START", width = 7,
            command = self.measure)
        self.start_button.pack(side = tk.LEFT, padx = 30, pady = 5)
        self.calibrate_button = tk.Button(self, text = "CALIBRATE", width = 7,
            command = partial(self.measure, True))
        self.calibrate_button.pack(side = tk.RIGHT, padx = 30, pady = 5)
        self.measure(True)
            
    def update_cap_display(self, text, tag):
        width, height, text_conf, font, color, tag = self.display_conf[tag]
        self.display.delete(tag)
        self.display.create_text(width, height, text = text_conf.format(text), 
            font = font, fill = color,tag = tag)
            
    def measure(self, calibrate = False):
        self.display.delete("all")
        self.capacitance.start_stream()
        if calibrate:
            self.capacitance.ref_capacity = None
        capacity, frequency = self.capacitance.measure()
        display_text = ["CALIBRATED", "info"] if calibrate else\
            [capacity, "cap"]
        self.update_cap_display(display_text[0], display_text[1])
        self.update_cap_display(frequency, "freq")
        self.capacitance.stop_stream()
    
    def release(self):
        self.parent.destroy()
        
def main():
    root = tk.Tk()
    root.title("CAPACITANCE")
    with Capacitance_NE555(RESISTANCE) as capacitance_ne555:
        capacitance_ui = CapacitanceUI(root, capacitance_ne555, WIDTH, HEIGHT)
        capacitance_ui.pack(expand=tk.YES, padx=5, pady=5)
        root.protocol("WM_DELETE_WINDOW",capacitance_ui.release)
        root.mainloop()
    
if __name__ == '__main__':
    main()
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo,

Jetzt läuft der stream während der Messung weiter und es kann so auch der Stellbereich bei Drehkondensatoren beobachtet werden. Zu der "callback mode" habe ich nicht wirklich brauchbare Beispiele gefunden und ich hoffe meine Lösung ist ok.

Code: Alles auswählen

#/usr/bin/env python
# -*- coding: utf-8

import tkinter as tk
import numpy as np
import pyaudio

WIDTH = 270
HEIGHT = 150

RA = 1 # kOhm
RB = 5 # kOhm
RESISTANCE = (RA + RB * 2) * 0.69


class Capacitance_NE555(object):
    def __init__(self, 
                 resistance, 
                 rate = 44100,
                 frames_per_buffer = 1024):
        self.py_audio = pyaudio.PyAudio()
        self.stream = None
        self.stream_data = None
        self.resistance = resistance
        self.rate = rate
        self.frames_per_buffer = frames_per_buffer
        self.ref_capacity = None
        self.ref_frequency = None
        self.measure_frequency = None
        
    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.release()
    
    def start_stream(self):
        self.stream = self.py_audio.open(format= pyaudio.paInt16,
                                         channels = 1,
                                         rate = self.rate,
                                         frames_per_buffer = \
                                         self.frames_per_buffer,
                                         input = True,
                                         stream_callback = self.callback)
                                             
    def stop_stream(self):
        if self.stream:
            self.stream.stop_stream()
            self.stream.close()
            self.stream = None
        
    def callback(self, in_data, frame_count, time_info, status):
        self.stream_data = in_data
        return (in_data, pyaudio.paContinue)
        
    def get_frequency(self, stream_data):
        past_mean = False
        f = 0
        for data in stream_data:
            if  data >= np.mean(stream_data) and past_mean== False:
                past_mean = True
                f=f+1
            elif data <= np.mean(stream_data):
                past_mean = False
        return f / (len(stream_data) / self.rate)
    
    def measure(self):
        if self.stream_data:
            frequencyies = list()
            for i in range(0, int(self.rate / self.frames_per_buffer * 0.1)):
                frequency  = self.get_frequency(np.frombuffer(
                                                self.stream_data, 
                                                dtype=np.int16)) 
                frequencyies.append(frequency)
            if self.ref_capacity:
                self.measure_frequency = np.mean(frequencyies)
                return 1 / self.measure_frequency / self.resistance * 100000000 \
                    - self.ref_capacity , self.measure_frequency 
            else:
                self.ref_frequency = np.mean(frequencyies)
                self.ref_capacity = 1 / self.ref_frequency / self.resistance \
                    * 100000000
                return  None, self.ref_frequency
            
    def release(self):
        if self.stream:
            self.stop_stream()
        self.py_audio.terminate()
        

class CapacitanceUI(tk.LabelFrame):
    def __init__(self, parent, capacitance_ne555, width, height):
        tk.LabelFrame.__init__(self, parent, text = "CAPACITANCE", 
            relief = "solid")
        self.capacitance = capacitance_ne555
        self.width = width
        self.height = height
        self.parent = parent
        self.after_id = None
        self.display_conf = {"cap" : (
                             self.width / 2, 
                             self.height / 2, 
                             "{0:2.2f} pf",
                             "system 27 bold", 
                             "blue",
                             "cap"),
                             "freq" : (
                             self.width / 2, 
                             20,
                             "{0:2.2f} Hz",
                             "system 15 bold", 
                             "green",
                             "freq"),
                             "info" :(
                             self.width / 2, 
                             self.height / 2,
                             "{0}",
                             "system 18 bold",
                             "magenta",
                             "info")}
        self.display = tk.Canvas(self, width = width, height = height,
            bg="cyan")
        self.display.pack(padx = 5, pady = 5)
        self.update_cap_display(0, "cap")
        self.start_button = tk.Button(self, text="START", width = 7,
            command = self.start_stop_measure)
        self.start_button.pack(side = tk.LEFT, padx = 30, pady = 5)
        self.calibrate_button = tk.Button(self, text = "CALIBRATE", width = 7,
            command = self.calibrate)
        self.calibrate_button.pack(side = tk.RIGHT, padx = 30, pady = 5)
        self.calibrate()
        
    def calibrate(self):
        self.start_button.config(state = "disabled")
        self.capacitance.ref_capacity = None
        self.start_stop_measure()
        self.after_id = self.after(100, self.start_stop_measure)
       
    def update_cap_display(self, text, tag):
        width, height, text_conf, font, color, tag = self.display_conf[tag]
        self.display.delete(tag)
        self.display.create_text(width, height, text = text_conf.format(text), 
            font = font, fill = color,tag = tag)
    
    def start_stop_measure(self):
        if self.after_id:
            self.after_cancel(self.after_id)
            self.after_id = None
            self.start_button.config(state = "normal")
            self.calibrate_button.config(state = "normal")
            self.start_button.config(text = "START")
            self.capacitance.stop_stream()
        else:
            self.calibrate_button.config(state = "disabled")
            self.start_button.config(text = "STOP")
            self.capacitance.start_stream()
            self.measure()

    def measure(self):
        if self.after_id:
            self.display.delete("all")
            if self.capacitance.measure():
                capacity, frequency = self.capacitance.measure()
                self.update_cap_display(capacity, "cap")
                self.update_cap_display(frequency, "freq")
        self.after_id = self.after(100, self.measure)
            
    def release(self):
        if self.after_id:
            self.after_cancel(self.after_id)
        self.parent.destroy()
        
def main():
    root = tk.Tk()
    root.title("CAPACITANCE")
    with Capacitance_NE555(RESISTANCE) as capacitance_ne555:
        capacitance_ui = CapacitanceUI(root, capacitance_ne555, WIDTH, HEIGHT)
        capacitance_ui.pack(expand=tk.YES, padx=5, pady=5)
        root.protocol("WM_DELETE_WINDOW",capacitance_ui.release)
        root.mainloop()
    
if __name__ == '__main__':
    main()
Gruß Frank
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo,

noch Fehler behoben.

Code: Alles auswählen

#/usr/bin/env python
# -*- coding: utf-8

import tkinter as tk
import numpy as np
import pyaudio

WIDTH = 270
HEIGHT = 150

RA = 1 # kOhm
RB = 5 # kOhm
RESISTANCE = (RA + RB * 2) * 0.69


class Capacitance_NE555(object):
    def __init__(self, 
                 resistance, 
                 rate = 44100,
                 frames_per_buffer = 1024):
        self.py_audio = pyaudio.PyAudio()
        self.stream = None
        self.stream_data = None
        self.resistance = resistance
        self.rate = rate
        self.frames_per_buffer = frames_per_buffer
        self.ref_capacity = None
        
    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.release()
    
    def start_stream(self):
        self.stream = self.py_audio.open(format= pyaudio.paInt16,
                                         channels = 1,
                                         rate = self.rate,
                                         frames_per_buffer = \
                                         self.frames_per_buffer,
                                         input = True,
                                         stream_callback = self.callback)
                                             
    def stop_stream(self):
        if self.stream:
            self.stream.stop_stream()
            self.stream.close()
            self.stream = None
        
    def callback(self, in_data, frame_count, time_info, status):
        self.stream_data = in_data
        return (in_data, pyaudio.paContinue)
        
    def get_frequency(self, stream_data):
        past_mean = False
        f = 0
        for data in stream_data:
            if  data >= np.mean(stream_data) and past_mean== False:
                past_mean = True
                f=f+1
            elif data <= np.mean(stream_data):
                past_mean = False
        return f / (len(stream_data) / self.rate)
    
    def measure(self):
        if self.stream_data:
            frequencyies = list()
            for i in range(0, int(self.rate / self.frames_per_buffer * 0.1)):
                frequency  = self.get_frequency(np.frombuffer(
                                                self.stream_data, 
                                                dtype=np.int16)) 
                frequencyies.append(frequency)
            if self.ref_capacity:
                return 1 / np.mean(frequencyies) / self.resistance * 100000000 \
                    - self.ref_capacity , np.mean(frequencyies) 
            else:
                ref_frequency = np.mean(frequencyies)
                self.ref_capacity = 1 / ref_frequency / self.resistance \
                    * 100000000
                return  0, ref_frequency
            
    def release(self):
        if self.stream:
            self.stop_stream()
        self.py_audio.terminate()
        

class CapacitanceUI(tk.LabelFrame):
    def __init__(self, parent, capacitance_ne555, width, height):
        tk.LabelFrame.__init__(self, parent, text = "CAPACITANCE", 
            relief = "solid")
        self.capacitance = capacitance_ne555
        self.width = width
        self.height = height
        self.parent = parent
        self.after_id = None
        self.display_conf = {"cap" : (
                             self.width / 2, 
                             self.height / 2, 
                             "{0:2.2f} pf",
                             "system 27 bold", 
                             "blue",
                             "cap"),
                             "freq" : (
                             self.width / 2, 
                             20,
                             "{0:2.2f} Hz",
                             "system 15 bold", 
                             "green",
                             "freq"),
                             "info" :(
                             self.width / 2, 
                             self.height / 2,
                             "{0}",
                             "system 18 bold",
                             "magenta",
                             "info")}
        self.display = tk.Canvas(self, width = width, height = height,
            bg="cyan")
        self.display.pack(padx = 5, pady = 5)
        self.update_cap_display(0, "cap")
        self.start_button = tk.Button(self, text="START", width = 7,
            command = self.start_stop_measure)
        self.start_button.pack(side = tk.LEFT, padx = 30, pady = 5)
        self.calibrate_button = tk.Button(self, text = "CALIBRATE", width = 7,
            command = self.calibrate)
        self.calibrate_button.pack(side = tk.RIGHT, padx = 30, pady = 5)
        self.calibrate()
        
    def calibrate(self):
        self.start_button.config(state = "disabled")
        self.capacitance.ref_capacity = None
        self.start_stop_measure()
        self.after_id = self.after(100, self.start_stop_measure)
       
    def update_cap_display(self, text, tag):
        width, height, text_conf, font, color, tag = self.display_conf[tag]
        self.display.delete(tag)
        self.display.create_text(width, height, text = text_conf.format(text), 
            font = font, fill = color,tag = tag)
    
    def start_stop_measure(self):
        if self.after_id:
            self.after_cancel(self.after_id)
            self.after_id = None
            self.start_button.config(state = "normal")
            self.calibrate_button.config(state = "normal")
            self.start_button.config(text = "START")
            self.capacitance.stop_stream()
        else:
            self.calibrate_button.config(state = "disabled")
            self.start_button.config(text = "STOP")
            self.capacitance.start_stream()
            self.measure()

    def measure(self):
        if self.after_id:
            self.display.delete("all")
            capacity, frequency = self.capacitance.measure()
            self.update_cap_display(capacity, "cap")
            self.update_cap_display(frequency, "freq")
        self.after_id = self.after(100, self.measure)
            
    def release(self):
        if self.after_id:
            self.after_cancel(self.after_id)
        self.parent.destroy()
        
def main():
    root = tk.Tk()
    root.title("CAPACITANCE")
    with Capacitance_NE555(RESISTANCE) as capacitance_ne555:
        capacitance_ui = CapacitanceUI(root, capacitance_ne555, WIDTH, HEIGHT)
        capacitance_ui.pack(expand=tk.YES, padx=5, pady=5)
        root.protocol("WM_DELETE_WINDOW",capacitance_ui.release)
        root.mainloop()
    
if __name__ == '__main__':
    main()
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo,

noch eine grafische Anzeige für das gemessene Signal reingebastelt.

Code: Alles auswählen

#/usr/bin/env python
# -*- coding: utf-8

import tkinter as tk
import numpy as np
import pyaudio

WIDTH = 300
HEIGHT = 170

RA = 1 # kOhm
RB = 5 # kOhm
RESISTANCE = (RA + RB * 2) * 0.69


class Capacitance_NE555(object):
    def __init__(self, 
                 resistance, 
                 rate = 44100,
                 frames_per_buffer = 1024):
        self.py_audio = pyaudio.PyAudio()
        self.stream = None
        self.stream_data = None
        self.resistance = resistance
        self.rate = rate
        self.frames_per_buffer = frames_per_buffer
        self.ref_capacity = None
        
    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.release()
    
    def start_stream(self):
        self.stream = self.py_audio.open(format= pyaudio.paInt16,
                                         channels = 1,
                                         rate = self.rate,
                                         frames_per_buffer = \
                                         self.frames_per_buffer,
                                         input = True,
                                         stream_callback = self.callback)
                                             
    def stop_stream(self):
        if self.stream:
            self.stream.stop_stream()
            self.stream.close()
            self.stream = None
        
    def callback(self, in_data, frame_count, time_info, status):
        self.stream_data = in_data
        return (in_data, pyaudio.paContinue)
        
    def calibrate(self):
        self.ref_capacity = None
        
    def get_frequency(self, stream_data):
        past_mean = False
        f = 0
        for data in stream_data:
            if  data >= np.mean(stream_data) and past_mean== False:
                past_mean = True
                f=f+1
            elif data <= np.mean(stream_data):
                past_mean = False
        return f / (len(stream_data) / self.rate)
    
    def measure(self):
        if self.stream_data:
            frequencyies = list()
            stream_data = list()
            for i in range(0, int(self.rate / self.frames_per_buffer * 0.1)):
                np_data = np.frombuffer(self.stream_data, 
                                        dtype = np.int16)
                frequency = self.get_frequency(np_data)
                stream_data.append(np_data)
                frequencyies.append(frequency)
            if self.ref_capacity:
                return 1 / np.mean(frequencyies) / self.resistance * 100000000 \
                    - self.ref_capacity , np.mean(frequencyies), stream_data
            else:
                ref_frequency = np.mean(frequencyies)
                self.ref_capacity = 1 / ref_frequency / self.resistance \
                    * 100000000
                return  0, ref_frequency, None
            
    def release(self):
        if self.stream:
            self.stop_stream()
        self.py_audio.terminate()
        

class CapacitanceUI(tk.LabelFrame):
    def __init__(self, parent, capacitance_ne555, width, height):
        tk.LabelFrame.__init__(self, parent, text = "CAPACITANCE", 
            relief = "solid")
        self.capacitance = capacitance_ne555
        self.width = width
        self.height = height
        self.parent = parent
        self.after_id = None
        self.display_conf = {"cap" : (
                             self.width / 2, 
                             self.height / 2 - 10, 
                             "{0:2.2f} pf",
                             "system 27 bold", 
                             "blue",
                             "cap"),
                             "freq" : (
                             self.width / 2, 
                             20,
                             "{0:2.2f} Hz",
                             "system 15 bold", 
                             "green",
                             "freq"),
                             "info" :(
                             self.width / 2, 
                             self.height / 2,
                             "{0}",
                             "system 18 bold",
                             "magenta",
                             "info")}
        self.display = tk.Canvas(self, width = width, height = height,
            bg="cyan")
        self.display.pack(padx = 5, pady = 5)
        self.update_cap_display(0, "cap")
        self.start_button = tk.Button(self, text="START", width = 7,
            command = self.start_stop_measure)
        self.start_button.pack(side = tk.LEFT, padx = 30, pady = 5)
        self.calibrate_button = tk.Button(self, text = "CALIBRATE", width = 7,
            command = self.calibrate)
        self.calibrate_button.pack(side = tk.RIGHT, padx = 30, pady = 5)
        self.calibrate()
        
    def calibrate(self):
        for x in range(self.width):
            self.display.delete("freq_line{0}".format(x))
        self.start_button.config(state = "disabled")
        self.capacitance.calibrate()
        self.start_stop_measure()
        self.after_id = self.after(100, self.start_stop_measure)
       
    def update_cap_display(self, text, tag):
        width, height, text_conf, font, color, tag = self.display_conf[tag]
        self.display.delete(tag)
        self.display.create_text(width, height, text = text_conf.format(text), 
            font = font, fill = color,tag = tag)
            
    def update_signal_line(self, points, tag):
        self.display.delete(tag)
        x, y, x_2, y_2 = points
        self.display.create_line(x, y, x_2, y_2, tag = tag )
    
    def start_stop_measure(self):
        if self.after_id:
            self.after_cancel(self.after_id)
            self.after_id = None
            self.start_button.config(state = "normal")
            self.calibrate_button.config(state = "normal")
            self.start_button.config(text = "START")
            self.capacitance.stop_stream()
        else:
            self.calibrate_button.config(state = "disabled")
            self.start_button.config(text = "STOP")
            self.capacitance.start_stream()
            self.measure()

    def measure(self):
        if self.after_id:
            capacity, frequency, np_data = self.capacitance.measure()
            self.update_cap_display(capacity, "cap")
            self.update_cap_display(frequency, "freq")
            start_x, start_y = 0, 0
            self.update_signal_line((0, 
                                    self.height - 30, 
                                    self.width, 
                                    self.height - 30),
                                    "zero_line")
            if np_data:
                for data in np_data[-1][0: self.width]:
                    data = data / self.height
                    self.update_signal_line((start_x, 
                                             start_y + self.height - 30, 
                                             start_x + 1, 
                                             data + self.height - 30),
                                             "freq_line{0}".format(start_x))
                    start_x += 1
                    start_y = data
                    
                    
        self.after_id = self.after(100, self.measure)
            
    def release(self):
        if self.after_id:
            self.after_cancel(self.after_id)
        self.parent.destroy()
        
def main():
    root = tk.Tk()
    root.title("CAPACITANCE")
    with Capacitance_NE555(RESISTANCE) as capacitance_ne555:
        capacitance_ui = CapacitanceUI(root, capacitance_ne555, WIDTH, HEIGHT)
        capacitance_ui.pack(expand=tk.YES, padx=5, pady=5)
        root.protocol("WM_DELETE_WINDOW",capacitance_ui.release)
        root.mainloop()
    
if __name__ == '__main__':
    main()
Gruß Frank
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn ich so einen Code sehe, kann ich nicht still bleiben:

Code: Alles auswählen

    def get_frequency(self, stream_data):
        past_mean = False
        f = 0
        for data in stream_data:
            if  data >= np.mean(stream_data) and past_mean== False:
                past_mean = True
                f=f+1
            elif data <= np.mean(stream_data):
                past_mean = False
        return f / (len(stream_data) / self.rate)
Du rechnest für jeden Datenpunkt zwei mal den Mittelwert über alle Datenpunkte aus. So viel Rechenzeitverschwendung kommt mir selten unter.

Code: Alles auswählen

    def get_frequency(self, stream_data):
        past_mean = False
        f = 0
        stream_mean = np.mean(stream_data)
        for data in stream_data:
            if  data >= stream_mean and past_mean == False:
                past_mean = True
                f += 1
            elif data <= stream_mean:
                past_mean = False
        return f / (len(stream_data) / self.rate)
Und das ganze kann man natürlich mit numpy noch vektorisieren:

Code: Alles auswählen

    def get_frequency(self, stream_data):
        stream_mean = np.mean(stream_data)
        past_mean = (stream_data > stream_mean).astype(int)
        f = (np.diff(past_mean) > 0).sum()
        return f / (len(stream_data) / self.rate)
In der nächsten Methode rechnest Du auch vieles doppelt. Die for-Schleife und damit die ganze Funktion machen auf den ersten Blick nichts sinnvolles:

Code: Alles auswählen

    def measure(self):
        if self.stream_data:
            frequencyies = list()
            stream_data = list()
            for i in range(int(self.rate / self.frames_per_buffer * 0.1)):
                # TODO: get new stream_data from anywhere
                np_data = np.frombuffer(self.stream_data, dtype=np.int16)
                frequency = self.get_frequency(np_data)
                stream_data.append(np_data)
                frequencyies.append(frequency)
            ref_frequency = np.mean(frequencyies)
            capacity = 1 / ref_frequency / self.resistance * 100000000
            if not self.ref_capacity:
                self.ref_capacity = capacity
                stream_data = None
            return capacity - self.ref_capacity, ref_frequency, stream_data
        # TODO: what happens in this case?
        raise RuntimeError("no stream data")
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Danke Sirius3,

- die Verschwendung der Rechenzeit war mir nicht bewusst bei "np.mean ()"
- das Vektorisieren sieht schön aus, doch die Messergebnisse und die grafische Anzeige stimmt nicht mehr - habe das Signal mit meiner Version und
Audacity verglichen. Beide sehen mal gleich aus !
- Die Daten aus dem "Inputstream" kommen kontinuierlich aus:

Code: Alles auswählen

    def callback(self, in_data, frame_count, time_info, status):
        self.stream_data = in_data
        return (in_data, pyaudio.paContinue)
- mit "if self.stream_data:" warte ich nur bis der stream auch wiklich läuft.

Gruß Frank
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

Die kommen eben nicht kontinuierlich, weil Du die beiden Funktionen nicht synchronisierst. Alles ist sehr fragil und nicht robust. Benutzte Queues, um die Daten vom Callback in die anderen Funktionen zu übertragen.
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo Sirius3,

du wirst recht haben, doch ich habe natürlich mit meinem Halbwissen und meinen amateurhaften Schätzgeräten die Funktion überprüft. Die Werte sind recht genau und auch die Überprüfung mit einem Signalgenerator (Handy) hat immer eine aktuelle Änderung des grafischen Signals (bis 20Khz) zur Folge. Es wird auch immer die gerade gewählte Wellenform angezeigt (Sinus, Square, Saw). Die Änderung der Kondensatoren im laufenden Betrieb ergibt auch eine sofortige Werteänderung in der Anzeige. So müssten der Stream doch sehr kontinuierlich und aktuell sein ?

Gruß
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Es liegt in der Natur solcher Probleme, dass die oft nicht schwarz-weiss sind. Dein jetziger Code arbeitet asynchron vor sich hin. Das fuehrt dazu, dass er im Zweifel den gleichen Buffer mehrfach bearbeitet, oder mal einen ueberspringt. Das kann man natuerlich unterschiedlich bewerten, aber erstmal ist das ein Fakt, und fuehrt zu glitches.

Wenn du das besser machen *willst*, dann kannst du eben eine Queue benutzen, um die Frames oder besser noch das Ergebnis von measure zu buffern, und im after-Handler dann eben ggf. mehrere Werte nacheinander zu updaten, oder mal auszusetzen.
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Danke __deets__,

Ich möchte es natürlich besser machen - falls es meine Fähigkeiten zulassen. Ich arbeite mit Menschen und da ist die Welt nur in allen Farben schön - auch mit allen Problemen, die mit dieser Vielfältigkeit einhergehen.

Gruß
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ausser einer eher unterhaendigen Unterstellung, dass Leute, die nicht mit Menschen arbeiten, eine eher Einfaeltige und wenig bunte Welt um sich herum haben, kann ich mit diesem Satz nichts anfangen. Ein Bezug zu diesem Problem jedenfalls wird mir nicht ersichlich. Aber ich arbeite auch nicht mit Menschen, sondern nur mit Computern.
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo __deets__,

war keine Anspielung, sondern nur ein Vergleich zu "schwarz-weiss". Wollte dir nicht auf die Füße treten !

Gruß
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo,

ein Versuch ohne Messung - nur mit Ausgabe der Streamdaten.

Code: Alles auswählen

#/usr/bin/env python
# -*- coding: utf-8

import tkinter as tk
import numpy as np
import pyaudio
import time
from threading import Thread, Event
from functools import partial
import queue

WIDTH = 256
HEIGHT = 200
MEASURE_TIME = 0.025

class ReadLineInAudioThreadClient(object):
    def __init__(self, queue):
        self.queue = queue
        self.run_event = None
        
    def stop(self):
        self.run_event.set()
        
    def start(self, measure_time):
        self.run_event = Event()
        self.thread = Thread(target=partial (self.worker_thread, 
                                             measure_time))
        self.thread.daemon = True
        self.thread.start()
            
    def worker_thread(self, measure_time):
        with ReadLineInAudio(measure_time) \
            as read_line_in_audio:
                read_line_in_audio.start_stream()
                while not self.run_event.is_set():
                    self.queue.put(read_line_in_audio.read_data())
                    self.run_event.wait(measure_time)


class ReadLineInAudio(object):
    def __init__(self, 
                 measure_time,
                 channels = 1,
                 rate = 44100,
                 frames_per_buffer = 256):
        self.py_audio = pyaudio.PyAudio()
        self.rate = rate
        self.frames_per_buffer = frames_per_buffer
        self.measure_time = measure_time
        self.channels = channels
        
    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.release()
    
    def start_stream(self):
        self.stream = self.py_audio.open(format= pyaudio.paInt16,
                                         channels = self.channels,
                                         rate = self.rate,
                                         frames_per_buffer = \
                                            self.frames_per_buffer,
                                         input = True,
                                         stream_callback = self.callback)
        time.sleep(0.1)
        
    def callback(self, in_data, frame_count, time_info, status):
        self.stream_data = in_data
        return (in_data, pyaudio.paContinue)
            
    def read_data(self):
        return np.frombuffer(self.stream_data, 
                             dtype = np.int16)
                             
    def release(self):
        try:
            self.stream.stop_stream()
            self.stream.close()
        except AttributeError as er:
            print(er)
        self.py_audio.terminate()
        

class CapacitanceUI(tk.LabelFrame):
    def __init__(self, 
                 parent, 
                 width, 
                 height, 
                 measure_time):
        tk.LabelFrame.__init__(self, parent, text = "LINE_IN", 
            relief = "solid")
        self.queue = queue.Queue()
        self.read_line_in_audio_thread_client = \
            ReadLineInAudioThreadClient(self.queue)
        self.measure_time = measure_time
        self.width = width
        self.height = height
        self.parent = parent
        self.after_id = None
        self.display = tk.Canvas(self, width = width, height = height,
            bg = "black")
        self.display.pack(padx = 5, pady = 5)
        self.start_button = tk.Button(self, text = "START", width = 7,
            command = self.start_measure)
        self.start_button.pack(side = tk.LEFT, padx = 30, pady = 5)
        self.stop_button = tk.Button(self, text = "STOP", width = 7,
            command = self.stop_measure)
        self.stop_button.pack(side = tk.RIGHT, padx = 30, pady = 5)
        self.stop_button.config(state = "disabled")
        
    def start_measure(self):
        self.start_button.config(state = "disabled")
        self.stop_button.config(state = "normal")
        self.read_line_in_audio_thread_client.start(self.measure_time)
        self.measure()
        
    def stop_measure(self):
        self.after_cancel(self.after_id)
        self.read_line_in_audio_thread_client.stop()
        self.start_button.config(state = "normal")
        self.stop_button.config(state = "disabled")

    def update_signal_line(self, points, tag):
        self.display.delete(tag)
        self.display.create_line(points, tag = tag, fill = "lightgreen")

    def measure(self):
        if not self.queue.empty():
            while True:
                try:
                    np_data = self.queue.get_nowait()
                    start_x, start_y = 0, 0
                    for data in np_data:
                        self.update_signal_line((start_x, 
                                                 start_y + self.height / 2, 
                                                 start_x + 1, 
                                                 data + self.height / 2),
                                                 "freq_line{0}".format(
                                                 start_x))
                        start_x += 1
                        start_y = data
                        
                except queue.Empty:
                    break
        self.after_id = self.after(int(self.measure_time * 1000), 
            self.measure)
    
    def release(self):
        if self.after_id:
            self.after_cancel(self.after_id)
        self.parent.destroy()
        
def main():
    root = tk.Tk()
    capacitance_ui = CapacitanceUI(root,
                                   WIDTH, 
                                   HEIGHT, 
                                   MEASURE_TIME)
    capacitance_ui.pack(expand=tk.YES, padx=5, pady=5)
    root.protocol("WM_DELETE_WINDOW",capacitance_ui.release)
    root.mainloop()
    
if __name__ == '__main__':
    main()
Gruß Frank
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

`Thread` hat sowohl ein args-Argument als auch ein daemon.
Den Sinn der ReadLineInAudioThreadClient-Klasse verstehe ich nicht, da py_audio doch mit Callbacks arbeitet.
AttributeError ist eher eine Programmierfehler, als dass man es sinnvoll in einem Programm einsetzen kann.

Code: Alles auswählen

class ReadLineInAudio(object):
    def __init__(self,
                 queue, 
                 measure_time,
                 channels = 1,
                 rate = 44100,
                 frames_per_buffer = 256):
        self.py_audio = self.stream = None
        self.queue = queue
        self.rate = rate
        self.frames_per_buffer = frames_per_buffer
        self.measure_time = measure_time
        self.channels = channels
        
    def __enter__(self):
        self.start_stream()
        return self

    def __exit__(self, *args):
        self.release()
    
    def start_stream(self):
        self.py_audio = pyaudio.PyAudio()
        self.stream = self.py_audio.open(format=pyaudio.paInt16,
                                         channels=self.channels,
                                         rate=self.rate,
                                         frames_per_buffer=self.frames_per_buffer,
                                         input=True,
                                         stream_callback=self.callback)
        
    def callback(self, in_data, frame_count, time_info, status):
        self.queue.put(np.frombuffer(in_data, dtype=np.int16))
        return (in_data, pyaudio.paContinue)
                             
    def release(self):
        if self.stream is not None:
            self.stream.stop_stream()
            self.stream.close()
            self.py_audio.terminate()
            self.stream = None
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Danke Sirius3,

das mit der den Callbacks steht auch so in der Doku und so hatte ich es auch eingebaut, damit die GUI nicht einfriert. Deets erwähnte ja Queues und die hatte ich mit einem eigenen Thread verbunden. Da fehlt mir halt Grundverständnis der Thematik ! Der AttributeError entsteht, wenn die GUI ohne gestarteten Stream geschlossen wird. Mit der Exception habe ich diese Fehlermeldung ausgeschlossen. Welche Menge an Daten machen beim Einlesen eigentlich Sinn ?

Gruß Frank
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@kaytec: Der `AttributeError` kann also nur passieren weil in der `__init__()` nicht alle Attribute angelegt werden. Sollten sie aber. Wenn es noch keinen Wert dafür gibt, dann halt mit `None`.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo,

nach einem Durchlauf wird "release()" ausgelöst ?

Code: Alles auswählen

import numpy as np
import pyaudio
import time
from threading import Thread, Event
from functools import partial
import queue

WIDTH = 256
HEIGHT = 200
MEASURE_TIME = 0.025

class ReadLineInAudio(object):
    def __init__(self,
                 queue, 
                 measure_time,
                 channels = 1,
                 rate = 44100,
                 frames_per_buffer = 256):
        self.py_audio = self.stream = None
        self.queue = queue
        self.rate = rate
        self.frames_per_buffer = frames_per_buffer
        self.measure_time = measure_time
        self.channels = channels
        
    def __enter__(self):
        self.start_stream()
        return self

    def __exit__(self, *args):
        self.release()
    
    def start_stream(self):
        self.py_audio = pyaudio.PyAudio()
        self.stream = self.py_audio.open(format=pyaudio.paInt16,
                                         channels=self.channels,
                                         rate=self.rate,
                                         frames_per_buffer=self.frames_per_buffer,
                                         input=True,
                                         stream_callback=self.callback)
        
    def callback(self, in_data, frame_count, time_info, status):
        self.queue.put(np.frombuffer(in_data, dtype=np.int16))
        return (in_data, pyaudio.paContinue)
                             
    def release(self):
        if self.stream is not None:
            self.stream.stop_stream()
            self.stream.close()
            self.py_audio.terminate()
            self.stream = None

class CapacitanceUI(tk.LabelFrame):
    def __init__(self, 
                 parent, 
                 width, 
                 height, 
                 measure_time):
        tk.LabelFrame.__init__(self, parent, text = "LINE_IN", 
            relief = "solid")
        self.measure_time = measure_time
        self.width = width
        self.height = height
        self.parent = parent
        self.after_id = None
        self.last_start_y = 0
        self.queue = queue.Queue()
        self.display = tk.Canvas(self, width = width, height = height,
            bg = "black")
        self.display.pack(padx = 5, pady = 5)
        self.start_button = tk.Button(self, text = "START", width = 7,
            command = self.start_measure)
        self.start_button.pack(side = tk.LEFT, padx = 30, pady = 5)
        self.stop_button = tk.Button(self, text = "STOP", width = 7,
            command = self.stop_measure)
        self.stop_button.pack(side = tk.RIGHT, padx = 30, pady = 5)
        self.stop_button.config(state = "disabled")
        
    def start_measure(self):
        self.start_button.config(state = "disabled")
        self.stop_button.config(state = "normal")
        with ReadLineInAudio(self.queue, self.measure_time) as real_line_in_audio:
            self.measure()
        
    def stop_measure(self):
        self.after_cancel(self.after_id)
        self.stop_button.config(state = "disabled")
        self.start_button.config(state = "normal")
 
    def update_signal_line(self, points, tag):
        self.display.delete(tag)
        self.display.create_line(points, tag = tag, fill = "lightgreen")

    def measure(self):
        if not self.queue.empty():
            while True:
                try:
                    np_data = self.queue.get_nowait()
                    start_x = 0
                    for data in np_data:
                        self.update_signal_line((start_x, 
                                                    self.last_start_y + self.height / 2, 
                                                    start_x + 1, 
                                                     data + self.height / 2),
                                                     "freq_line{0}".format(
                                                     start_x))
                        start_x += 1
                        self.last_start_y = data
                except queue.Empty:
                    break
        self.after_id = self.after(int(self.measure_time * 1000), 
            self.measure)
    
    def release(self):
        if self.after_id:
            self.after_cancel(self.after_id)
        self.parent.destroy()
        
def main():
    root = tk.Tk()
    capacitance_ui = CapacitanceUI(root,
                                   WIDTH, 
                                   HEIGHT, 
                                   MEASURE_TIME)
    capacitance_ui.pack(expand=tk.YES, padx = 5, pady = 5)
    root.protocol("WM_DELETE_WINDOW",capacitance_ui.release)
    root.mainloop()
    
if __name__ == '__main__':
    main()
Gruß Frank
Antworten