Getting scales of captured signals

  • 5 Replies
  • 1184 Views
Getting scales of captured signals
« on: December 03, 2024, 06:35:25 PM »
I want to convert data captured using the Python API to floating point numbers representing volts.  I got the test script to work but it appears to return raw ADC data, not data scaled to volts.  Is there a way to get the scaling factors for each channel? It looks like sfGetYScaleA and sfGetYScaleB would be the correct function calls to to do this but they don't appear to be exposed to the Python API.

*

Dejan

  • *****
  • 149
    • View Profile
Re: Getting scales of captured signals
« Reply #1 on: December 04, 2024, 08:19:29 PM »
To convert raw ADC values to voltage with proper scale, calibration data needs to be read from onboard EEPROM first. Reading calibration data is not yet implemented in the API, but it can be done through the GUI application by selecting: "EEPROM -> Read Calibration". This will return JSON formatted data which contains board calibration data. After reading calibration data from EEPROM, this data will be saved to the "hardware2.json" file in "<software_installation_path>/data/startup/" folder. 

Note that there are two sets of calibration data: "calibratedNormal" values (for sampling speeds up to 250 MSPS) and "calibrated500Mhz" (for 500 MSPS).

To ensure the board is correctly calibrated, calibration data must be applied to the hardware registers.This includes offset (offsetsCh0, offsetsCh1) and gain values (gainValueCh0, gainValueCh1) depending on selected sampling speed and voltage range.

For example, if reading raw ADC values from CH1 at 1 V/div voltage range (and sampling speed is below 500 MSPS), the following calibration values must  be applied to corresponding hardware registers:
  • "calibratedNormal > offsetsCh0 > volt1" - this value must be applied to the CH1 offset register - this can be done with sfSetYPositionA function
  • "calibratedNormal > gainValueCh0 >  volt1" - this value must be applied to the CH1 gain register - this can be done with sfSetYRangeScaleA function

After applying calibration values to hardware registers, converting raw ADC values to voltages is straightforward with the following formula:
V = ADC_raw_value * voltage_range * number_of_divisions / 1024
** number_of_divisions is number of grid divisions which is 10

Example (for raw ADC value 162)...:  V = 162 * 1  * 10 / 1024 = 1,582 V

*I am working to provide an example Python script for reading calibration data and will include it here and in the software repository.

Re: Getting scales of captured signals
« Reply #2 on: December 04, 2024, 09:32:47 PM »
Thanks.  This gets me much closer.  A few follow up questions.

1.  How doI get/set the V/div voltage range?
2. Is number_of_divisions always 10?

Code: [Select]
# read the callibration data
with open(f"{scopefun_dir}/data/startup/hardware2.json") as f:
callibration_json = json.load(f)

# apply calibration to the hardware registers
voltage_range = "volt1"  # How do we get/set this?
ch0_offset = callibration_json["calibratedNormal"]["offsetsCh0"]["volt1"]
ch0_gain= callibration_json["calibratedNormal"]["gainValueCh0"]["volt1"]
ch1_offset = callibration_json["calibratedNormal"]["offsetsCh1"]["volt1"]
ch1_gain= callibration_json["calibratedNormal"]["gainValueCh1"]["volt1"]
sfSetYPositionA(scope.SHw, ch0_offset)
sfSetYRangeScaleA(scope.SHw, 0, ch0_gain)
sfSetYPositionB(scope.SHw, ch1_offset)
sfSetYRangeScaleB(scope.SHw, 0, ch1_gain)
sfHardwareConfig(scope.sfctx, scope.SHw)

*

Dejan

  • *****
  • 149
    • View Profile
Re: Getting scales of captured signals
« Reply #3 on: December 04, 2024, 09:40:30 PM »
Voltage range is determined with sfSetYRangeScaleA, sfSetYRangeScaleB.
Number of division is always 10.

Re: Getting scales of captured signals
« Reply #4 on: December 04, 2024, 10:26:03 PM »
OK, I think I got it.

Code: [Select]
        def set_voltage_range(self, voltage_range):
NUMBER_OF_DIVISIONS = 10
VOLTAGE_RANGES = [("volt2", 2.0),
                  ("volt1", 1.0),
                  ("mili500", 500e-3),
                  ("mili200", 200e-3),
                  ("mili100", 100e-3),
                  ("mili20", 20e-3),
                  ("mili10", 10e-3),]

