def run(calibration_points, sample_count, adc_range, adc_resolution, invert, adc_channel, save): voltages = [ n / calibration_points * adc_range for n in range(calibration_points + 1) ] expected_codes = [ int(voltages[n] / adc_range * (adc_resolution - 1)) for n in range(calibration_points + 1) ] if invert: expected_codes = [adc_resolution - 1 - code for code in expected_codes] measured_codes = [] gem = gemini.Gemini() sol_ = sol.Sol() gem.enter_calibration_mode() gem.disable_adc_error_correction() sol_.send_voltage(0) for n in range(calibration_points + 1): voltage = n / calibration_points * adc_range print(f"Measuring {voltage:.3f}, expecting {expected_codes[n]}.") sol_.send_voltage(voltage) time.sleep(0.2) samples = [] for s in range(sample_count): samples.append(gem.read_adc(adc_channel)) result = statistics.mean(samples) print(f"Got {result:.1f}, diff {result - expected_codes[n]:.1f}") measured_codes.append(result) gain_error = adc_errors.calculate_avg_gain_error(expected_codes, measured_codes) offset_error = adc_errors.calculate_avg_offset_error(expected_codes, measured_codes, gain_error) print(f"Measured: Gain: {gain_error:.3f}, Offset: {offset_error:.1f}") corrected = adc_errors.apply_correction(measured_codes, gain_error, offset_error) corrected_gain_error = adc_errors.calculate_avg_gain_error(expected_codes, corrected) corrected_offset_error = adc_errors.calculate_avg_offset_error(expected_codes, corrected, corrected_gain_error) print(f"Corrected: Gain: {corrected_gain_error:.3f}, Offset: {corrected_offset_error:.1f}") if save: gem.set_adc_gain_error(gain_error) gem.set_adc_offset_error(int(offset_error)) print("Saved to NVM.") else: print("Dry run, not saved to NVM.") gem.enable_adc_error_correction()
def post_measure(self, value): if self._gain_error is None: return value return adc_errors.apply_correction(value, self._gain_error, self._offset_error)
def run( calibration_points, sample_count, adc_range, adc_resolution, invert, adc_channel, save, ): voltages = [ n / calibration_points * adc_range for n in range(calibration_points + 1) ] expected_codes = [ int(voltages[n] / adc_range * (adc_resolution - 1)) for n in range(calibration_points + 1) ] if invert: expected_codes = [adc_resolution - 1 - code for code in expected_codes] measured_codes = [] gem = gemini.Gemini() sol_ = sol.Sol() gem.enter_calibration_mode() gem.disable_adc_error_correction() sol_.send_voltage(0) for n in range(calibration_points + 1): expected = expected_codes[n] voltage = n / calibration_points * adc_range log.info(f"Measuring {voltage:.3f}, expecting {expected}.") sol_.send_voltage(voltage) time.sleep(0.1) samples = [] for s in range(sample_count): samples.append(gem.read_adc(adc_channel)) result = statistics.mean(samples) diff = result - expected_codes[n] if abs(diff) > 100: log.error( "ADC reading too far out of range. Expected {expected}, measured: {result:.1f}, diff: {diff:.1f}" ) log.info(f"Measured {result:.1f}, diff {diff:.1f}") measured_codes.append(result) gain_error = adc_errors.calculate_avg_gain_error(expected_codes, measured_codes) offset_error = adc_errors.calculate_avg_offset_error( expected_codes, measured_codes, gain_error ) log.info(f"Measured: Gain: {gain_error:.3f}, Offset: {offset_error:.1f}") corrected = adc_errors.apply_correction(measured_codes, gain_error, offset_error) corrected_gain_error = adc_errors.calculate_avg_gain_error( expected_codes, corrected ) corrected_offset_error = adc_errors.calculate_avg_offset_error( expected_codes, corrected, corrected_gain_error ) log.success( f"Expected after correction: Gain: {corrected_gain_error:.3f}, Offset: {corrected_offset_error:.1f}" ) local_copy = pathlib.Path("calibrations") / f"{gem.serial_number}.adc.json" local_copy.parent.mkdir(parents=True, exist_ok=True) with local_copy.open("w") as fh: json.dump({"gain_error": gain_error, "offset_error": offset_error}, fh) log.info(f"Saved local copy to {local_copy}") if save: gem.set_adc_gain_error(gain_error) gem.set_adc_offset_error(int(offset_error)) log.success("Saved to NVM.") else: log.warning("Dry run, not saved to NVM.") gem.enable_adc_error_correction() # Test out the new calibrated ADC log.info("Taking measurements with new calibration...") measured_codes = [] for n in range(calibration_points + 1): voltage = n / calibration_points * adc_range log.debug(f"Measuring {voltage:.3f}, expecting {expected_codes[n]}.") sol_.send_voltage(voltage) time.sleep(0.1) samples = [] for s in range(sample_count): samples.append(gem.read_adc(adc_channel)) result = statistics.mean(samples) log.info(f"Measured {result:.1f}, diff {result - expected_codes[n]:.1f}") if abs(diff) > 50: log.error( "ADC reading too far out of range. Expected {expected}, measured: {result:.1f}, diff: {diff:.1f}" ) measured_codes.append(result) gain_error = adc_errors.calculate_avg_gain_error(expected_codes, measured_codes) offset_error = adc_errors.calculate_avg_offset_error( expected_codes, measured_codes, gain_error ) log.success( f"Measured, corrected: Gain: {gain_error:.3f}, Offset: {offset_error:.1f}" ) log.success("Done") gem.close()