使用带有Tkinter GUI python的动画图形

时间:2016-03-13 15:44:13

标签: python python-2.7 matplotlib tkinter arduino

我正在开发一个python代码,我的计算机读取使用串行通信传输的数据,我的程序以图形格式显示这些数据。每0.1秒接收一次新数据,然后更新图表。

代码是:

import matplotlib
matplotlib.use("TkAgg")
from matplotlib import *
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import matplotlib.animation as animation
from random import *
from Serial import *
import Tkinter as tk
import ttk
import xlwt
import serial

COMPORT = "COM7"
BUAD = 115200

def init():
    connected = False
    global ser
    global COMPORT, BUAD
    ser = serial.Serial(COMPORT, BUAD)
    while not connected:
        serin = ser.read()
        connected = True

def TransmitCommand(Command):
    SCommand = Command + 'y'
    ser.write(SCommand)

def TransmitData(Data):
    SData = str(Data) + 'y'
    ser.write(SData)

def ClosePort():
    ser.close()

def RecieveData():
    return ser.readline()


################################################################################
############################    Graph1   #######################################
################################################################################
F1 = Figure(figsize=(15,8), dpi=80)
rc("font", size = 10)
Figure
a1 = F1.add_subplot(111)
tList = []
xList = []
yList = []
zList = []
fList = []
xfList = []
yfList = []
zfList = []
fxList = []
fyList = []
fzList = []
t = 0.00
t1 = 0
x = 0
y = 0
z = 0
ex = 0
ey = 0
ez = 0
r1 = 0
r2 = 0
r3 = 0
l = 0
txp = 0
typ = 0
tzp = 0
global fx1, fy1, fz1
fx1 = 0.00000
fy1 = 0.00000
fz1 = 0.00000

PPS1 = 1

def Play1():
    global PPS1
    TransmitCommand('SendData')
    #print 'Done'
    PPS1 = 0
def Pause1():
    global PPS1
    TransmitCommand('StopData')
    PPS1 = 1
def Stop1():
    global PPS1
    TransmitCommand('StopData')
    PPS1 = 2
def Extract1():
    pass
def Save1():
    pass


def SaveGraph1():
    pass

def animate1(i):
    global l, ex, ey, ez, t, x, y, z, tList, xList, yList, zList, r1, r2, r3
    global fx1, fy1, fz1, txp, typ, tzp, xt, yt, zt

    if(PPS1 == 0):
        tList.append(t)
        xList.append(x)
        yList.append(y)
        zList.append(z)

        t = int(RecieveData())
        x = int(RecieveData())
        if(l == 0):
            x = (x*0.707)/300
        else:
            x = ex - (x*0.707)/300
        if(x > 0):
            if(xList[l-1] == 0)|(xList[l-1] < 0):
                fx1 = (1.0/(t - txp))*1000
                txp = t
                r1 = 1
        y = int(RecieveData())
        if(l == 0):
            y = (y*0.707)/300
        else:
            y = ey - (y*0.707)/300
        if(y > 0):
            if(yList[l-1] == 0)|(yList[l-1] < 0):
                fy1 = (1.0/(t - typ))*1000
                typ = t
                r2 = 1
        z = int(RecieveData())
        if(l == 0):
            z = (z*0.707)/300
        else:
            z = ez - (z*0.707)/300
        if(z > 0):
           if(zList[l-1] == 0)|(zList[l-1] < 0):
                fz1 = (1.0/(t - tzp))*1000
                tzp = t
                r3 = 1

        if(l == 0):
            ex = x
            ey = y
            ez = z

        l = l+1

    if(PPS1 == 2):    
        tList = []
        xList = []
        yList = []
        zList = []
        t = 0
        x = 0
        y = 0
        z = 0    

    a1.clear()
    a1.plot(tList, xList, label = "ax")
    a1.plot(tList, yList, 'r', label = "ay")
    a1.plot(tList, zList, 'g', label = "az")
    a1.set_ylim(-1,1)
    a1.set_xlabel("Time (ms)")
    a1.set_ylabel("Acceleration (g)")
    a1.legend()   

def GenerateGraph1(Master):
    dataPlot = FigureCanvasTkAgg(F1, master=Master)
    dataPlot.show()
    dataPlot.get_tk_widget()

    display1 = tk.Canvas(Master, width=100, height=400, bg ="white")
    display1.pack(side = 'right')
    button1 = tk.Button(display1, text='Play', command=Play1, font='Times 12', bd=5,
                                height = 2, width = 10, anchor = 'w').grid(row = 0, column = 0)
    button2 = tk.Button(display1, text='Pause', command=Pause1, font='Times 12', bd=5,
                                height = 2, width = 10, anchor = 'w').grid(row = 1, column = 0)
    button3 = tk.Button(display1, text='Stop', command=Stop1, font='Times 12', bd=5,
                                height = 2, width = 10, anchor = 'w').grid(row = 2, column = 0)
    button4 = tk.Button(display1, text='Extract Data', command=Extract1, font='Times 12', bd=5,
                                height = 2, width = 10, anchor = 'w').grid(row = 3, column = 0)
    button5 = tk.Button(display1, text='Save Data', command=Save1, font='Times 12', bd=5,
                                height = 2, width = 10, anchor = 'w').grid(row = 4, column = 0)
    button5 = tk.Button(display1, text='Save Graph', command=SaveGraph1, font='Times 12', bd=5,
                                height = 2, width = 10, anchor = 'w').grid(row = 5, column = 0)
    button5 = tk.Button(display1, text='Send Mail', command=Save1, font='Times 12', bd=5,
                                height = 2, width = 10, anchor = 'w').grid(row = 6, column = 0)
    toolbar = NavigationToolbar2TkAgg(dataPlot, Master)
    toolbar.update()
    dataPlot._tkcanvas.pack()

