How to automate a calibration task - Page 1
Forum section: electronics / beginners

author: trilerian
author_rank: Regular Contributor
timestamp: January 19, 2025, 06:33:11 am
content: Ok, so one of my products I have to calibrate the voltage reading of the device. At the current point in time this is a very manual process, I hook up the device to my bench power supply, I look at the output of the device and I use my DMM to see the actual voltage. I adjust the voltage on the power supply, I put all this into an excel spread sheet and I create a linear curve. The voltage range this is used for is pretty small so the linear curve produces results +/- 2mV.Anyway, I would like to change this process and do the calibration with a custom application that I can launch from my PC. I ordered a small managed switch so I could hook up my power supply and DMM to a LAN network with my PC and I want to automate the entire thing. This will require controlling a Siglent SPD4121X to increment its voltage, serial output from my mcu onboard my product, and output from my Keithley DMM 6500. Dump into an excel sheet and create a best fit polynomial curve.Before I start going down the rabbit hole too far, is all this possible?

author: ledtester
author_rank: Super Contributor
timestamp: January 19, 2025, 06:48:39 am
content: Yes.My suggestion would be to do it with Python...- use pymeasure to control the DMM6500:https://pymeasure.readthedocs.io/en/latest/api/instruments/keithley/keithleyDMM6500.html- use PyVISA to control the Siglent:https://siglentna.com/operating-tip/spd-programming-tips/and here is an article on how to interact with a micocontroller over a serial interface:https://kevinmloeffler.com/2018/05/05/use-python-to-collect-and-save-data-from-microcontrollers-to-your-pc/

author: voltsandjolts
author_rank: Unknown
timestamp: January 19, 2025, 09:41:46 am
content: Quote from: trilerian on January 19, 2025, 06:33:11 amAll very achievable. As above reply I also recommend python for this task.

author: trilerian
author_rank: Regular Contributor
timestamp: January 24, 2025, 01:29:19 pm
content: I got my switch in and got all my equipment that have ethernet ports on the LAN. But I am having issues with the commands in pymeasure. I can connect to the DMM, I can create the object, I can get a voltage reading to print, but I can't set the auto range. If I use the command: dmm.measure_voltage() it automatically sets the range to 1V. I can use the command: dmm.auto_range(mode=None) followed by: print(dmm.voltage) and that will print the voltage to my display and keep auto range, but if I use the measure_voltage() it goes right back to 1V range. I have tried a few commands to try to set it, including passing a max voltage of 10V into the function, but no. Also setting mode = None seems to be the only mode that will work, I've tried voltage with no luck. And lastly, when I close the session I have to reboot my DMM to be able to control it locally again.

author: trilerian
author_rank: Regular Contributor
timestamp: January 28, 2025, 04:26:54 am
content: I had a chance to work on this a bit tonight. This is so cool, lol. Anyway, I have the code changing the output on the power supply and then reading the voltage with my dmm. I need to add the device I want to calibrate still and then after that figure out to to work the spread sheet. Anyway, here is my current code if anyone is interested in this. It really is kind of fun.Code:import pyvisaimport timefrom pymeasure.instruments.keithley import KeithleyDMM6500# Define the IP address for the Keithley DMMip_address_dmm = "IP Address"# Initialize the DMMdmm = KeithleyDMM6500(f"TCPIP::{ip_address_dmm}::inst0::INSTR")def main():try:# Initialize the VISA resource managerrm = pyvisa.ResourceManager()instadd = "TCPIP::IP Address::INSTR"inst = rm.open_resource(instadd)inst.write_termination = '\n'inst.read_termination = '\n'time.sleep(0.04)# Turn on the outputinst.write('OUTP CH1,ON')time.sleep(1)# Sweep through voltage settings and measure with DMMfor voltage in [3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 4.1, 4.2, 4.3, 4.4, 4.5]:inst.write(f'SOURce:VOLTage:SET CH1,{voltage}')time.sleep(1)dmm.auto_range() # Assuming this adjusts the range automaticallyprint(f"Voltage set to {voltage}V, DMM reading: {dmm.voltage}")# Turn off the outputinst.write('OUTP CH1,OFF')print(f"Measurements are done, closing connections")except Exception as e:print(f"An error occurred: {e}")finally:# Ensure the instrument connection is closedtry:inst.close()dmm.close()except NameError:pass # If inst was never initialized due to an earlier errorif __name__ == '__main__':main()

author: coromonadalix
author_rank: Super Contributor
timestamp: January 28, 2025, 05:53:32 am
content: with python on network ports, just a matter of opening them, send commands ..... i do it with a scope and a signal generator, no drivers needed at al, l not even use pyvisa in my caseit check the scope presence and generator presence and start doing "now" over 120 frequencies tests, it even control an small rs232 dual relay board (with mcu) to add an 50 ohms along 2/3 of the running testsand export everything in csv format. My biggest problems where Python versions, had to use older say 3.10 3.11 on x64 systems, the latest where failing on imported modules in python ?? (known bug)real time saver ... my 1st python coding loll and some code examples from Siglent

