From 729e43becd6ba245731a5a106e767db54543e4a9 Mon Sep 17 00:00:00 2001 From: Ladislav Foldyna Date: Wed, 21 Feb 2018 14:57:25 +0100 Subject: [PATCH] Added Calibration utility for more details please see README.md file --- utils/calibration/README.md | 42 +++++++++++++++ utils/calibration/calibration.py | 93 ++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 utils/calibration/README.md create mode 100755 utils/calibration/calibration.py diff --git a/utils/calibration/README.md b/utils/calibration/README.md new file mode 100644 index 0000000..2d58089 --- /dev/null +++ b/utils/calibration/README.md @@ -0,0 +1,42 @@ +Based on the measurement, Analyzer did not provide accurate SWR results. The raw SWR +was very dependent on frequency and did not match an expected SWR. + +The raw SWR samples are shown below: + +Freq[Hz]/Expected SWR 1 1,5 2 3 4 7,8 20 +3000000 1,00517 1,14305 1,55263 2,43736 3,28571 6,40952 16,12222 +7000000 1,00504 1,14516 1,53968 2,38526 3,15544 5,93103 13,83333 +9000000 1,00482 1,15789 1,53251 2,32927 3,07463 5,6129 11,98413 +10500000 1,00442 1,14634 1,49639 2,24953 2,92593 5,20588 10,2755 +11500000 1,0042 1,13889 1,46739 2,14992 2,76547 4,77483 8,95402 +14000000 1,00386 1,1346 1,41396 1,97744 2,47143 3,88776 6,27692 +21000000 1,00377 1,1477 1,40177 1,90788 2,3211 3,41633 5,03364 +28000000 5,8951 1,1529 1,43052 2,02791 2,48699 3,83 5,8951 + +Therefore a calibration is highly recommended. It was tested many interpolation techniques with +various results. Very negative think was a strong frequency dependence. Therefore the +Antenna analyzer bandwidth (1-30MHz) was divided into the chunks - 30 chunks; 1per 1MHz + +After bandwidth splitting, it was possible to analyze the SWR curve and find a technique +for computing real (expected) SWR from raw SWR. The best interpolation result returned a polynominal +function order 3 + +Folowing formula shows how the rela SWR is computed by Antenna Analyzer. + +real SWR = coef3 * RAW_SWR^3 + coef2 * RAW_SWR^2 + coef1 * RAW_SWR + con + +where coef3..1 and con are pre-computed values for each chunk. The coefficients are computed by calibration.py +and have to be copy&pasted to arduino source code. + +What does the utility calibration.py do: + +1) calibration.py connects the Antenna Analyzer +2) User is asked to enter a calibration Load + example "500" means: user has connected 500 Ohm dummy load and calibration can start +3) calibration.py receives SWR values from Antenna Analyzer for every bandwidth chunk +4) User should repeat steps 2 and 3 with various dummy loads - recommended dummy load range is 50 - 1000 Ohm +5) If user enters an empty string then the utility computes the coefficients. +6) The coefficients are printed as C-array initialization structure. +7) The C-array initialization structure has to be copy&pasted to arduino source code - initialization part +8) The arduino source code has to be compiled and uploaded to Arduino. + diff --git a/utils/calibration/calibration.py b/utils/calibration/calibration.py new file mode 100755 index 0000000..29b37c9 --- /dev/null +++ b/utils/calibration/calibration.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 + +# Setup script for calibration Antenna Analyzer project +# the result should has to be inserted to Arduino source code + +# Usage +# ./calibration.py +# +# Copyright (C) 2018 Ladislav Foldyna +# Author: Ladislav Foldyna + +# This file is part of AntennaAnalyzer. +# +# AntennaAnalyzer is free software: you can redistribute it and/or modify +# it under the terms of either the Apache Software License, version 2, or +# the GNU Lesser General Public License as published by the Free Software +# Foundation, version 3 or above. +# +# AntennaAnalyzer is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# You should have received a copy of both the GNU Lesser General Public +# License and the Apache Software License. If not, +# see and . + +import sys +import serial +import numpy as np + +def main(): + all_samples = []; + + if ( len(sys.argv) < 2 ): + sys.stderr.write('Usage: {} COM_PORT\n'.format(sys.argv[0])); + sys.exit(1); + + com_port = sys.argv[1] + + try: + ser = serial.Serial(com_port, 57600) + except serial.SerialException as e: + sys.stderr.write('Could not open serial port {}: {}\n'.format(com_port, e)) + sys.exit(1); + + # when client establich an connection to arduino, arduino resets itself + # we will read booting characters but they are not important for calibration + + try: + while True: + arduino_answer = str(ser.readline(), 'utf-8').rstrip() + print(arduino_answer) + if ( arduino_answer.find('#OK#') >= 0 ): + break; + + # now calibration loop is starting + while True: + command = input("Enter Calibration Load: ") + + if (len(command) == 0 ): + break; + + command = command + 'f' + + #sending user command + ser.write(command.encode()) + + run_results = [] + + #reading SWR calibration samples + # format is: + while True: + arduino_answer = str(ser.readline(), 'utf-8').rstrip() + print(arduino_answer) + if ( arduino_answer.find('#OK#') >= 0 ): + break; + expected_swr, freq, swr = arduino_answer.split(',') + run_results.append([float(expected_swr), int(freq), float(swr)]) + + all_samples.append(run_results) + except serial.SerialException as e: + sys.stderr.write('Communication error {}\n'.format(e)) + sys.exit(1) + + #computing the coefficients + for i in range(0,30): + x = [b[2] for b in [item[i] for item in all_samples]] + y = [b[0] for b in [item[i] for item in all_samples]] + z = np.polyfit(x,y,3) + print("{ .do_correction = 1, .coef3 = %f, .coef2 = %f, .coef1 = %f, .con = %f}," % (z[0], z[1], z[2], z[3]) ) + +if __name__ == '__main__': + main()