Pythonskole

LIVE plotting med PASCO

PASCO lanserte høsten 2021 en integrasjon av sine trådløse (hvite) sensorer direkte i Python. Det åpnet for muligheten av å plotte, måle og analysere data i sanntid på en måte som ikke har vært mulig før. Her er en kort introduksjon (i videoformat) til hva det er mulig å gjøre, samt tre koder som du kan ta i bruk selv.  

Innhold

Video

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.

Kode: pasco-devices.py

Med denne koden kan du sjekke hvilke enheter som er tilgjengelig, koble til en av dem og sjekke hva de tilbyr av sensorer og måledata.

Ønsker du å kopiere koden og prøve den selv, trykk «Copy» øverst til høyre vi kodevinduet under. 

				
					# pasco-device.py
# Looks for Pasco devices and prints their available 
# sensors and measurments. Then disconnects.
# 
# Import pasco libraries
# Documentation: https://pypi.org/project/pasco/
from pasco.pasco_ble_device import PASCOBLEDevice
from pasco.code_node_device import CodeNodeDevice
from pasco.character_library import Icons

# Create handle to manage devices
device = PASCOBLEDevice()

# Read available bluetooth devics. 
# Please make sure of the following 
# before running this code: 
#  - the PC's bluetooth is on
#  - the device(s) is on and blinking red (not green)
#  - the device(s) are close to the PC
found_devices = device.scan()
n = len(found_devices)
print("Found ",n," devices")
if n == 0: exit(0)  #Exit code if no devices are found

#Print list of available devices
for i, ble_device in enumerate(found_devices):
    print(f'{i}: {ble_device.name}')

#Ask for user input, for what device we want to analyze
selected_device = found_devices[int(input('Select a device: '))]

#Connect to device
print("Connecting to:"+str(selected_device))
device.connect(selected_device)

#Print warning if connection failed, exit code if fail
if not device.is_connected():
    print("Connection failed")
    exit(0)

#Print list of sensors on device
print("Sensor list:",device.get_sensor_list())
#Print list of measurments available with the sensors
print("Measurement list:",device.get_measurement_list())

#Clean disconnect. If the code exists with an error between 
#device.connect() and device.disconnect(), the devices will blink
#green after running this code. To make them available 
#for a new connection, you need to first turn them off, then 
#restart them (you want a red blinking light) on the bluetooth-lamp
device.disconnect()


				
			

Kode: pasco-codenode-liveplotting.py

Med denne koden leker vi med plotting i sanntid fra en //Code.Node og noen muligheter til å programmere lamper og høytaleren på enheten. 

Ønsker du å kopiere koden og prøve den selv, trykk «Copy» øverst til høyre vi kodevinduet under. 

				
					#LIVE PLOTTING WITH PASCO PYTHON MODULE
#CONTACT: kontakt@pythonskole.no
#Version 15.10.2021

# Documentation: https://pypi.org/project/pasco/
from pasco.pasco_ble_device import PASCOBLEDevice
from pasco.code_node_device import CodeNodeDevice
from pasco.character_library import Icons

from matplotlib import animation
import matplotlib.pyplot as plt
import time
import numpy as np


##############################################################
#Edit this section: 
##############################################################
# Say what data you want to plot from the code-node. 
# These are your options: 
# 'Temperature', 'Brightness', 'Loudness', 'MagneticFieldStrength', 
# 'Accelerationx', 'Accelerationy', 'TiltAngleX', 'TiltAngleY', 
# 'CartPosition', 'CartVelocity', 'Button1', 'Button2'
data    = 'Accelerationy'   #Choose from the list above
measure_time = 15.0         #Say how many seconds you want to measure
ymin =  -15                  #What max/min y-values do you expect
ymax =  15
max_iterations = 200        #At how many iterations do you wish to abort?
dump_data = True


#################################################################
################  EDIT THIS AT YOUR OWN RISK ####################
#################################################################


