Implementing NI USB-6009 and Optical Sensor for Project - python

I am currently working on a project where I utilise NI USB - 6009 and an optical sensor to register wheel rotation then from there calculate the angular and linear velocity. My plan is to plot that output in the python GUI (tkinter) and if possible the graph as well. My arrangement is as followed:
digital output from sensor to NI USB 6009 digital input, vcc to 5v and gnd to ground (I think that is the standard wiring). So far, I can put the number of pulses on the gui but it has to be plotted together with the plot here and also I am not able to calculate the time between pulses because the task module takes extra work. Did anyone have a similar experience so one might share the solution? or should I go with arduino instead?
Appreciate your help
here are my codes:
import nidaqmx
import math
from nidaqmx.constants import Edge
from nidaqmx.constants import AcquisitionType
from nidaqmx.constants import VoltageUnits
from nidaqmx.constants import TerminalConfiguration
import matplotlib.pyplot as plt
from matplotlib import style
import numpy as np
import time
import nidaqmx.system
from nidaqmx.system import system as nidaqSystem
import tkinter as tk
from tkinter import ttk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
nfft = 1000
fs = 1000.0
win = tk.Tk()
win.configure(bg='white')
win.geometry("650x400")
win.resizable(False,False)
with nidaqmx.Task() as task:
task.di_channels.add_di_chan("Dev1/port1/line0")
# task.timing.cfg_samp_clk_timing(fs, active_edge=Edge.RISING, sample_mode=AcquisitionType.CONTINUOUS, samps_per_chan=nfft)
fig = plt.figure()
# ax1 = fig.add_subplot(211)
# ax2 = fig.add_subplot(212)
# freqs = np.linspace(0, int(fs/2), int(nfft/2+1))
while True:
t1 = (int(round(time.time() * 1000)))
data = task.read(number_of_samples_per_channel=nfft)
if data == True:
data == 1
else:
data == 0
pulse = math.floor(np.sum(np.diff(data) > 0)/2)
print(pulse)
count_label = ttk.Label(win,text=pulse,background='white')
count_label.place(x=10, y=10)
# graph = FigureCanvasTkAgg(fig,win)
# graph.draw()
# graph.get_tk_widget().pack(side=tk.LEFT, fill=tk.BOTH,expand=True)
# count_entry = ttk.Entry(win,textvariable=print(pulse))
# count_entry.place(x=10,y=30)
# count_entry = tk.StringVar()
# ax1.clear()
# ax2.clear()
# ax1.plot(data)
# ax2.plot(pulse)
fig.show()
plt.pause(0.1)
# t3 = (int(round(time.time() * 1000)))
win.mainloop()

Related

Updating a real time plot using Matplotlib

I'm trying to generate a real time plot using Matplotlib, with real time gathered data from an Arduino MKR1000.
Code:
import serial
import matplotlib.pyplot as plt
import numpy as np
ser = serial.Serial('COM7', 9600)
plt.close('all')
plt.figure(figsize=[10,8])
plt.ion()
data = np.array([])
while True:
a = ser.readline()
a = a.decode()
b = float(a[0:4])
data = np.append(data, b)
plt.plot(data)
plt.pause(0.1)
The output is a new plot created every 0.1 seconds, but I want to update the same real-time plot.
Anyone can help?
I'm using Python 3 on a Windows 10 system

Simple matplotlib.animation graph geting slower very fast and than stoping

