The device is connected to /dev/ttyS0 with a baud rate of 19200, 8-bit data, no parity, and 1 stopbit. You need to edit the line 'serial.Serial' with the relevant parameters to use this code for your device. Editing 'DATA_LENGTH' will change the rate at which the graph scrolls forward. Also, you'd need to change the 'command' that the device understands as 'send me data' (here it is the s character - line 'input'). Knowledge of the format of the returned data is also essential (here I turn ascii into 2 integers) line 'struct.unpack' - see here for help). Otherwise this should work with any device. Tested on Ubuntu 9.10 and 10.4 using serial port and USB-serial converters.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import pprint | |
import sys | |
import wx | |
# use wx with mpl is with the WXAgg backend | |
import matplotlib | |
matplotlib.use('WXAgg') | |
from matplotlib.figure import Figure | |
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigCanvas, NavigationToolbar2WxAgg as NavigationToolbar | |
import numpy as npy | |
import pylab | |
import serial | |
import time | |
import struct | |
# set connection: | |
ser = serial.Serial('/dev/ttyUSB0', 19200, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=1, timeout=0.1, xonxoff=1, rtscts=0) | |
ser.open() # open connection | |
ser.isOpen() # should be true | |
DATA_LENGTH = 120 #seconds | |
REDRAW_TIMER_MS = 60 # milliseconds | |
def getData(): | |
input = 's' | |
# send 's' the character to the device | |
ser.write(input) | |
out = '' | |
# give device time to answer | |
time.sleep(0.02) | |
while ser.inWaiting() > 0: | |
out += ser.read(1) #request data (serial.read() only returns 8 bit ASCII strings) | |
#out += ser.read(ser.inWaiting()) | |
if out != '': | |
# read in a length-2 string of 8-bit characters and then use the struct module to convert the strings into integers | |
response=struct.unpack(">bb", out) | |
# use only first integer in tuple (2nd is empty) | |
print response[0] | |
return response[0] | |
class GraphFrame(wx.Frame): | |
# the main frame of the application | |
def __init__(slf): | |
wx.Frame.__init__(slf, None, -1, "Sensor response", size=(800,600)) | |
slf.Centre() | |
slf.data = [] | |
slf.create_main_panel() | |
slf.redraw_timer = wx.Timer(slf) | |
slf.Bind(wx.EVT_TIMER, slf.on_redraw_timer, slf.redraw_timer) | |
slf.redraw_timer.Start(REDRAW_TIMER_MS) | |
def create_main_panel(slf): | |
slf.panel = wx.Panel(slf) | |
slf.init_plot() | |
slf.canvas = FigCanvas(slf.panel, -1, slf.fig) | |
slf.hbox1 = wx.BoxSizer(wx.HORIZONTAL) | |
slf.vbox = wx.BoxSizer(wx.VERTICAL) | |
slf.vbox.Add(slf.canvas, 1, flag=wx.LEFT | wx.TOP | wx.GROW) | |
slf.panel.SetSizer(slf.vbox) | |
def init_plot(slf): | |
slf.dpi = 100 | |
slf.fig = Figure((3.0, 3.0), dpi=slf.dpi) | |
slf.axes = slf.fig.add_subplot(111) | |
slf.axes.set_axis_bgcolor('black') | |
slf.axes.set_title('My data', size=12) | |
slf.ymin = -50000 # initalise with large values | |
slf.ymax = 50000 | |
pylab.setp(slf.axes.get_xticklabels(), fontsize=8) | |
pylab.setp(slf.axes.get_yticklabels(), fontsize=8) | |
# plot the data as a line series, and save the reference | |
# to the plotted line series | |
slf.plot_data = slf.axes.plot( | |
slf.data, | |
linewidth=2, | |
color="white", | |
)[0] | |
#count=count+1 | |
#if count>120: | |
# slf.Destroy() | |
def draw_plot(slf): | |
# redraws the plot | |
xmax = len(slf.data) if len(slf.data) > DATA_LENGTH else DATA_LENGTH | |
xmin = xmax - DATA_LENGTH | |
ymin = slf.ymin # ymin and ymax set based on previous entries | |
ymax = slf.ymax #50000 | |
slf.axes.set_xbound(lower=xmin, upper=xmax) | |
slf.axes.set_ybound(lower=ymin, upper=ymax) | |
pylab.setp(slf.axes.get_xticklabels(), visible=True) | |
slf.plot_data.set_xdata(npy.arange(len(slf.data))) | |
slf.plot_data.set_ydata(npy.array(slf.data)) | |
slf.canvas.draw() | |
def on_redraw_timer(slf, event): | |
newData = getData() | |
slf.data.append(newData) | |
slf.draw_plot() | |
data=slf.data | |
if len(data)>=6: | |
# get last 5 values | |
datanew=[data[len(slf.data)-5],data[len(slf.data)-4],data[len(slf.data)-3],data[len(slf.data)-2],data[len(slf.data)-1]] | |
slf.ymin = (min(datanew))-(min(datanew)*10)/100 # min of last 5, minus 10% | |
slf.ymax = (max(datanew))+(max(datanew)*10)/100 # max of last 5, plus 10% | |
else: | |
slf.ymin = (min(data))-(min(data)*10)/100 # min minus 10% | |
slf.ymax = (max(data))+(max(data)*10)/100 # max plus 10% | |
def on_exit(slf, event): | |
slf.Destroy() | |
def flash_status_message(slf, msg, flash_len_ms=1500): | |
slf.statusbar.SetStatusText(msg) | |
slf.timeroff = wx.Timer(slf) | |
slf.Bind( | |
wx.EVT_TIMER, | |
slf.on_flash_status_off, | |
slf.timeroff) | |
slf.timeroff.Start(flash_len_ms, oneShot=True) | |
def on_flash_status_off(slf, event): | |
slf.statusbar.SetStatusText('') | |
if __name__ == '__main__': | |
app = wx.PySimpleApp() | |
app.frame = GraphFrame() | |
app.frame.Show() | |
app.MainLoop() |
No comments:
Post a Comment