# Create a code element, through which we can handle the instrument
codenode = CodeNodeDevice()
# List all code.Node-devices
codenode_list = codenode.scan('//code.Node')
if codenode_list:  # Go forth if some devices are found
    # Print the list of devices
    for i, dev in enumerate(codenode_list):
        print(str(i)+":"+str(dev))
    # Get user input which device you want. 
    # If there is only one, select that device automatically
    select = input('Select a codenode: ') if len(codenode_list) > 1 else 0
    select_codenode = codenode_list[int(select)]
    print("Connecting to:"+str(select_codenode))
    codenode.connect(select_codenode)
else:
    print("No codenode found")
    exit(0)

if not codenode.is_connected():
    print("Connection failed")
    exit(0)

#Prevent the device to disconnect after 5 minutes
codenode.keepalive()

led_list = [[0,0],[1,1], [3,3], [2,2], [4,4]]
codenode.set_leds_in_array(led_list, 128)
time.sleep(1)
codenode.set_sound_frequency(440)
time.sleep(1)
led_list = [[0,4],[1,3], [2,2], [3,1], [4,0]]
codenode.set_leds_in_array(led_list, 128)
codenode.set_rgb_led(0, 50, 150)
time.sleep(1)
led_list = [[0,0],[1,1], [3,3], [2,2], [4,4]]
codenode.set_leds_in_array(led_list, 128)
codenode.set_rgb_led(150, 50, 0)
time.sleep(1)
led_list = [[0,4],[1,3], [2,2], [3,1], [4,0]]
codenode.set_leds_in_array(led_list, 128)
codenode.set_rgb_led(150, 150, 50)
time.sleep(1)
led_list = [[0,0],[1,1], [3,3], [2,2], [4,4]]
codenode.set_leds_in_array(led_list, 128)
codenode.set_rgb_led(0, 50, 150)
time.sleep(1)
led_list = [[0,4],[1,3], [2,2], [3,1], [4,0]]
codenode.set_leds_in_array(led_list, 128)
codenode.set_rgb_led(150, 50, 0)
time.sleep(1)
led_list = [[0,0],[1,1], [3,3], [2,2], [4,4]]
codenode.set_leds_in_array(led_list, 128)
codenode.set_rgb_led(150, 150, 50)
time.sleep(1)
led_list = [[0,4],[1,3], [2,2], [3,1], [4,0]]
codenode.set_leds_in_array(led_list, 128)
codenode.set_sound_frequency(0)
time.sleep(2)

#Setup data storage and plotting parameters
xdata   = []
ydata   = []
t_start = time.time()
t_stop  = t_start+measure_time
xdata_range = [0,measure_time]
ydata_range = [ymin,ymax]

#Set up figure, axis and plot element
fig = plt.figure()
ax  = plt.axes()
plt.title(data)
plt.ylabel(data)
plt.xlabel('Tid (s)')
ax.set_xlim(xdata_range)
ax.set_ylim(ydata_range)
line, = ax.plot([], [])

# initialization function: plot the background
def init():
    line.set_data([],[])
    return line,

# animation function.  This is called sequentially
def animate(i):
    tid = time.time()-t_start
    verdi = codenode.read_data(data)
    xdata.append(tid)
    ydata.append(verdi)
    line.set_data(xdata,ydata)
    if dump_data: 
        print("Frame:{0:3d} Tid:{1:6.2f}s  fps={2:4.1f}  "+data+"={3:10.4f}".\
            format(i,tid,i/tid,verdi),end='\r')
    else: 
        print("Frame:{0:3d} Tid:{1:6.2f}s  fps={2:4.1f}".\
                format(i,tid,i/tid),end='\r')
    return line,

# call the animator.  blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,
            frames=max_iterations, interval=1, blit=True, repeat=False)
plt.show()



# My experience is that this is needed to avoid 
# bluetooth-issues at connection-time
codenode.disconnect()



				
			

Kode: pasco-temperature-live.py