I've started to learn about matplotlib functions because i wanted to visualize data i was receiving via websocket. For that i made a dummy program that mimics the behaviour of my main program but has added the functionality of mathplotlib. what i noticed is the program takes more and more time to finish each loop and eventually 'freezes'. i managed to extend it life by changing the interval in animation.FuncAnimation from 1000 to 10000. But that just the program to plot sometimes up to 9s for 1 new peace of data. I believe the problem lays in a inappropriate way of cleaning old plots. But i don't know where exactly i did the mistake
import time
import datetime
import timeit
import queue
import os
import random
import copy
import matplotlib.pyplot as plt
import matplotlib.animation as animation
q = queue.Queue()
beta=[0,]
b=False
czas=[]
produkty=["primo"]
cena=[[] for _ in range(len(produkty))]
fig=plt.figure()
#ax1=fig.add_subplot(1,1,1)
#ax2=fig.add_subplot(1,1,1)
ax1=plt.subplot(1,1,1)
ax2=plt.subplot(1,1,1)
def animate(i):
ax1.clear()
ax2.clear()
ax1.plot(czas,cena[0])
ax2.plot(czas,beta)
while True:
time.sleep(1)
alpfa=time.time()
#input('press enter')
rand_produkt=random.choice(produkty)
rand_price=random.randint(1,10)
rand_czas=time.ctime()
alfa={'type':'ticker','price':rand_price,'product_id':rand_produkt,'time':rand_czas}
q.put(alfa)
if q.not_empty:
dane=q.get()
typ=dane.get('type',None)
if typ=='ticker':
price=dane.get('price', None)
pair=dane.get('product_id',None)
t=dane.get('time', None)
b=True
if b==True:
b=False
produkt_id=produkty.index(pair)
cena[produkt_id].append(float(price))
czas.append(t)
plt.ion()
ani=animation.FuncAnimation(fig,animate,interval=1000)#, blit=True)repeat=True)
plt.show()
plt.pause(0.001)
#fig.clf()
beta.append(time.time()-alpfa)
print(beta[-1])
The problem with your code is that you call a new animation in you while loop. Hence this will cause slow down down the line. It is better to initiate your plot ones. One trick may be to update the object data directly as such:
from matplotlib.pyplot import subplots, pause, show
from numpy import sin, pi
fig, ax = subplots()
x = [0]
y = [sin(2 * pi * x[-1])]
p1, = ax.plot(x, y)
show(block = False)
while True:
# update data
x.append(x[-1] + .1)
y.append(sin(2 * pi * x[-1]))
p1.set_data(x, y) # update data
ax.relim() # rescale axis
ax.autoscale_view()# update view
pause(1e-3)

speed up mplotlib when plotting live serial data

I am using an Arduino to create a 3d lidar scan of the area around it, and sending x,y,z coordinates over serial to a python script to visualize the data live. The issue I've run into is that mplotlib is much too slow to keep up with the stream. I have a feeling this is due to completely redrawing the plot, but I have not found a solution. I write s1000 over serial to start the lidar scan, and sending a x,y,z coordinate once per second.
import serial
import numpy
import matplotlib.pyplot as plt #import matplotlib library
from mpl_toolkits.mplot3d import Axes3D
from drawnow import *
from matplotlib import animation
import time
ser = serial.Serial('COM7',9600,timeout=5)
ser.flushInput()
time.sleep(5)
ser.write(bytes(b's1000'))
plt.ion()
fig = plt.figure(figsize=(16,12))
ax = fig.add_subplot(111, projection="3d")
ax.set_xlim3d(-255, 255)
ax.set_ylim3d(-255, 255)
ax.set_zlim3d(-255, 255)
x=list()
y=list()
z=list()
while True:
try:
ser_bytes = ser.readline()
data = str(ser_bytes[0:len(ser_bytes)-2].decode("utf-8"))
xyz = data.split(", ")
dx = float(xyz[0])
dy = float(xyz[1])
dz = float(xyz[2].replace(";",""))
x.append(dx);
y.append(dy);
z.append(dz);
ax.scatter(x,y,z, c='r',marker='o')
plt.draw()
plt.pause(0.0001)
except:
print("Keyboard Interrupt")
ser.close()
break

Embedding matplotlib into tkinter canvas opens two windows