author: trilerian
author_rank: Regular Contributor
timestamp: February 04, 2025, 04:59:20 am
content: Quote from: coromonadalix on January 28, 2025, 05:53:32 amI'm still learning Python, lol. Well really I am still a new coder in general, while I now have about 2 years experience in hacking stuff together, it has mainly been Arduinoese. I just started a C++ course, so maybe some of that will stick.Anyway, here is my pretty much finished code if anyone else is interested, or maybe it could help someone else. The code uses PyVisa and PyMeasure as suggested in the first reply. Then it connects to the serial output of my MCU. It then steps through the voltage range I care about and takes the DMM reading followed by the MCU reading. The code outputs to an excel file and calculates a 2nd order polynomial to fit the voltage output of the MCU to the DMM. I can then use that to correct the output. Although I will say I am getting about the same deviation after correction as I was getting with my linear approximation. Roughly 1-2mV.Code:import pyvisaimport timeimport serialimport pandas as pdimport numpy as npfrom pymeasure.instruments.keithley import KeithleyDMM6500# Define the IP address for the Keithley DMMip_address_dmm = "xxx.xxx.xxx.xxx"# Initialize the DMMdmm = KeithleyDMM6500(f"TCPIP::{ip_address_dmm}::inst0::INSTR")# Initialize Serialser = serial.Serial('COMX', 115200)# Initialize data storagedata_log = []cell_voltages = []dmm_readings = []def main():try:time.sleep(1)# Initialize the VISA resource managerrm = pyvisa.ResourceManager()instadd = "TCPIP::xxx.xxx.xxx.xxx::INSTR"inst = rm.open_resource(instadd)inst.write_termination = '\n'inst.read_termination = '\n'# Turn on the outputinst.write('OUTP CH1,ON')inst.write(f'SOURce:VOLTage:SET CH1,(3.0)')time.sleep(1)# Sweep through voltage settings and measure with DMMfor voltage in [3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 4.1, 4.2, 4.3, 4.4, 4.5]:inst.write(f'SOURce:VOLTage:SET CH1,{voltage}')time.sleep(0.10)dmm.auto_range() # Adjusts range automaticallydmm_reading = dmm.voltage # Read voltage from DMMdata = ser.readline().decode('utf-8').strip() # Read serial data# Convert serial data to float if possibletry:cell_voltage = float(data)except ValueError:cell_voltage = None # Skip if invalidif cell_voltage is not None:cell_voltages.append(cell_voltage)dmm_readings.append(dmm_reading)else:print(f"Invalid data received: {data}")print(f"Voltage set to {voltage}V, DMM reading: {dmm_reading}V, Cell Voltage: {cell_voltage}")# Append data to logdata_log.append({"Set Voltage (V)": voltage,"DMM Reading (V)": dmm_reading,"Cell Voltage": cell_voltage})time.sleep(1)# Turn off the outputinst.write('OUTP CH1,OFF')print("Measurements are done, closing connections")except Exception as e:print(f"An error occurred: {e}")finally:# Ensure the instrument connection is closedtry:inst.close()dmm.close()except NameError:pass # If inst was never initialized due to an earlier error# Compute the best-fit polynomialif cell_voltages and dmm_readings:poly_degree = 2 # Adjust degree as needed (linear = 1, quadratic = 2, etc.)coefficients = np.polyfit(cell_voltages, dmm_readings, poly_degree)polynomial = np.poly1d(coefficients)print(f"Polynomial Fit: {polynomial}")# Apply the correction to measured valuescorrected_values = [polynomial(v) for v in cell_voltages]# Add corrected values to logfor i in range(len(data_log)):data_log["Corrected Cell Voltage"] = corrected_valueselse:print("No valid data for polynomial fitting.")# Save data to an Excel filedf = pd.DataFrame(data_log)df.to_excel("measurement_results_with_polynomial.xlsx", index=False)print("Data saved to measurement_results_with_polynomial.xlsx")if __name__ == '__main__':main()

author: ledtester
author_rank: Super Contributor
timestamp: February 04, 2025, 04:22:23 pm
content: Great to see that you got the setup working!Just two things about the code that I noticed...- you can move the dmm.auto_range() outside the for loop -- although this isn't a big deal- with regards to this line:Code:for voltage in [3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 4.1, 4.2, 4.3, 4.4, 4.5]:you may be interested in this discussion:https://stackoverflow.com/questions/7267226/range-for-floats