Example_Powersupply_advanced

This is an example of using the library.

  1# %% ==========================================================================
  2# Import and Definitions
  3# =============================================================================
  4import datetime
  5import time
  6from dataclasses import dataclass
  7from typing import Any
  8
  9import matplotlib.pyplot as plt
 10import numpy as np
 11import pandas as pd
 12from tqdm import tqdm
 13
 14
 15@dataclass
 16class SourceCfg:
 17    name: str
 18    device: Any    # or a Protocol for your instrument API
 19    auto: bool
 20    channel: int | str
 21    set_voltage: float
 22    current_limit: float
 23
 24    def apply_startup(self) -> None:
 25        if self.auto:
 26            self.device.set_voltage(self.channel, self.set_voltage)
 27            self.device.set_current_limit(self.channel, self.current_limit)
 28
 29# Instrument Libraries Github: https://github.com/MartinMiroslavovMihaylov/Python_Instruments_Automation_Scripts
 30# Install with:
 31# pip install git+https://github.com/MartinMiroslavovMihaylov/Python_Instruments_Automation_Scripts.git
 32
 33# from Instruments_Libraries.GPP4323 import GPP4323
 34# from Instruments_Libraries.KEITHLEY2612 import KEITHLEY2612
 35from Instruments_Libraries.InstrumentSelect import PowerSupply_GPP4323, SourceMeter
 36
 37# %% ==========================================================================
 38# Select Instruments and Load Instrument Libraries
 39# =============================================================================
 40# myGPP4323 = GPP4323('COMXX') # noqa: N816
 41myGPP4323 = PowerSupply_GPP4323()  # noqa: N816
 42myGPP4323.reset()
 43
 44# myKEITHLEY2612 = KEITHLEY2612('COMXX') # noqa: N816
 45myKEITHLEY2612 = SourceMeter() # noqa: N816
 46myKEITHLEY2612.reset()
 47
 48# %% ==========================================================================
 49# Setup the Measurement
 50# =============================================================================
 51num_of_points = 10
 52sleep_time = 0.5
 53
 54DC_Sources: dict[str, SourceCfg] = {
 55    # dataclass name: SourceCfg(name, device, auto, channel, set_voltage, current_limit)
 56    "VCC":          SourceCfg("VCC", myKEITHLEY2612, True,  'a', 4.0,  0.310),
 57    "bias":         SourceCfg("bias", myGPP4323, True,  1, 2.9,  0.005),
 58}
 59
 60# %% ==========================================================================
 61# Configure the Instrument
 62# =============================================================================
 63# Keithly Sourcemeter needs to be setup as voltage source more specifically
 64myKEITHLEY2612.set_channel_display() # Display all channels
 65myKEITHLEY2612.set_output_source_function('a', "voltage")
 66myKEITHLEY2612.set_output_source_function('b', "voltage")
 67myKEITHLEY2612.set_display_measurement_function('a','amp') # measure current
 68myKEITHLEY2612.set_display_measurement_function('b','amp') # measure current
 69
 70
 71for source in DC_Sources.values():
 72    source.apply_startup() # apply startup, checks for "auto" internally
 73
 74# %% ==========================================================================
 75# Measurement
 76# =============================================================================
 77for source in DC_Sources.values():
 78    if source.auto: # if the source is set to auto
 79        source.device.set_output(source.channel, 'ON') # Turn on the channel
 80
 81records = [] # Empty list to store data and meta data
 82for idx in tqdm(range(num_of_points)):
 83    rec = {} # single record
 84    for source in DC_Sources.values():
 85        rec[source.name + "_Voltage"] = source.device.measure_voltage(source.channel)
 86        rec[source.name + "_Current"] = source.device.measure_current(source.channel)
 87        rec[source.name + "_Power"] = source.device.measure_power(source.channel)
 88
 89    rec["Timestamps"] = datetime.datetime.now()
 90    records.append(rec)
 91    time.sleep(sleep_time)
 92    temp = idx*np.pi # do something with idx
 93
 94# %% ==========================================================================
 95# Create Dataframe
 96# =============================================================================
 97meas_df = pd.DataFrame.from_records(records)
 98
 99# %% ==========================================================================
100# Plot the Measurement
101# =============================================================================
102t0 = meas_df["Timestamps"].iloc[0]
103relative_time = (meas_df["Timestamps"] - t0).dt.total_seconds()
104
105plt.plot(relative_time, meas_df["VCC_Current"])
106plt.xlabel('Time (s)')
107plt.ylabel('Current (A)')
108plt.show()
109# %% ==========================================================================
110# Save Dataframe
111# =============================================================================
112# Save DataFrame to HDF5 (better than CSV)
113meas_df.to_hdf("measurements.h5", key="data", mode="w")
114# key="data" is like a "dataset name" inside the HDF5 file 
115# (you can store multiple DataFrames in one file with different keys).
116# mode="w" overwrites the file. Use mode="a" if you want to append new datasets.
117
118# Later: Load it back
119loaded_df = pd.read_hdf("measurements.h5", key="data")
120print(loaded_df.head())
121
122#or
123
124# Save DataFrame to CSV
125meas_df.to_csv("measurements.csv", index=False)
126
127# Load it back, auto-parsing the "Timestamps" column as datetime
128loaded_df = pd.read_csv("measurements.csv", parse_dates=["Timestamps"])
129print(loaded_df.head())
130
131# %% ==========================================================================
132# Close Instrument
133# =============================================================================
134myGPP4323.Close()