The following code I am working on in not behaving the way I wish it to. I have embedded a matplotlib graph into a tkinter canvas. The program opens up two windows, one of which functions properly, and one of which is not necessary.I am not sure how to fix this. Here is the code, please ignore the unnecessary imports :)
import numpy as np
import sys
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import matplotlib as mpl
from matplotlib import cm
from numpy.random import random
from matplotlib.widgets import Button
import matplotlib.colors
import tkinter as tk
import matplotlib.backends.tkagg as tkagg
from matplotlib.backends.backend_agg import FigureCanvasAgg
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
DEBUG_MODE = False #Debug mode - True = ON
MATRIX_WIDTH = 50
MATRIX_HEIGHT = 50
WINDOW_WIDTH = 800
WINDOW_HEIGHT = 600
LED_COUNT = MATRIX_WIDTH * MATRIX_HEIGHT
REFRESH_RATE = 30 #REFRESH_RATE used to control FuncAnimation interval
MATRIX = random((50,50)) #Fills MATRIX as not to be null for first print
plt.rcParams['toolbar'] = 'None' #Disables matplotlib toolbar
fig = plt.figure(figsize=(3,3)) #'figsize' measured in inches
im = plt.imshow(MATRIX, interpolation='nearest', cmap=cm.Spectral)
plt.axis('off') #Turns off x, y axis
def data_gen(): #Generates amd populates MATRIX with pattern data
while True:
MATRIX = random((MATRIX_WIDTH, MATRIX_HEIGHT))
yield MATRIX
if (DEBUG_MODE): print("MATRIX yeilded")
def update(data): #Updates/prints new MATRIX from data_gen()
im.set_array(data)
if (DEBUG_MODE): print("Updated data")
root = tk.Tk()
label = tk.Label(root,text="Matrix Program").grid(column=0, row=0)
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.get_tk_widget().grid(column=0,row=1)
ani = animation.FuncAnimation(fig, update, data_gen, interval=REFRESH_RATE)
plt.show()
What needs to be done to this code so that it opens only one canvas from tkinter with the live matplotlib graph embedded?
How can I set the size of the canvas?
Do not call plt.show() if you want to show your figure inside a tk GUI. Best do not use pyplot at all when embedding.
On the other hand, you probably want to start the mainloop, tk.mainloop(), at some point.
Refer to the matplotlib example on how to embedd a matplotlib figure into tk.

Graph figure not displayed when live plotting arduino data with matplotlib

I am trying to plot real-time lectures from Arduino UNO's analogue input with matplotlib.
My problem: The graph would not be shown. Only when I stop running the code (Ctrl+C), It will show the last values's graph.
when adding "print pData" line to the code in order to check whether the values are properly arriving to the computer, these are correctly displayed (shows the 25 values array each second) on the python terminal.
#!/usr/bin/python
from matplotlib import pyplot
import pyfirmata
from time import sleep
# Associate port and board with pyFirmata
port = '/dev/ttyACM0'
board = pyfirmata.Arduino(port)
# Using iterator thread to avoid buffer overflow
it = pyfirmata.util.Iterator(board)
it.start()
# Assign a role and variable to analog pin 0
a0 = board.get_pin('a:0:i')
pyplot.ion()
pData = [0.0] * 25
fig = pyplot.figure()
pyplot.title('Real-time Potentiometer reading')
ax1 = pyplot.axes()
l1, = pyplot.plot(pData)
pyplot.ylim([0, 1])
while True:
try:
sleep(1)
pData.append(float(a0.read()))
pyplot.ylim([0, 1])
del pData[0]
l1.set_xdata([i for i in xrange(25)])
l1.set_ydata(pData) # update the data
#print pData
pyplot.draw() # update the plot
except KeyboardInterrupt:
board.exit()
break
Here is a mock-up that uses matplotlib.animation for real-time plotting.
from matplotlib import pyplot
import matplotlib.animation as animation
import random
# Generate sample data
class Pin:
def read(self):
return random.random()
a0 = Pin()
n = 25
pData = [None] * n
fig, ax = pyplot.subplots()
pyplot.title('Real-time Potentiometer reading')
l1, = ax.plot(pData)
# Display past sampling times as negative, with 0 meaning "now"
l1.set_xdata(range(-n + 1, 1))
ax.set(ylim=(0, 1), xlim=(-n + 1, 0))
def update(data):
del pData[0]
pData.append(float(a0.read()))
l1.set_ydata(pData) # update the data
return l1,
ani = animation.FuncAnimation(fig, update, interval=1000, blit=True)
try:
pyplot.show()
finally:
pass
#board.exit()

Categories

Resources