for idx in range(1, len(VOLTAGE_RANGES)):
volts_per_div = VOLTAGE_RANGES[idx][1]
max_voltage = 10.0 * volts_per_div
if max_voltage < voltage_range:
break

# pick the previous range which fit the signal
idx -= 1
(voltage_range_key, voltage_range) = VOLTAGE_RANGES[idx]

# get the callibration data for this range
ch0_offset = self.callibration_data["calibratedNormal"]["offsetsCh0"][voltage_range_key]
ch0_gain = self.callibration_data["calibratedNormal"]["gainValueCh0"][voltage_range_key]
ch1_offset = self.callibration_data["calibratedNormal"]["offsetsCh1"][voltage_range_key]
ch1_gain = self.callibration_data["calibratedNormal"]["gainValueCh1"][voltage_range_key]

# set the hardware registers
sfSetYPositionA(self.SHw, ch0_offset)
sfSetYRangeScaleA(self.SHw, idx, ch0_gain)
sfSetYPositionB(self.SHw, ch1_offset)
sfSetYRangeScaleB(self.SHw, idx, ch1_gain)
sfHardwareConfig(self.sfctx, self.SHw)

*

Dejan

  • *****
  • 149
    • View Profile
Re: Getting scales of captured signals
« Reply #5 on: December 06, 2024, 03:10:49 PM »
Thanks for the code. I see you have used voltage_range input to select most appropriate range which is OK, but I have made some changes to allow only defined ranges. I also added separate adjustments for channels CH1 and CH2. There were some errors in the code which I also fixed. Note that  attr parameter in sfSetYRangeScaleA is used to select high/low gains and the attribute is  fixed for selected voltage_range (value of attr is defined in 'hardware.json' file).

Code: [Select]
def set_voltage_range(SHardware, CH1_voltage_range, CH2_voltage_range):
VOLTAGE_RANGES = [("volt2", 2.0, 0),
                  ("volt1", 1.0, 0),
                  ("mili500", 500e-3, 0),
                  ("mili200", 200e-3, 0),
                  ("mili100", 100e-3, 1),
                  ("mili50", 50e-3, 1),
                  ("mili20", 20e-3, 1),
                  ("mili10", 10e-3, 1)]

# Set CH1 gain and offset
try:
for idx1 in range(0, len(VOLTAGE_RANGES)+1):
if CH1_voltage_range == VOLTAGE_RANGES[idx1][1]:
(CH1_voltage_range_key, CH1_voltage_range, ch1_gain_attribute) = VOLTAGE_RANGES[idx1]
# get the Calibration data for this range
ch1_offset = calibration_data["calibratedNormal"]["offsetsCh0"][CH1_voltage_range_key]
ch1_gain = calibration_data["calibratedNormal"]["gainValueCh0"][CH1_voltage_range_key]
# set the hardware registers
sfSetYPositionA(SHardware, ch1_offset)
sfSetYRangeScaleA(SHardware, ch1_gain_attribute, ch1_gain)
break
except IndexError:
print("Err0: CH1 voltage range '{} V' is not defined.".format(CH1_voltage_range))

# Set CH2 gain and offset
try:
for idx2 in range(0, len(VOLTAGE_RANGES)+1):
if CH2_voltage_range == VOLTAGE_RANGES[idx2][1]:
(CH2_voltage_range_key, CH2_voltage_range, ch2_gain_attribute) = VOLTAGE_RANGES[idx2]
# get the Calibration data for this range
ch2_offset = calibration_data["calibratedNormal"]["offsetsCh1"][CH2_voltage_range_key]
ch2_gain = calibration_data["calibratedNormal"]["gainValueCh1"][CH2_voltage_range_key]
# set the hardware registers
sfSetYPositionB(SHardware, ch2_offset)
sfSetYRangeScaleB(SHardware, ch2_gain_attribute, ch2_gain)
break
except IndexError:
print("Err0: CH2 voltage range '{} V' is not defined.".format(CH2_voltage_range))
« Last Edit: December 06, 2024, 03:30:59 PM by Dejan »