tkinter+matplotlib实现示波器效果,动态显示汽车数据

来源:互联网 发布:javascript用什么运行 编辑:程序博客网 时间:2024/04/25 03:35

       最近研究汽车的can数据,想实时显示油门刹车转向灯量的图形,搞了好久,总是不能做到实时,都放弃了,一天看到了一片文章:能实时显示音波数据,而且代码就几十行,于是拿来运行,效果不错。代码放在下面。

# -*- coding: utf-8 -*-
"""
Created on Tue Mar 24 10:48:07 2015
@author: Administrator
"""


import pyaudio
import Tkinter as tk
import wave
import threading
import Queue as queue
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import matplotlib.lines as line
import numpy as np
from scipy import fftpack
from scipy import signal


CHUNK = 102400
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "output.wav"
data =[]
Recording=False
FFT_LEN = 128
frames=[]
counter=1


#GUI
class Application(tk.Frame):
    def __init__(self,master=None):
        tk.Frame.__init__(self,master)
        self.grid()
        self.creatWidgets()


    def creatWidgets(self):
        self.quitButton=tk.Button(self,text='quit',command=root.destroy)
        self.quitButton.grid(column=1,row=3)




#Matplotlib
fig = plt.figure()
rt_ax = plt.subplot(212,xlim=(0,CHUNK), ylim=(-10000,10000))
fft_ax = plt.subplot(211)
fft_ax.set_yscale('log')
fft_ax.set_xlim(0,CHUNK/2 + 1)
fft_ax.set_ylim(1,100000000)
rt_ax.set_title("Real Time")
fft_ax.set_title("FFT Time")
rt_line = line.Line2D([],[])
fft_line = line.Line2D([],[])


rt_data=np.arange(0,CHUNK,1)
fft_data=np.arange(0,CHUNK/2 + 1,1)
rt_x_data=np.arange(0,CHUNK,1)
fft_x_data=np.arange(0,CHUNK/2 + 1,1)


def plot_init():
    rt_ax.add_line(rt_line)
    fft_ax.add_line(fft_line)
    return fft_line,rt_line,
    
def plot_update(i):
    global rt_data
    global fft_data
    
    rt_line.set_xdata(rt_x_data)
    rt_line.set_ydata(rt_data)
    
    fft_line.set_xdata(fft_x_data)
    fft_line.set_ydata(fft_data)
    return fft_line,rt_line,




ani = animation.FuncAnimation(fig, plot_update,
                              init_func=plot_init, 
                              frames=1,
                              interval=30,
                              blit=True)




# pyaudio
p = pyaudio.PyAudio()
q = queue.Queue()


def audio_callback(in_data, frame_count, time_info, status):
    global ad_rdy_ev


    q.put(in_data)
    ad_rdy_ev.set()
    if counter <= 0:
        return (None,pyaudio.paComplete)
    else:
        return (None,pyaudio.paContinue)




stream = p.open(format=FORMAT,
        channels=CHANNELS,
        rate=RATE,
        input=True,
        output=False,
        frames_per_buffer=CHUNK,
        stream_callback=audio_callback)




if Recording:
    wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
    wf.setnchannels(CHANNELS)
    wf.setsampwidth(p.get_sample_size(FORMAT))
    wf.setframerate(RATE)


print("Start Recording")
stream.start_stream()


#processing block


window = signal.hamming(CHUNK)


def read_audio_thead(q,stream,frames,ad_rdy_ev):
    global rt_data
    global fft_data


    while stream.is_active():
        ad_rdy_ev.wait(timeout=1000)
        if not q.empty():
            #process audio data here
            data=q.get()
            while not q.empty():
                q.get()
            rt_data = np.frombuffer(data,np.dtype('<i2'))
            #rt_data = rt_data * window
            fft_temp_data=fftpack.fft(rt_data,rt_data.size,overwrite_x=True)
            fft_data=np.abs(fft_temp_data)[0:int(fft_temp_data.size/2+1)]
            if Recording :
                frames.append(data)
        ad_rdy_ev.clear()


ad_rdy_ev=threading.Event()


t=threading.Thread(target=read_audio_thead,args=(q,stream,frames,ad_rdy_ev))


t.daemon=True
t.start()


plt.show()
root=tk.Tk()
app=Application(master=root)
app.master.title("Test")
app.mainloop()


stream.stop_stream()
stream.close()
p.terminate()


print("* done recording")
if Recording:
    wf.writeframes(b''.join(frames))
    wf.close()


    我怎么使用它呢?他这个代码是没有与tkinter结合的,我放到我们的tkinter代码里,发现animation不能用,于是又网搜,找到了方案,ax必须放在tkinter控件创建完毕后才能创建,从而animation才能起作用。后来又遇到多线程导致程序崩溃的问题。发现不能在多个线程做gui更新,于是把gui操作放在动画的每一帧里做,问题解决,用了全局量,虽然不喜欢但是工作正常,也就不深究了。现在实时效果很好。

阅读全文
0 0
原创粉丝点击