Skip to content

Commit 3d84bfe

Browse files
authored
Merge pull request #44 from VektrexElectronicSystems/development
Development
2 parents cdf9646 + f7a2b6b commit 3d84bfe

File tree

50 files changed

+28112
-23336
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+28112
-23336
lines changed

.vscode/settings.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"python.pythonPath": ".venv\\Scripts\\python.exe",
32
"python.linting.pylintEnabled": true,
4-
"python.linting.enabled": true
3+
"python.linting.enabled": true,
4+
"python.envFile": "${workspaceFolder}/.env"
55
}

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
# SpikeSafe Python Samples
22

33
Use these code samples to start learning how to communicate with your SpikeSafe via TCP/IP using Python. Sequences can be run with the following Vektrex products:
4-
- [SpikeSafe SMU](https://www.vektrex.com/products/spikesafe-source-measure-unit/)
4+
- [SpikeSafe PSMU](https://www.vektrex.com/products/spikesafe-source-measure-unit/)
55
- [SpikeSafe Performance Series ("PRF")](https://www.vektrex.com/products/spikesafe-performance-series-precision-pulsed-current-sources/)
66

77
## Directory
88

99
- [Getting Started](getting_started) - These sequences are primarily intended for first-time users of Vektrex products. They contain steps to perform the basic tasks that are necessary to run the sequences within the run_spikesafe_operating_modes folder.
1010
- [Run SpikeSafe Operating Modes](run_spikesafe_operating_modes) - These folders contain examples to run specific SpikeSafe modes designed to test LEDs, Lasers, and electrical equipment. Basic settings will be sent to the SpikeSafe, and then one or more channels will be enabled to demonstrate the operation of each mode.
11-
- [Making Integrated Voltage Measurements](making_integrated_voltage_measurements) - These folders contain examples to measure voltage using the SpikeSafe SMU's integrated voltage Digitizer. The SpikeSafe outputs current to an LED, Laser, or electrical equipment, and then voltage measurements are read and displayed onscreen.
12-
- [Using the Force Sense Selector Switch](using_force_sense_selector_switch) - These folders contain examples to operate the optional integrated switch within the SpikeSafe SMU. The SpikeSafe outputs to an LED, Laser, or electrical equipment as in the previous examples, and the switch is used to either disconnect the SpikeSafe from the test circuit or to operate an auxiliary source to power the DUT.
11+
- [Making Integrated Voltage Measurements](making_integrated_voltage_measurements) - These folders contain examples to measure voltage using the SpikeSafe PSMU's integrated voltage Digitizer. The SpikeSafe outputs current to an LED, Laser, or electrical equipment, and then voltage measurements are read and displayed onscreen.
12+
- [Using the Force Sense Selector Switch](using_force_sense_selector_switch) - These folders contain examples to operate the optional integrated switch within the SpikeSafe PSMU. The SpikeSafe outputs to an LED, Laser, or electrical equipment as in the previous examples, and the switch is used to either disconnect the SpikeSafe from the test circuit or to operate an auxiliary source to power the DUT.
1313
- [Application-Specific Examples](application_specific_examples) - These folders consist of more advanced sequences to address specific test scenarios, as well as some demonstrations to fine-tune your SpikeSafe current output. These sequences explain how to make light measurements using a SpikeSafe and a spectrometer, how to make in-situ junction temperature measurements on LEDs, and how to take full advantage of all SpikeSafe features.
1414

1515
## Usage
@@ -28,6 +28,9 @@ Some sequences involve graphing measurement results. To properly graph results,
2828
### Installing PyCLibrary Package
2929
Some sequences require external C resources, and requires the [PyCLibrary](https://pyclibrary.readthedocs.io/en/latest/) library. To install this library, enter the command `python -m pip install pyclibrary`. Once the PyCLibrary library is installed, each sequence that involves external C resources can be run as a standalone Python file.
3030

31+
### Installing pyserial Package
32+
Some sequences involve connecting to a serial interface instrument and requires the [pyserial](https://pypi.org/project/pyserial/) library (version 3.5 or greater). Use the command `python -m pip install pyserial` to install the latest version of pyserial. Once the pyserial library is installed, each sequence that involves a serial interface can be run as a standalone Python file.
33+
3134
### General Usage
3235
For most examples, you may need to modify the specified IP address within a sequence to match the IP address that is physically set on your SpikeSafe's DIP switch. In each sequence, the default IP address of 10.0.0.220 is set in the line `ip_address = '10.0.0.220'`.
3336

application_specific_examples/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
# Application-Specific Examples
22

3-
These sequences address specific scenarios in which SpikeSafe functionality is used in an integrated test system, or scenarios where more advanced SpikeSafe settings need to be tuned to meet specific criteria. These sequences are for users that are comfortable with the basic functionality of the SpikeSafe PRF or SMU. See individual folders' descriptions for more information on each sequence.
3+
These sequences address specific scenarios in which SpikeSafe functionality is used in an integrated test system, or scenarios where more advanced SpikeSafe settings need to be tuned to meet specific criteria. These sequences are for users that are comfortable with the basic functionality of the SpikeSafe PRF or PSMU. See individual folders' descriptions for more information on each sequence.
44

55
## Directory
6+
- [Controlling Thermal Platform Temperature](controlling_thermal_platform_temperature)
7+
- [Fixed Pulse Count Using Software Timing](fixed_pulse_count_using_software_timing)
68
- [Making Tj Measurements](making_tj_measurements)
9+
- [Measuring DC Staircase Voltages](measuring_dc_staircase_voltages)
710
- [Measuring Wavelength Spectrum](measuring_wavelength_spectrum)
811
- [Pulse Tuning](pulse_tuning)
912
- [Running LIV Sweeps](running_liv_sweeps)
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# Goal:
2+
# Use TEC to ramp up to 50°C, stabilize, and run for 10 minutes; then ramp down to 25°C, stabilize, and run for 10 minutes.
3+
4+
import logging
5+
import sys
6+
import time
7+
from datetime import datetime, timedelta
8+
from SerialInterface import SerialInterfaceDll
9+
from time import sleep
10+
11+
### set these before starting application
12+
set_temperature_one = 50
13+
set_temperature_one_stability_minutes = 10
14+
set_temperature_two = 25
15+
set_temperature_two_stability_minutes = 10
16+
17+
### setting up sequence log
18+
log = logging.getLogger(__name__)
19+
logging.basicConfig(filename='SpikeSafePythonSamples.log',format='%(asctime)s, %(levelname)s, %(message)s',datefmt='%m/%d/%Y %I:%M:%S',level=logging.INFO)
20+
21+
### start of main program
22+
try:
23+
log.info("ControllingThermalPlatformTemperature.py started.")
24+
25+
TEC_controller = SerialInterfaceDll()
26+
27+
# Set the beep enable sound
28+
TEC_controller.write_command("BEEP 1")
29+
30+
# Set the mount type to 284 TEC High Power LaserMount.
31+
# Will default sensor type, sensor coefficients, gain, fan mode, and current limit
32+
TEC_controller.write_command("TEC:MOUNT 284")
33+
34+
# Set temperature control mode
35+
TEC_controller.write_command("TEC:MODE:T")
36+
37+
# Set the heat/cool mode to both
38+
TEC_controller.write_command("TEC:HEATCOOL BOTH")
39+
40+
# Set the low set temperature limit to 10°C
41+
TEC_controller.write_command("TEC:LIMit:TLO 10")
42+
43+
# Set the high set temperature limit to 85°C
44+
TEC_controller.write_command("TEC:LIMit:THI 85")
45+
46+
# Set platform tolerance to be within 0.5°C of set point for 30 seconds
47+
TEC_controller.write_command("TEC:TOLerance 0.5, 30")
48+
49+
##### Target temperature 1
50+
51+
# Set set temperature to set_temperature_one
52+
TEC_controller.write_command("TEC:T {0}".format(set_temperature_one))
53+
54+
# Set controller output to on
55+
TEC_controller.write_command("TEC:OUT 1")
56+
57+
# Monitor until TEC is in tolerance
58+
while True:
59+
TEC_out_of_tolerance = TEC_controller.write_command("TEC:COND?")
60+
if TEC_controller.isKthBitSet(TEC_out_of_tolerance, 9) == True:
61+
break
62+
63+
# Let TEC temperature stabilize while in tolerance
64+
TEC_stability_start_time = time.time()
65+
while True:
66+
TEC_out_of_tolerance = TEC_controller.write_command("TEC:COND?")
67+
if ((TEC_controller.isKthBitSet(TEC_out_of_tolerance, 9) == True) and
68+
(time.time() - TEC_stability_start_time - 30 >= set_temperature_one_stability_minutes * 60)):
69+
break
70+
else:
71+
break
72+
73+
# Set set temperature to set_temperature_two
74+
TEC_controller.write_command("TEC:T {0}".format(set_temperature_two))
75+
76+
##### Target temperature 2
77+
78+
# Monitor until TEC is in tolerance
79+
while True:
80+
TEC_out_of_tolerance = TEC_controller.write_command("TEC:COND?")
81+
if TEC_controller.isKthBitSet(TEC_out_of_tolerance, 9) == True:
82+
break
83+
84+
# Let TEC temperature stabilize while in tolerance
85+
TEC_stability_start_time = time.time()
86+
while True:
87+
TEC_out_of_tolerance = TEC_controller.write_command("TEC:COND?")
88+
if ((TEC_controller.isKthBitSet(TEC_out_of_tolerance, 9) == True) and
89+
(time.time() - TEC_stability_start_time - 30 >= set_temperature_two_stability_minutes * 60 * 60)):
90+
break
91+
else:
92+
break
93+
94+
##### Disconnect
95+
TEC_controller.close()
96+
97+
log.info("ControllingThermalPlatformTemperature.py completed.\n")
98+
99+
except Exception as err:
100+
# print any general exception to both the terminal and the log file, then exit the application
101+
error_message = 'Program error: {}\n'.format(err)
102+
log.error(error_message)
103+
print(error_message)
104+
sys.exit(1)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Example for Controlling Thermal Platform Temperature using a Thermal Controller
2+
3+
## **Purpose**
4+
In this sequence, we will address how to control a thermal platform's temperature using a thermal controller in an integrated system. A thermal controlled platform is often used in LED/laser systems to control DUT temperature for taking precise junction temperature (Tj) measurements, and stabilizing temperature-controlled environments.
5+
6+
## Overview
7+
Operates a thermal controller (Arroyo 5400 Series TECSource) to control a thermal platform (Arroyo TEC 284 Series High Power LaserMount). The controller will have the platform to ramp up to 50°C, stabilize, and run for 10 minutes; then ramp down to 25°C, stabilize, and run for 10 minutes.
8+
9+
Install the libraries listed in the [Considerations](#considerations) section of this document. More information on TECSources can be found [here](https://www.arroyoinstruments.com/categories/temperature-controllers) and LaserMounts [here](https://www.arroyoinstruments.com/categories/lasermounts).
10+
11+
## Key Settings
12+
The following settings are configured by default. At the top of the sequence, there are multiple lines corresponding to individual test parameters. These lines may be modified to match the necessary parameters for your specific LED or Laser.
13+
14+
### Thermal Controller Settings
15+
- **Set Temperature One:** 50°C
16+
- **Set Temperature One Stability Time:** 10 minutes
17+
- **Set Temperature Two:** 25°C
18+
- **Set Temperature Two Stability Time:** 10 minutes
19+
20+
## Considerations
21+
- This sequence involves connecting to a serial thermal controller using RS-232 interface and requires the [pyserial](https://pypi.org/project/pyserial/) library. See instructions on installing this library under the "Usage" section in the [SpikeSafePythonSamples markdown file](/README.md#installing-pyserial-package).
22+
23+
## Expected Results
24+
After initializing the thermal controller, the thermal controller will ramp up to Set Temperature One at 50°C and stabilize for 10 minutes. Afterwards the thermal controller will ramp down to Set Temperature Two at 25°C and stabilize for 10 minutes.
25+
26+
## Useful Products for Controlling Thermal Platform Temperature using a Thermal Controller
27+
28+
Vektrex [Control Panel Software Application](https://www.vektrex.com/software-applications/control-panel/) provides a user interface to easily perform Tj measurements in minutes. Control Panel provides control over SpikeSafe current output, Voltage Digitizer measurements, and graphing tools such as a time square-root graphing and line-of-best-fit y-axis extrapolation in order to programmatically determine Vf(0). See the figure below:
29+
30+
![](control_panel_tj_screenshot.png)
31+
32+
For more information regarding Vektrex Control Panel, contact [email protected].
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import serial
2+
import serial.tools.list_ports as port_list
3+
from time import sleep
4+
5+
class SerialInterfaceDll(object):
6+
7+
def __init__(self, port=None, baudrate=38400, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=0, write_timeout=0, command_delay=0.1):
8+
self.port = port
9+
self.baudrate = baudrate
10+
self.parity = parity
11+
self.stopbits = stopbits
12+
self.bytesize = bytesize
13+
self.timeout = timeout
14+
self.write_timeout = write_timeout
15+
self.command_delay = command_delay
16+
17+
if port == None:
18+
ports = list(port_list.comports())
19+
for p in ports:
20+
print (p)
21+
# Choosing COM port from list of available connections
22+
if "USB Serial Port" in p[1]:
23+
try:
24+
self.port = p[0]
25+
# Setting up and connecting to device
26+
self.ser = serial.Serial(port = self.port,
27+
baudrate = self.baudrate,
28+
parity = self.parity,
29+
stopbits = self.stopbits,
30+
bytesize = self.bytesize,
31+
timeout = self.timeout,
32+
write_timeout = self.write_timeout)
33+
if self.ser.is_open:
34+
print("\n" + self.port + " has been opened.\n")
35+
self.ser.write(b'*IDN? \r\n')
36+
sleep(0.1)
37+
print(bytes.decode(self.ser.read(256)))
38+
else:
39+
print("\nDid not connect to " + self.port + "\n")
40+
return
41+
except:
42+
print("Failed to connect to " + p[0])
43+
else:
44+
self.ser = serial.Serial(port = self.port,
45+
baudrate = self.baudrate,
46+
parity = self.parity,
47+
stopbits = self.stopbits,
48+
bytesize = self.bytesize,
49+
timeout = self.timeout,
50+
write_timeout = self.write_timeout)
51+
52+
53+
def close(self):
54+
self.ser.close()
55+
sleep(self.command_delay)
56+
if not self.ser.is_open:
57+
print("\n" + self.port + " has been closed.\n")
58+
return
59+
60+
def write_command(self,command):
61+
response = None
62+
self.ser.write(str.encode(command) + b'\r\n')
63+
sleep(self.command_delay)
64+
response = bytes.decode(self.ser.read(256))
65+
return(response)
66+
67+
def isKthBitSet(self, n, k):
68+
if n & (1 << (k - 1)):
69+
return True
70+
else:
71+
return False
145 KB
Loading
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# Goal:
2+
# Make 10,000 pulses using software based timing and then shutoff pulsing
3+
4+
import sys
5+
import time
6+
import logging
7+
from spikesafe_python.ReadAllEvents import log_all_events
8+
from spikesafe_python.ReadAllEvents import read_until_event
9+
from spikesafe_python.SpikeSafeError import SpikeSafeError
10+
from spikesafe_python.TcpSocket import TcpSocket
11+
12+
### set these before starting application
13+
14+
# SpikeSafe IP address and port number
15+
ip_address = '10.0.0.220'
16+
port_number = 8282
17+
18+
### setting up sequence log
19+
log = logging.getLogger(__name__)
20+
logging.basicConfig(filename='SpikeSafePythonSamples.log',format='%(asctime)s, %(levelname)s, %(message)s',datefmt='%m/%d/%Y %I:%M:%S',level=logging.INFO)
21+
22+
### start of main program
23+
try:
24+
log.info("FixedPulseCountUsingSoftwareTimingExample.py started.")
25+
26+
# instantiate new TcpSocket to connect to SpikeSafe
27+
tcp_socket = TcpSocket()
28+
tcp_socket.open_socket(ip_address, port_number)
29+
30+
# reset to default state and check for all events,
31+
# it is best practice to check for errors after sending each command
32+
tcp_socket.send_scpi_command('*RST')
33+
log_all_events(tcp_socket)
34+
35+
# set Channel 1's mode to DC Dynamic and check for all events
36+
tcp_socket.send_scpi_command('SOUR1:FUNC:SHAP PULSEDDYNAMIC')
37+
log_all_events(tcp_socket)
38+
39+
# set Channel 1's Trigger Output to Positive and check for all events
40+
tcp_socket.send_scpi_command('OUTP1:TRIG:SLOP POS')
41+
log_all_events(tcp_socket)
42+
43+
# set Channel 1's Trigger Output Always and check for all events
44+
tcp_socket.send_scpi_command('SOUR0:PULS:TRIG ALWAYS')
45+
log_all_events(tcp_socket)
46+
47+
# set Channel 1's Pulse On Time to 1us and check for all events
48+
tcp_socket.send_scpi_command('SOUR1:PULS:TON 0.000001')
49+
log_all_events(tcp_socket)
50+
51+
# set Channel 1's Pulse Off Time 9us and check for all events
52+
tcp_socket.send_scpi_command('SOUR1:PULS:TOFF 0.000009')
53+
log_all_events(tcp_socket)
54+
55+
# set Channel 1's Pulse Width adjustment to disabled and check for all events
56+
tcp_socket.send_scpi_command('SOUR1:PULS:AADJ 0')
57+
log_all_events(tcp_socket)
58+
59+
# set Channel 1's current to 100mA and check for all events
60+
tcp_socket.send_scpi_command('SOUR1:CURR 0.1')
61+
log_all_events(tcp_socket)
62+
63+
# set Channel 1's voltage to 20V and check for all events
64+
tcp_socket.send_scpi_command('SOUR1:VOLT 20')
65+
log_all_events(tcp_socket)
66+
67+
# set Channel 1's Auto Range to On and check for all events
68+
tcp_socket.send_scpi_command('SOUR1:CURR:RANG:AUTO 1')
69+
log_all_events(tcp_socket)
70+
71+
# set Channel 1's Load Impedance to High and check for all events
72+
tcp_socket.send_scpi_command('SOUR1:PULS:CCOM 1')
73+
log_all_events(tcp_socket)
74+
75+
# set Channel 1's Rise Time to Fast and check for all events
76+
tcp_socket.send_scpi_command('SOUR1:PULS:RCOM 1')
77+
log_all_events(tcp_socket)
78+
79+
# set Channel 1's Ramp mode to Fast and check for all events
80+
tcp_socket.send_scpi_command('OUTP1:RAMP FAST')
81+
log_all_events(tcp_socket)
82+
83+
# Start the channel
84+
tcp_socket.send_scpi_command('OUTP1 ON')
85+
86+
# wait until Channel 1 is ready
87+
read_until_event(tcp_socket, 100) # event 100 is "Channel Ready"
88+
89+
# pulsing starts before before getting Channel Ready message
90+
# wait 30ms for getting ~10000 pulses
91+
time.sleep(0.030)
92+
93+
# disable Channel
94+
tcp_socket.send_scpi_command('OUTP1 OFF')
95+
96+
# disconnect from SpikeSafe
97+
tcp_socket.close_socket()
98+
99+
log.info("FixedPulseCountUsingSoftwareTimingExample.py completed.\n")
100+
101+
except SpikeSafeError as ssErr:
102+
# print any SpikeSafe-specific error to both the terminal and the log file, then exit the application
103+
error_message = 'SpikeSafe error: {}\n'.format(ssErr)
104+
log.error(error_message)
105+
print(error_message)
106+
sys.exit(1)
107+
except Exception as err:
108+
# print any general exception to both the terminal and the log file, then exit the application
109+
error_message = 'Program error: {}\n'.format(err)
110+
log.error(error_message)
111+
print(error_message)
112+
sys.exit(1)

0 commit comments

Comments
 (0)