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()