Med denne koden leker vi med temperatursensoren og kurvetilpasninger. Målinger og regresjon skjer i sanntid, og koden er gjort tilgjengelig så elevene selv kan gå inn å endre funksjonen som tilpasses. 

Ønsker du å kopiere koden og prøve den selv, trykk «Copy» øverst til høyre vi kodevinduet under. 

				
					#CODE: pasco-temperature-live.py
#Version: 20.10.2021
#Author: Vegard Rekaa (kontakt@pythonskole.no)

# Documentation: https://pypi.org/project/pasco/
from pasco.pasco_ble_device import PASCOBLEDevice

from matplotlib import animation
import matplotlib.pyplot as plt
import time
import numpy as np #We only need polyfit here

device = PASCOBLEDevice()
available_devices = device.scan()
n = len(available_devices)
print("Found ",n," devices")
for dev in available_devices: 
    print(dev)
if n == 0: 
    print("Exiting")
    exit(0)

device_id = '508-699'
print("Connecting to my temperature sensor: ",device_id)
device.connect_by_id(device_id)

#print("Connecting to the first device in the list")
#print("Device: "+str(available_devices[0]))
#device.connect(available_devices[0])
if not device.is_connected():
    print("Connection failed")
    exit(0)

device.keepalive()

#set up the experiment
tid_start = time.time()
tid = 0
xmin = 0
xmax = 120.0
ymin = 10.0
ymax = 50.0
interval = 2000 #ms between each message
max_iterations = int((xmax-xmin)/(interval/1000))
data_type = 'Temperature'
xdata  = []
y1data = []
y2data = []


def curvefit():
    #Linear curve fit
    if len(xdata) < 2:
        a,b = 0.0,0.0
    else:
        a,b = np.polyfit(xdata,y1data,1)
    return [a*x + b for x in xdata]
    #Fourth order polynomial curve fit
    #if len(xdata) < 5:
    #    a,b,c,d,e = 0.0,0.0,0.0,0.0,0.0
    #else:
    #    a,b,c,d,e = np.polyfit(xdata,y1data,4)
    #return [a*x**4 + b*x**3 + c*x**2 + d*x + e for x in xdata]


#Set up figure, axis and plot element
fig = plt.figure()
ax  = plt.axes()
ax.set_xlim([xmin,xmax])
ax.set_ylim([ymin,ymax])
plt.xlabel("Tid (s)")
plt.ylabel("Temperatur (C)")
labels     = ['Data','Curve fit']
colors     = ["blue","red"]
linestyles = ['dotted','solid']
markers    = ['.','']

#Set up initial line elements
lines = []
for index in range(2):
    lobj = ax.plot([],[],linewidth=1,label=labels[index],color=colors[index],
            linestyle=linestyles[index],marker=markers[index])[0]
    lines.append(lobj)


# initialization function: plot the background
def init():
    for line in lines:
        line.set_data([],[])
    plt.legend()
    return lines

# animation function.  This is called sequentially
def animate(i):
    tid = time.time()-tid_start
    print("Frame:{0:3d} Tid:{1:6.2f}s  fps={2:4.1f}".\
            format(i,tid,i/tid),end='\r')
    xdata.append(tid)
    y1data.append(device.read_data(data_type))
    y2data = curvefit()
    lines[0].set_data(xdata,y1data)
    lines[1].set_data(xdata,y2data)
    return lines


# call the animator
print("Max iterations:",max_iterations)
anim = animation.FuncAnimation(fig, animate, init_func=init,
            frames=max_iterations, interval=interval, repeat=False)

#handles,labels = ax.get_legend_handles_labels()
#plt.legend(handles,labels)
plt.show()

device.disconnect()



				
			

Takk for din bestilling!

Vi kontakter deg så snart vi har lest din bestilling. Om du er på jakt etter inspirasjon til hva det kurset du ønsker skal handle om, kan du se vår YouTube-kanal.

Om du blir utålmodig eller har travelt med å få bekreftet din bestilling, kontakt oss på 93024034 eller kontakt@pythonskole.no.

Vennlig hilsen Vegard & Co