Skip to content

Commit

Permalink
Added Calibration utility
Browse files Browse the repository at this point in the history
for more details please see README.md file
  • Loading branch information
Ladislav Foldyna committed Feb 21, 2018
1 parent cf266c2 commit 729e43b
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 0 deletions.
42 changes: 42 additions & 0 deletions utils/calibration/README.md
Original file line number Diff line number Diff line change
@@ -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.

93 changes: 93 additions & 0 deletions utils/calibration/calibration.py
Original file line number Diff line number Diff line change
@@ -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 <COM_Port>
#
# 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 <http://www.gnu.org/licenses/> and <http://www.apache.org/licenses/>.

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: <expected, frequency, raw_swr>
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()

0 comments on commit 729e43b

Please sign in to comment.