def show_frame():
    frame = GenerateGraph(Graph)
    frame.tkraise()

Main = tk.Tk()
init()
n = ttk.Notebook(Main, width= 800, height = 400)
n.grid(row=6,column=0, columnspan=9)
n.columnconfigure(0, weight=1)
n.rowconfigure(6, weight=1)    

f1 = ttk.Frame(n);
n.add(f1, text='Acceleration vs Time')
GenerateGraph1(f1)
ani1 = animation.FuncAnimation(F1, animate1, interval=100)
mainloop()

Arduino代码是:

int toggle1 = 0;
boolean Graph = 0;
int x = 0;
int y = 0;
int z = 0;
int i = 0;

const int groundpin = 18;             // analog input pin 4 -- ground
const int powerpin = 19;              // analog input pin 5 -- voltage
const int xpin = A3;                  // x-axis of the accelerometer
const int ypin = A2;                  // y-axis
const int zpin = A1;                  // z-axis (only on 3-axis models)

#include <elapsedMillis.h>
elapsedMillis timeElapsed;

void Acceleration(){
  Serial.print(timeElapsed);
  Serial.print("\n");
  Serial.print(analogRead(xpin));
  Serial.print("\n");
  Serial.print(analogRead(ypin));
  Serial.print("\n");
  Serial.print(analogRead(zpin));
  Serial.print("\n");
  }

void setup()
{
  Serial.begin(115200);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(xpin, INPUT);
  pinMode(ypin, INPUT);
  pinMode(zpin, INPUT);
  Serial.write('1'); 

  noInterrupts();           // disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;

  OCR1A = 25000;            // compare match register 16MHz/64/10Hz
  TCCR1B |= (1 << WGM12);   // CTC mode
  TIMSK1 |= (1 << OCIE1A);  // enable timer compare interrupt
  interrupts();             // enable all interrupts
  TCCR1B |= (1 << CS10);
  TCCR1B |= (1 << CS11);

  pinMode(groundpin, OUTPUT);
  pinMode(powerpin, OUTPUT);
  digitalWrite(groundpin, LOW);
  digitalWrite(powerpin, HIGH);
}

ISR(TIMER1_COMPA_vect){
  if(Graph == 1){
    Acceleration();
}}

void loop() {
  String brightness, recieve, r1;
  int b1, b2, ledPin;

  while(Serial.available() == 0) {}
  recieve = Serial.readStringUntil('y');
  r1 = recieve + "t";
  if(recieve == "SendData"){Graph = 1;}
  if(recieve == "StopData"){Graph = 0;timeElapsed = 0;}
  if(recieve == "motor1"){
    ledPin = 8;
    while(Serial.available() == 0){}
    brightness = Serial.readStringUntil('y');
    b1 = brightness.toInt();
    analogWrite(ledPin, b1);}
  if(recieve == "motor2"){
    ledPin = 9;
    while(Serial.available() == 0){}
    brightness = Serial.readStringUntil('y');
    b1 = brightness.toInt();
    analogWrite(ledPin, b1);}
  }
  }

我从振动传感器获取数据。我使用秒表来计算实际开始振动的时间与图表开始显示数据变化的时间之间的差异。对于第一组数据,时间差为5秒,对于数据组2,差异为1分10秒,对于第三组,则为2分钟。当我添加第二个图表和GUI的其余部分时,效果变得更加明显。我需要这个软件能够运行几个小时,这意味着我的GUI可能会一度无响应,我还需要数据是实时的。可能是导致此问题的原因以及如何解决它。可能有一种更好的方式将GUI中的实时数据显示为图形,但由于我是python的新手,我不知道。

1 个答案:

答案 0 :(得分:0)

这个简单的动画示例将每秒绘制一个新的红点,该方法应该比你正在做的更稳定;我有一个运行超过4个月的应用程序,每分钟绘制一次,如下所示:

import matplotlib.pyplot as plt
import random
import time
plt.ion()

x = 0
while x<100:
    y = random.random()
    plt.plot(x,y,marker='.',c='red')
    x+=1
    time.sleep(1)
    plt.tight_layout()
    plt.show()
    plt.pause(0.1)

你说你需要它实时&#34;,但可能是你的代码的执行时间比你获得新数据的时间长0.1秒。最好每10个数据点更新一次图表;或者我正在做......每分钟一次。