Easy DIY Yagi Antenna for VHF/UHF Amateur Radio Bands

Build a 3-element Yagi-Uda antenna for 2 meter and 70 cm Amateur Radio bands with low-cost common building materials from your local hardware supply store. This antenna requires no extraneous impedance-matching components or complex tuning procedure. Just follow the construction outline here and in a couple of hours you’ll be on-the-air with a high-performance antenna.

Design

As an FCC licensed radio amateur I take great pride and satisfaction in designing and building my own antennas (antennae). This is my first Yagi antenna project. I was intrigued by the idea of passive elements creating directional gain and the wide variety of possible performance optimizations. This antenna was designed with the following goals in mind.

  • Intrinsic 50 ohm feed point impedance for maximum efficiency and to avoid the necessity of adding an impedance-matching network or using an antenna tuner.
  • Quick breakdown of the antenna for easy storage and portability.
  • Durable for low maintenance long term outdoor deployment.

EZNEC application program was used to simulate the antenna design. 4NEC2 could also be used but EZNEC is EZ. Some Yagis are built with the element centers electrically shorted to a conductive Boom (and each other). But here the Boom is made of PVC so the elements are insulated from the Boom. Following my intuition, I iterated element length and spacing values to optimize for a 50 ohm feedpoint impedance. These dimensions are shown in the table and diagram below.

(meter)DirectorDriven ElementReflector
Cu Length0.79960.4590 (2pcs.)1.0040
Spacing-0.256700.2567
Easy Yagi Element Length and Spacing Dimensions (Meters)
Easy Yagi mechanical drawing

Simulation Results

Azimuth plot indicates a forward gain of 12 dBi with Front/Back gain of 21.5 dB and 67 degrees Beamwidth at 146MHz.

Horizontal elevation at maximum gain is 4.5 degrees. This certainly seems strongly directional to me. In the SWR plot below, the impedance vector Z is 45+i0.84 ohms at 146 MHz which is close to 50 Real ohms. SWR is about 1.1:1 throughout the entire 2m band (144-146MHz). More than 98% of power is radiated.

SWR Plot

Testing and Validation

Using a NanoVNA Vector Network Analyzer, a Smith Chart and SWR plot were captured for both the 2meter and 70cm bands. Colored markers 1,2,3 show the min, mid, max extent of each band. The optimal 2m SWR frequency corresponded well with the simulation even though an SWR of 1.1 was not achieved. Even so the measured SWR is better than 1.5:1 throughout the band which is 97% efficient and “good enough”. The broad SWR bandwidth is attributed to the relatively thick (1/2″) Copper pipe elements.

2 meter frequency sweep Smith Chart and SWR plot
70 cm frequency sweep Smith Chart and SWR plot

I connected the antenna to my Handy Talky (HT) transceiver and contacted several repeaters and received good signal reports. Even in the Yagi horizontal orientation I was using less than 2 Watts to engage repeaters. By rotating the Yagi from side-to-side horizontally I could hear static noise rise and fall, thus demonstrating some directional gain variation.

Materials

The table below details a shopping list with estimated prices to build one antenna. Everything but the SO-239 UHF coax connector can be found at your local hardware store. At a cost of just $36 you can’t go wrong.

Qty. DescriptionUnit Price ($)Ext. Price ($)
13/4″ x 10 ft. PVC Class 200 pipe2.312.31
33/4 x 3/4 x 3/4″ Tee coupler0.832.49
13/4″ Cross coupler2.842.84
63/4″ – 1/2″ Reducer Bushing with internal threads, Model #C438-1010.834.98
11/2″ x 10 ft. Copper Pipe, Type M11.2711.27
21/4″-20 x 2.5″ Stainless Phillips Pan Head Screw (1×2 pack)1.181.18
61/4″-20 Stainless Hex Nut (3×2 pack)1.183.54
2#8 x 1″ Phillips Pan Head Stainless Steel Sheet Metal Screw (1×2 pack)0.800.80
18″x10″ Clear Non-Glare Acrylic Sheet3.383.38
1SO-239 Panel Mount UHF-Female Coaxial Connector2.492.49
Total35.28
Shopping List for Easy Yagi materials

Build Process

  • Separate the 2 driven element pipe pieces by 1″. Drill 2 holes 1.5″ inches about the center (3/4″ either side) of the PVC Cross fitting for 2 #8 sheet metal screws which connect the signal wires to the Copper pipe.
  • I left the PVC pipe fittings unglued for easy take down purposes. The natural friction of assembly seems strong enough for permanent deployment.
  • The SO-239 UHF connector is mounted on Plexiglass sheet (2″x 4″) and held in place by a pair of 1/4″-20 x 2.5″ screws. A pair of nuts serve as spacers on each end.
Easy Yagi Antenna Electrical Connections Photo
Easy Yagi Electrical Connection Interface

Discussion

My first attempt to design and build a Yagi-Uda antenna turned out well. I was surprised to discover the 70cm band workable, while this makes sense since 70cm is the 3rd harmonic of the 2m band, the simulation did not hold promise. But sometimes you get lucky if you try. You too can build this 3-element Yagi antenna without fancy test equipment by using accurate dimensional measurements and good construction technique.

References

Basic Antennas by Joel Hallashttps://www.arrl.org/shop/Basic-Antennas/
A 4-element 2m homemade Yagi antenna https://www.youtube.com/watch?v=M6y6ecQDhh0
EZNEC Demo v6.0 application download. https://www.eznec.com
Original U.S. Bureau of Standards Yagi info 1976https://nvlpubs.nist.gov/nistpubs/Legacy/TN/nbstechnicalnote688.pdf
NanoVNA infohttps://nanovna.com

Renegade Home

2010 U.S. Census Data for Postgresql

Census data published by the U.S. Census Bureau is not readily transformed for Relational Database Management System (RDMS) insertion. Here we provide an archive file to create a United States 2010 Census Short Form 1 (SF1) relational database for my favorite open source RDMS PostgreSQL. Check back here for 2020 Census updates, coming soon.

Database Features

Census Bureau instructions pertain to Microsoft Access 2007 database creation but then only to separate databases for each state. Here we create data tables that combine all 50 states (plus District of Columbia and Puerto Rico). Tables are inked with a PRIMARY KEY defined on stusab (state) and logrecno. An example table definition appears below.

create table sf1_00001 (
fileid varchar(510),
stusab varchar(510),
chariter varchar(510),
cifsn varchar(510),
logrecno integer,
p0010001 integer,
PRIMARY KEY (logrecno, stusab)
);

Restoring the DB

Download link (11GB): Census_2010_sf1_pg This 2010 Census PostgreSQL database archive was created with the following Pg commands:

pg_dump -Fc -f /archive/Census_2010_sf1_pg -d sf1_2010r &

The pg_dump custom format (-Fc) allows flexibility to restore one or more objects. The database user is not saved so you can easily restore your own user. The following Pg commands will restore the database.

createdb sf1_2010r
pg_restore -Fc -d sf1_2010r -v < Census_2010_sf1_pg

The size of the final database is 230GB, so be prepared.

Testing

Try this query at the psql prompt:

select sf1_00003.stusab as “State”,
sf1_00003.p0030001 as “Population”,
geo_header_sf1.geocomp,
geo_header_sf1.logrecno
from geo_header_sf1,sf1_00003
where geo_header_sf1.sumlev=’040′ and
geo_header_sf1.geocomp = ’00’ and
geo_header_sf1.logrecno = sf1_00003.logrecno and
geo_header_sf1.stusab = sf1_00003.stusab
order by “Population” desc;

If everything is working, you should see all 50 states (+DC, PR)

State | Population | geocomp | logrecno
——-+————+———+———-
CA | 37253956 | 00 | 1
TX | 25145561 | 00 | 1
NY | 19378102 | 00 | 1
FL | 18801310 | 00 | 1
IL | 12830632 | 00 | 1
PA | 12702379 | 00 | 1
OH | 11536504 | 00 | 1
MI | 9883640 | 00 | 1
GA | 9687653 | 00 | 1
NC | 9535483 | 00 | 1
NJ | 8791894 | 00 | 1
VA | 8001024 | 00 | 1
WA | 6724540 | 00 | 1
MA | 6547629 | 00 | 1
IN | 6483802 | 00 | 1
AZ | 6392017 | 00 | 1
TN | 6346105 | 00 | 1
MO | 5988927 | 00 | 1
MD | 5773552 | 00 | 1
WI | 5686986 | 00 | 1
MN | 5303925 | 00 | 1
CO | 5029196 | 00 | 1
AL | 4779736 | 00 | 1
SC | 4625364 | 00 | 1
LA | 4533372 | 00 | 1
KY | 4339367 | 00 | 1
OR | 3831074 | 00 | 1
OK | 3751351 | 00 | 1
PR | 3725789 | 00 | 1
CT | 3574097 | 00 | 1
IA | 3046355 | 00 | 1
MS | 2967297 | 00 | 1
AR | 2915918 | 00 | 1
KS | 2853118 | 00 | 1
UT | 2763885 | 00 | 1
NV | 2700551 | 00 | 1
NM | 2059179 | 00 | 1
WV | 1852994 | 00 | 1
NE | 1826341 | 00 | 1
ID | 1567582 | 00 | 1
HI | 1360301 | 00 | 1
ME | 1328361 | 00 | 1
NH | 1316470 | 00 | 1
RI | 1052567 | 00 | 1
MT | 989415 | 00 | 1
DE | 897934 | 00 | 1
SD | 814180 | 00 | 1
AK | 710231 | 00 | 1
ND | 672591 | 00 | 1
VT | 625741 | 00 | 1
DC | 601723 | 00 | 1
WY | 563626 | 00 | 1
(52 rows)

References

  1. Census Bureau data set
  2. 2010 Census Summary File 1 technical documentation.

LED Christmas Tree 328

Strange things happen during a pandemic shutdown. For some reason, being stuck inside, I got the urge to prepare Christmas gifts for my friends and relatives. I have built LED Christmas Trees for many years from kits and original designs. Here is the latest revision for 2020.

LED Christmas Tree
Finished Tree

General Description

As shown in photo above the LED Christmas Tree consists of a green printed circuit board in the outline shape of a tree decorated with 16 LEDs. A microphone responds to ambient sound to effectively clock a microcontroller (MCU) executing different LED sequence patterns. The unit is powered by a 6VDC, 600mA AC adaptor (wall wart). Overall Dimensions: 6″Hx4″Wx2″D

Features

The ATmega328P microcontroller (MCU) in a 28L DIP package controls the LED action. The Arduino Uno uses this same MCU and indeed the firmware was developed in the Arduino environment.

  • An Electret Microphone connects to the MCU Analog Comparator (AIN0/AIN1) to detect sound and animate the LEDs.
  • A 16 bit Linear Feedback Shift Register (LFSR) creates a Maximal Length Pseudo Random Bit Stream (PRBS) dynamic LED sequence. This produces an eye-catching pattern as the bits shift in order around the 16 LEDs.
  • If no sound is detected for 30 seconds all the LEDs turn off and the Tree enters a low-power stealth mode, ready to resume execution at the next sonic vibration.
  • All through-hole component technology makes or easy assembly. Socketed integrated circuits enable firmware updates. Unit cost is $40-60 depending on quantities.

Hardware

The ATmega328P microcontroller (MCU) in a 28L DIP package controls the LED action. The Arduino Uno uses this same MCU and indeed the software was developed in the Arduino environment.

The Printed Circuit board was manufactured by ExpressPCB and designed using their FREE CAD tools. I used my home shop band saw with a fine toothed blade to cut out the Tree profile.

Microphone Circuit

As shown in the diagram below the electret microphone output is capacitively coupled to a linear op-amp IC (LM358). An LM358 op-amp is biased with 5K ohm resistors producing a voltage gain of 2x, so it mainly functions as an impedance buffer. But this is enough signal to trip the Analog Comparator (AIN0,AIN1). The circuit is shown below.

Microphone Circuit
Electret Microphone Interface Circuit

Firmware Sketch

This sketch is short and very simple, only 1900 bytes are flashed (about 4% of available program and variable space). All the LED dynamics are driven by two Interrupt Service Routines (Analog Comparator and Timer1).

Software Functional Block Diagram

Each time an Analog Interrupt occurs an interrupt counter is incremented. This value, depending on the range, decides which sequence subroutine to execute. The sequence subroutine operates like a Finite State Machine where each call advances the sequence by one clock tick. The LFSR sequence is generated algorithmically but other patterns are defined by a multi-dimensional array. The first dimension defines the sequence step while the second dimension lists the LEDs to turn off and on. A multi-dimensional array allows the programmer to create any LED sequence, in a straight forward manner, limited only by your imagination and MCU memory size.

Timer1 is the MCU’s only 16 bit timer (max. value is 65535 counts). When a timeout occurs all the LEDs are turned off. In order to achieve a 30 second timeout delay, the CPU clock was divided by 16 making the internal CPU clock frequency 1MHz. To avoid premature timeout Timer1 is reset every time an Analog Comparator interrupt occurs.

The sketch includes 5 canned LED sequences and debug compile options for using the Arduino Serial Monitor. Many debug problems required stand-alone, real-time operation without the Serial Monitor.

LFSR

A Linear Feedback Shift Register (LFSR) is a logic configuration often applied in cryptography and authentication, random number generation, logic testing, communications coding, decoding and error correction.

There are 2 main LFSR configurations. In Fibonacci LFSRs, 2 or more Q outputs are Xor’d (logic exclusive OR) to generate feedback (externally) to the first input stage (D0). The other type, named after Evariste Galois, inserts Xor’d feedback (internally) between the D-flop stages.

By taping different output stages for feedback we can create different sequences with different run lengths. With proper choice of feedback stages we can create a Maximal Length Sequence with a run length of 2^n -1 combinations.

Example: 4 bit LFSR

With feedback taps chosen from Q0, Q3, this 4 bit LFSR generates a Maximal Length PRBS of 15 combinations (2^4 – 1).

4 bit LFSR
4 Bit LFSR for PRBS
tD0D1D2D3feedback
011110
101111
210110
301011
410101
511010
601100
700111
810010
901000
1000100
1100010
1210001
1311001
1411101
151111Repeat
160111Repeat
Maximal Length 4-bit LFSR State List

If we count the number of consecutive 1’s and 0’s we find that 1/2 are 1 bit, one-quarter are 2 bits, one-eight are 3 bits etc. up to 1/(2^n) are n bits wide. Thus the distribution nearly equals the statistical expectation value for a truly random distribution.  This type of analysis is shown for our 4 bit LFSR in the Table 2 below. Some difference between Actual versus Ideal Probability Expectation is noted, however for wider LFSRs, with more states, these Expectation values are very close. This is what gives a PRBS its pseudo random quality.

width=
length
4
15
bits
combos.
Random
Prob. Expectation
 
Bit PatternRun Len.#Occur.ActualIdeal
‘b1120.250.25
‘b11210.1250.125
‘b111310.1250.0625
‘b11114000.0625
‘b0120.250.25
‘b00210.1250.125
‘b0003000.0625
‘b0000410.1250.0625
A 4-bit LFSR Statistical Expectation

Stream Cipher

Suppose we want to encrypt the message ‘HI’ which is ASCII Capital ‘H’ (‘b0100 1000) and ASCII Capital  ‘I’ (‘b0100 1001). This makes our Plaintext = ‘b0100100001001001.

Select a 16 bit Key from Table 1, e.g. column D0 from t = 2  to 16 i.e. Key = ‘b1011001000111101. To encode the message, Xor each bit of Plaintext with the corresponding bit of Key. Remember that Xor is like binary addition (without the carry bit).

Encrypt (Encode)

Generate Ciphertext by Xor’ng Key with Plaintext

t0123456789101112131415
Key1011001000111101
Plaintext0100100001001001
Ciphertext1111101001110100

Decrypt (Decode)

Restore Plaintext by Xor’ng original Key with Ciphertext

t0123456789101112131415
Key1011001000111101
Ciphertext1111101001110100
Plaintext0100100001001001

Of course this is a trivial example (so you can follow along). If the key (initial state) were much wider, say 256 bits, the number of possible keys would be 1E+77. If you tried cracking the cipher by guessing 100 trillion keys per second it would still take 2.5E+47 universe lifetimes to try every possible key. Chances of success are very low.

Assembly

To perform the necessary ATmega328P programming I modified an Arduino Uno by replacing the 28 lead MCU DIP (Dual Inline Package) with a narrow 28L ZIF (Zero Insertion Force) socket, and built the Adafruit 462 Standalone AVR ISP Programmer Shield Kit to program bootloaders into raw MCU ICs.

Programming Tools
MCU Programming Tools

Conclusion

This was a satisfying project because it created unique Christmas gifts for my relatives and friends. Children especially, enjoy the voice/audio interaction. No doubt my relatives will not be satisfied unless my next revision is controlled by a Smartphone App and automatically uploads data to the Cloud for real time ambient noise analysis. I kept one Tree for myself to set on my piano so I can entertain guests with a multi-media performance of Christmas Carols.

Programmers are invited to play with LED sequences, switching delays and add digital filters or other functionality.

Building this standalone MCU project extended my development skills in the Arduino environment. 10 Tree units were assembled with 100% yield.

development platform
Development Platform

References

COVID-19 Mortality Risk Given a Positive Diagnosis

Bayes Theorem for conditional probability is applied to Oregon Health Authority COVID-19 reports to calculate the probability of death (Mortality Risk) given a positive infection test result. This same statistical method is commonly used in cancer and pre-employment drug screening. Latest data is available at OHA.

Executive Summary

As of 5/16/20, In Oregon’s population of cases attributed to COVID-19 infection, the probability of death for those testing positive is estimated to be 1.67%. Strangely, more COVID-19 dead patients test negative (78) than positive (59). Also, the probability of false positive (3.77%) is relatively high compared to false negative (0.08%). This begs the question, are so many false positive deaths really due to the virus?

Bayesian Definitions

Empirical Data

Scarce testing resources may not accurately sample asymptomatic infections, in which case the mortality risk here is exaggerated.

Joint Probability Distribution

Renegade Stanton Stools

A pair of Stanton Stools is designed and built from low-cost construction lumber using normal woodshop power tools (band saw, wood lathe and drill press). I was inspired to build these stools from an American Woodshop episode here featuring Chad Stanton making his Stanton Stools using hand tools only. Mr. Stanton provides some useful design guidelines but leaves it up to the woodworker to create their own work of art.

Motivation

Like many woodworkers I aspire to build wooden chairs because I regard chair-building  as a high form of the woodworking art. This project is an ideal way to build necessary skills for building chairs (especially Windsor chairs) and yields some useful furniture that I will donate to my nieces’ families.

For about $12 I purchased 1 piece of 2″ x 12″ x 10 ft. of Douglas Fir dimensioned construction lumber to build 2 stools. I’m a sucker for  woodworking projects that use minimum materials but yield maximum utility from simple design and construction.

Design

The stools were crafted to have a rustic, textured look. Like they were carved with an axe and retrieved from an old  barn. The taller stool is 23″ and the shorter stool 17″ in height (typical chair seat height). The splay of the legs (vertical leg angle) was 9 degrees.

Construction

As mentioned in Stanton’s video, it is wise to label individual components and orient the leg end grain to be parallel to the seat grain. Hopefully this alignment allows the pieces to expand and contract together to minimize stress during seasonal humidity changes.

Stool Parts
Stool component pieces before glue-up, labelled with blue painter’s  tape

Angle Jig

Angle Jig
9 degree Angle Jig for boring seat holes and leg mortises

Normally chair-making requires a lot of cutting patterns and jigs to achieve the subtle angles. Here one jig provides an angle to bore the seat and legs. Typical angles are 8, 9, 10 degrees. For an angle of 9.04 degrees Side a=1 3/4″, Side b=11″, as shown below

Angle jig
9 degree angle jig for seat holes and leg mortises

Tenon Measuring Tool

Being a novice at the lathe I had trouble sizing lathe tenons to fit a mortise snugly. This was attributed to my poor measurement technique using (flimsy) calipers. So I created the tool below by boring 1/2, 5/8, 3/4, 7/8, 1 and 1 1/4″ holes along a common center line and cutting precisely through the centers. This tool proved easy to use and very accurate. If a tenon fit well here, it made for a strong glue joint. A great tool for future chair-making.

Tenon Tool
Tenon measuring tool made from 1″ thick oak

I recommend using Titebond Extend wood glue for its longer open time. The stools are finished with Shellac, Cherry Stain and several coats of Polyurethane

Conclusion

This was a fun and worthwhile woodworking project. I progressed my woodworking skills and the stools I made are strong and light and should last a lifetime with my nieces’ families. For my next round of Stanton Stools I would probably forego the seat’s through-hole tenons in favor of a recessed mortise yielding a smoother seat.

Finished Stools
Finished Stools tall (23″) and short (17″)

A 6 Meter SlimJim Ladder Line Antenna Designed with NanoVNA

This blogpost describes the design, construction and performance of a home-made DIY 6 meter (50MHz) SlimJim type amateur radio antenna made from 450 ohm Ladder Line (aka Window Line, Balanced Line, Open Wire, Twin Lead ). This Ladder Line material is typically purposed to connect a radio transmitter or receiver to an antenna (as a transmission line) but here it is made into the actual antenna. A NanoVNA Vector Network Analyzer measurement instrument aids in design and evaluation of antenna characteristics. The Slim Jim is a variant of the J-pole antenna. J-poles are very  popular among radio amateurs because they are easy to make from common, low-cost hardware store materials and because they perform well. This antenna can be used in a permanent or stealthy portable installation.

Motivation

As an amateur radio operator I take great pride in designing and  building my own antennas (antennae?). Amateur radio is the only class of broadcast license that the FCC privileges in this way. Currently my amateur radio station transmits on the 40-20-15-10 meter HF bands as well as VHF (2 meter) and UHF (70 cm) frequencies.  Through my HF antenna tuner I’m able to switch in this additional antenna for 6 meters. Also, because this antenna is lightweight, it can be hung from a tree to fit nicely in my backyard.

Antenna Design

The website M0UKD offers a handy J-pole/SlimJim calculator. This page reveals formulas for calculating dimensions. The only required user inputs are frequency and velocity factor. Velocity factor relates to the antenna dielectric material, in this case JSC #1318 450 ohm ladder line sold in my local Ham Radio Outlet at $0.70 per foot. The velocity factor (Vf) for this cable is specified as 0.91 (91%) here. However I decided to measure it myself using my NanoVNA.  This method gave me a value of Vf=0.90 (90%). Entering the lowest band frequency(50MHz) and slowest Vf (0.90) gave me some margin for element fine-trimming later. The resulting element dimensions are shown below.

SlimJim vs. J-Pole Diagram image
SlimJim vs. J-pole Configuration Diagram

M0UKD Antenna Calculator
6 Meter Antenna Dimensions from M0UKD Calculator Webpage

Choke Balun

A choke balun is commonly recommended for j-pole type antennas and it makes sense to me to stifle any common mode current. The transmission line is not intended to be a radiating element. I made this choke balun from Shireen rfc100a 50 ohm coax. About 5ft of coax is coiled 4 times through 4 TDK ZCAT 2035-0930 snap-on ferrite core inductors. I was proud of myself for combining 2 types of choke balun into one (coiled transmission line and ferrite core). A photo is below.

Choke Balun
Choke Balun made from coiled coax cable and snap-on ferrite cores.

Antenna Construction

I tried to position the ladder line to avoid cutting insulting dielectric which forms the mechanical support for the parallel wires but the required 6 cm Gap is longer than any “closed window”. This left a good part of the antenna hanging by only one #18 steel wire. To provide more structural support I cut out a length of insulation from excess material and glued it in place of the missing webbing. Since the dielectric material is polyethylene a special bonding adhesive (Loctite Plastics Bonding System with an activator pen and glue tube) was required. This proved very effective.

Ladder Line Patch
Gap Patch Glued on Ladder Line

  • I measured and cut the different wire lengths to within 1/16 inch of the metric equivalent.
  • The steel wire is brittle. When forming the ends (shorting the 2 wire conductors), bend with a large radius (1/4″) using needle-nose pliers.
  • Plastic zip ties were used to hold up Choke Balun and provide strain relief for transmission line coax.
  • The outer shielded part of the unbalanced coax transmission line connects to the longest element.

I was much gratified to see my new antenna resonating close to the design goal on the very 1st try, proving M0UKD’s calculator to be very accurate.

To find the optimum 50 ohm feed point I connected my NanoVNA to the antenna via a 6″ length of SMA coax with the inner and outer conductors separated. Then using a hand clamp to press the wire connection, I moved the connection point up and down the feedpoint area while measuring VSWR.  I targeted a VSWR minimum for the lower end of the 6m band (between 50 and 52 MHz) and determined that 15 instead of 13.5 cm (design target) was best. My target VSWR and the final field-installed (with balun, 50ft RG-8X coax) VSWR is shown in NanoVNA graphic below.

VSWR target vs. acutual
Target VSWR (blue) versus finished, installed antenna VSWR (brown)

I was not terribly disappointed that VSWR shifted higher but still maintained a ratio < 2:1 throughout the 6m band (50-54MHz).

NanoVNA

I used a VNA in my work and often fantasized about owning one for my home shop/lab. Recently I found this new (to me) device that’s great for the RF builder. Some featured points:

  • Cost: ~$45. Complete kit includes calibration standards, much cheaper than a commercial Antenna Analyzer.
  • Wide frequency range: 50KHz – 900MHz (covers HF, VHF, UHF amateur bands and more, like 2.2Km, 630m amateur bands)
  • Has 2 ports for S11 return and S21 through measurements (think filters)
  • The unit comes with a color touch screen but it’s much easier to  use the FREE and very capable NanoVNA-saver application software.
  • Powered through USB cable or internal rechargeable batteries

I used my NanoVNA to measure conductor velocity factor and VSWR through the major stages of construction, balun, transmission line and installation.

Conclusion

My new antenna performs well as I’ve made numerous QSO contacts across several states. I was concerned that the balun coax wouldn’t transmit my transceiver’s full  power (100W)  but I calculate a current of 1.414A ((100W/50ohm)^0.5=1.4A) which is not excessive. I’ve routinely run 80W. Here’s a photo in all it’s glory.

6m antenna photo
6m Ladder Line SlimJim antenna, hung from a tree branch, standing 14ft. tall.

Construction is simple and cheap ($60) and any ham radio operator will get a lot of use in a permanent or portable application.

Bill of Materials

Total cost less than $60

WordPress Shortcode Dynamic Tables

I searched high and low for a WordPress plugin to display dynamic table data from my databases on my WP sites. I store a lot of data, with frequent updates, using the Postgresql relational database management system (RDMS). This post explains using WordPress shortcodes to query a database and display table data so your posts are always current. Tables can be displayed inline anywhere in posts and pages where you can insert a shortcode. This method was developed on a site running the Gutenberg block editor (WP v5.2.1 ) so don’t be shy, give it a try.

Custom shortcode functions could be developed as a simple plugin but I chose to add this PHP shortcode function in the functions.php file of my child theme. The HTML output defines a CSS class i.e. <table class=”pg_table_query”> for easy styling to compliment your theme.

The pg_table_query shortcode takes 2 arguments; (1) sql query and (2) text title displayed as a table caption.  An example Gutenberg shortcode entry is shown below.

example shortcode block entry

Loading the page/post produces the table shown below. CSS styling, also in the child theme, centers the table caption and highlights header data.

table generated from database using shortcode

The shortcode function pg_table_query_func coded in PHP below is written in the functions.php file of my child theme.

function pg_table_query_func($atts) {
$atts = shortcode_atts (
array(
‘sql’ => ‘select * from quote_day_r;’,
‘title’ => ‘table title’
), $atts, ‘pg_table_query_func’ );
$host = “host=db_host”;
$port = “port=5432”;
$dbname = “dbname=my_db”;
$credentials = “user=db_user password=my_pwd”;
$output=”;

$db=pg_connect( “$host $port $dbname $credentials”) or die (“no database connection”);
$ret = pg_query($db, $atts[‘sql’]) or die (“query failure”);
$output .= ‘<table class=”pg_table”>’.”\n”;
$output .= ‘<caption>’.$atts[‘title’].'</caption>’.”\n”.'<tr>’;
for($i=0; $i<pg_num_fields($ret); $i++) {
$fieldname=pg_fieldname($ret,$i);
$output .= ‘<th><b>’.$fieldname.'</b></th>’;
}
$output .= ‘</tr>’.”\n”.'<tr>’;
for($row=0; $row<pg_num_rows($ret); $row++) {
$output .= ‘<tr>’;
$result = pg_fetch_row($ret,$row);
for($col=0; $col<pg_num_fields($ret); $col++) {
$output .= ‘<td>’.$result[$col].'</td>’;
}
$output .= ‘</tr>’.”\n”;
}
$output .= ‘</table>’.”\n”;

return $output;
}
add_shortcode (‘pg_table_query’,’pg_table_query_func’);

The related CSS style code:

table.pg_table {
color: #070707;
border: 1px solid #070707;
vertical-align: middle;
border-spacing: 0px;
line-height: 1.2;
width: 100%;
}

.pg_table td, tr, th {
border: 1px solid black;
text-align: center;
font-size: 12px;
}

.pg_table caption {
display: table-caption;
text-align: center;
font-weight: bold;
font-size: 18px;
padding: 5px 0 5px 0;
}

Sort and Average Rank in Fantasy Sports

As a dedicated fantasy hockey sports fan, I try to get an edge on the competition by analyzing player performance statistics for my initial draft and player trades during the season.  This often involves sorting or ranking players in scoring categories (e.g. goals, assists …).  It turns out that there are several ways of sorting and some may be more applicable than others for judging performance statistics.  For example, suppose we’re ranking goals in a league where 10 players have each scored 5 goals. A simple sort may order these players in ranks from 21 – 30. Even though 10 players score the same performance statistic (5 goals) their ranks can differ by 10 places. Not only that but typically a sort operation is non-deterministic i.e. the same 10 players can be ranked in any order, all between 21 – 30. One way to resolve ties (draws) is to assign an average rank (i.e. 25.5)  for all 10 players. Rank averaging maintains “sum-of-ranks” which is important for a defined sample size and fairer when comparing  to other statistics, in my opinion. A rank averaging method is commonly used in Yahoo Fantasy Hockey and other fantasy sports.

I looked far and wide on the Internet for a computer algorithm to automate average ranks.  Unable to find a suitable routine, I made my own. Using the Perl programming language I show how to sort a performance category and calculate the average ranks. No doubt a more elegant solution exists but at least mine works.

The annotated Perl script below should explain the average rank problem. It takes an unsorted hash of player scoring data and outputs a hash with an average rank for each player. The script’s print output shows the (complicated) averaging steps in action. I’ve tested this on sets of ~900 players and it works perfectly. Some lines of code below are truncated, be careful with copy-and-paste.

#!/usr/bin/perl -w
# define sub sr() to sort and calculate (average) ranks a’la Yahoo Fantasy Hockey.
# sorting higher score is better(top rank=0) to lower score.
use strict;
use warnings;
use List::Util qw(sum);

# define hash of real numbers.
my %scrHash = (); # player scores in some category (goals, assists…
my %rnkHash = (); # output for player ranks in this category.

#     Unsorted hash                        # Possible sort                     rank avg_rank
$scrHash{name0}{goals} = 2; # $scrHash{name7}{goals} = 8 0 1.5
$scrHash{name1}{goals} = 3; # $scrHash{name9}{goals} = 8 1 1.5
$scrHash{name2}{goals} = 4; # $scrHash{name8}{goals} = 8 2 1.5
$scrHash{name3}{goals} = 5; # $scrHash{name6}{goals} = 8 3 1.5
$scrHash{name4}{goals} = 5; # $scrHash{nameA}{goals} = 6 4 4
$scrHash{name5}{goals} = 5; # $scrHash{name4}{goals} = 5 5 6
$scrHash{name6}{goals} = 8; # $scrHash{name6}{goals} = 5 6 6
$scrHash{name7}{goals} = 8; # $scrHash{name5}{goals} = 5 7 6
$scrHash{name8}{goals} = 8; # $scrHash{name2}{goals} = 4 8 8
$scrHash{name9}{goals} = 8; # $scrHash{name1}{goals} = 3 9 9
$scrHash{nameA}{goals} = 6; # $scrHash{name0}{goals} = 2 10 10
$scrHash{nameB}{goals} = 1; # $scrHash{nameC}{goals} = 1 11 12
$scrHash{nameC}{goals} = 1; # $scrHash{nameB}{goals} = 1 12 12
$scrHash{nameD}{goals} = 1; # $scrHash{nameD}{goals} = 1 13 12
$scrHash{nameE}{goals} = 0; # $scrHash{nameE}{goals} = 0 14 14
#                                                                                                  sum of ranks 105 105

sr(“goals”);

print “Program End.\n”;
exit(0);

sub sr { # sort rank
my $cat=$_[0]; print “sr: category: $cat\n”;
my @valArray = (); # sorted score values
my @avgArray = (); # variable length array with running average.
my @rnkArray = (); # vartiable length array orders average ranks.
my $cntr=0;
my @sc = reverse sort { $scrHash{$a}{$cat} <=> $scrHash{$b}{$cat} }keys \%scrHash;
foreach my $id (@sc) {
print “sr: $cntr, $id, $scrHash{$id}{$cat}\n”;
$valArray[$cntr++] = $scrHash{$id}{$cat};
}

# Define 2 flags $en: equals-next, $el: equals-last
my $en = 0;
my $el = 0;

# Go through the sorted value array and average the rankings.
# These rankings are zero-based. push $i+1 for 1-based or similar.
for (my $i=0; $i<@valArray; $i++) {
if ($valArray[$i] == $valArray[$i-1]) { $el = 1; } else { $el = 0; }
if (($i <@valArray-1) && ($valArray[$i] == $valArray[$i+1])) { $en = 1; } else { $en = 0; }
if ($en == 0 && $el == 0) {@avgArray = (); push(@avgArray, $i); }
if ($en == 0 && $el == 1) {push(@avgArray, $i); }
if ($en == 1 && $el == 0) {@avgArray = (); push(@avgArray, $i); }
if ($en == 1 && $el == 1) {push(@avgArray, $i); }
my $avg = @avgArray ? sum(@avgArray)/@avgArray : 0;

print “i: $i val: $valArray[$i] el: $el en: $en avg: $avg \tavgArray: (@avgArray)\n”;

if ( $en == 0 ) {
foreach my $j (@avgArray) { push(@rnkArray, $avg); }
print “rnkArray: (@rnkArray)\n”;
}
}

# re-sort %scrHash to insert id and avg rank into new %rnkHash.
$cntr=0;
@sc = reverse sort { $scrHash{$a}{$cat} <=> $scrHash{$b}{$cat} } keys \%scrHash;
foreach my $id (@sc) {
$rnkHash{$id}{$cat}= $rnkArray[$cntr];
print “$cntr, id: $id, val: $scrHash{$id}{$cat}, avg_rank: $rnkHash{$id}{$cat}\n”;
$cntr++;
}
} # end sub

It is my contention that a team composed of the top ranked players in each position would win any league. But in a head-to-head match-up, there may exist combinations of players that could win 6 of 10 scoring categories and thus the match. I’m not a statistician and can’t prove it, but you’re welcome to educate me.

Please visit my fantasy hockey page: Renegade Hockey

OCF HF Dipole SWR Tuning

A procedure for tuning Standing Wave Ratio (SWR) of a simple dipole antenna, by trimming wire length, is presented here with empirical data. This is a follow-up to a previous post about design and construction of an off-center fed dipole antenna for the HF Amateur Ham radio bands.  ocf-hf-dipole-antenna-diy

Antenna Analyzer

To aid the tuning process I acquired a RigExpert AA-54 Antenna Analyzer. This instrument can easily log Freq, R, X  data, over a USB cable, using the AntScope product application software. Then CSV formatted data is imported into an Excel spreadsheet for VSWR calculation and plotting.

Trim Length

SWR tuning is performed by snipping short lengths of antenna wire, at the farthest ends, in order to raise the resonant frequency to within a desired frequency range. Fortunately there is a simple, accurate, formula to calculate the trim lengths. Consider:

c = L1 * F1 = L0 * F0

Where c is the speed of light, F is Frequency and L is Wavelength,  0 subscript is the initial and 1 is the target case. Using some algebra we derive Trim_Length:

Trim_Length = L0 – L1 = L0 * ( F1 – F0) / F1

For example, raising the resonant frequency of a 65 ft. dipole from 7.0 to 7.3 MHz:

Trim_Length = 65 ft. * (7.3 – 7.0) / 7.3 = 2.67 ft.

For this case, where the antenna is fed in a 1/3, 2/3 off center ratio, the trim lengths at each end are respectively:

short_side_trim = 2.67 ft. / 3 = 0.89 ft.

long_side_trim = 2 * 2.67 ft. / 3 = 1.78 ft.

Trim Results

I’m somewhat risk averse because shortening wires is easier than lengthening them. Optimizing performance on several bands can be tricky so I trim the wires in small increments, and measure the results across the relevant bands at each step.

The plot below shows the SWR performance across the entire frequency range for the AA-54 Analyzer (i.e. 0-54MHz). Note the original length “1st” and trim lengths of -6, -15 and -17 inches

Local SWR minimums are noted at the 40m, 20m, 15m and 10m bands.  Local minimums are observed around 43 and 50 MHz as well. 43 MHz is not usable for Amateur operators and 50MHz (6m) is somewhat marginal and not interesting to me now.

Focusing on the 40m band, the effect of trimming can be measured at each step. Each incremental trim raised the resonant frequency and after trimming 17 inches, SWR ranges from 1.4:1 to 1.8:1 across the 40m band (7.0 – 7.3 MHz) (yellow).

Similar results are shown for the 20m band. After 21 inches trimming VSWR is a nearly ideal (1.4:1) across the entire band. Considering the effect of trimming on other bands I stopped trimming here. 21 inches is somewhat less than the predicted 2.67 ft. (32″) but close enough for practical purposes.

A Z-normalized Smith Chart below shows the impedance across a range of frequencies in the 40m and 20m bands. Black markers are at mid band. The lowest SWR, nearest the center, for both bands, is found at about twelve-o’clock in the chart.

A circle of constant 2:1 SWR is shown in red.

SWR vs. Reflected Power

The motivation for trimming dipole wires is to match the antenna’s impedance to the transmitter output impedance, in this case 50 ohms real resistance. When matched, the reflected wave is minimized and power radiated by the antenna is maximized. So how low a SWR is good enough? Below is a plot of SWR versus reflected power.

As shown, a 3:1 SWR reflects 25% power, 2:1 SWR reflect about 11% and 1.5:1 reflects just 4%. Therefore a 2:1 SWR or better is generally regarded as “tuned”.

Conclusion

  1. An Antenna Analyzer was a useful tool for measuring complex impedance across a wide range of frequencies (outside amateur bands). With this data, VSWR was calculated  and a strategy formulated to improve performance.
  2. I discovered a new usable amateur band on 15m. This bonus band was not anticipated in the original design. In fact I have made several QSOs throughout the USA using this band.
  3. As initially constructed, the length-measured antenna wires were close to the design goal but SWR improved substantially after trimming.

OCF HF Dipole Antenna DIY

As a ham radio enthusiast, I take great pride in designing, building and testing my own antennas. I’m not an expert but I’ve had success at VHF, UHF frequencies and I wanted to try longer range communications possible on HF bands. A full blown HF tower 60 ft. in the air is not practical at my humble suburban abode. Nevertheless, a row of trees in the backyard provided space to explore the capabilities of a homemade antenna.

The antenna described here is commonly known as a Half-Wave Off Center Fed (OCF) Dipole or it’s cousin the Windom antenna. It is designed to resonate on a fundamental frequency and its even harmonics, in this case the 40, 20 and 10m amateur radio HF bands. The form is similar to other dipole antennas i.e. long wires suspended horizontally with a balanced electrical feed. Except for the ferrite toroid cores, all the components are commonly available at your local hardware store.

Design

Referring to my ARRL Amateur Radio Handbook, for #14 insulated Cu wire, a half-wave length for 40m (7MHz) was 68 feet according to the formula below.

Length[ft.] = 468/(Vf * Freq) = 468/(0.98*7) = 68 ft.

where Vf is velocity factor (0.98 here) and Freq = Frequency in MHz

I determined that erecting a horizontal 68 ft. antenna was feasible in my backyard.  There is much debate about feedpoint location but I chose 2 nominal segment lengths of 23  and 46 feet for a 1/3 to 2/3 split. A major compromise to performance would be that the maximum height of the antenna is limited to about 20ft. as shown in diagram below,

Feed point impedance is a function of elevation above ground so I wanted to simulate my site’s configuration using EZNEC demo, a free EM field simulator program. The SWR results below indicate a minimum at 7.21 MHz (middle of 40m band).  Here, Z = 61 ohms @ 0.61 deg. (close to ideal).

Indeed 3 resonant frequencies are shown, the fundamental, 2nd and 4th harmonics. While SWR is not perfectly 1:1 at all 3 frequencies I took the EZNEC results as a 1st order guide. The real physical antenna would be optimized on-site by manual pruning. This situation illustrates the purpose of an Antenna Tuner but alas, not in my budget.

More EZNEC results are shown below. Max. field angle is about 19 degrees, pretty close to 15 degrees, considered ideal.

elevation
Elevation radiation pattern

The Azimuth radiation pattern is not perfectly circular but much more omni-directional than a dipole in free space. I suspect part of the omni-directionality is due to the vertical vector components of the inverted-V configuration.

Azimuth radiation pattern

Guanella 4:1 Dual Core Current Balun

The balun transforms the 50 Ohm coax feedline impedance to 200 Ohm at the dipole offset feed point. It also transforms the unbalanced coax to a balanced feed. This 4:1 current balun is implemented using 2 pcs. 1.4×2.4″ ferrite cores of type 61 material.  This is the most expensive component of the antenna. Using these large size ferrite cores and #14 Cu wire give the antenna a transmit power capability of 1.5KW I estimate.  This is the legal limit for any Amateur broadcaster. The circuit diagram is shown below.

4:1 guanella current balun

Note that the copper wire windings are in opposite directions for transformer 1-2-3-4 versus 5-6-7-8. Fourteen windings were used for each. Using different colored insulated wire helps avoid winding mistakes.

Guanella toroid core transformers

Assembly

Below is a brief Bill of Materials:

  1. ferrite toroid core, 2 pcs. P/N FT-240-61,  ebay.com $20 each
  2. SO-239 bulkhead mount female UHF connector, 1 piece, ebay.com, $2
  3. 100ft. #14 stranded THHN insulated copper wire, Home Depot, $22
  4. Plastic electrical utility box, 1 piece, Home Depot, $12
  5. Strain relief hardware, 2 sets, Home Deport, $4
  6. Miscellaneous 8-32 eye-hook hardware, $5, Home Depot

Total cost: $85

Antenna Components

Assembly is very straight forward. I used a long table and tape measure to measure wire lengths. A magic marker was used to mark-off each foot with longer marks for each 10 ft. and a double mark for the theoretical ideal length. An extra 1 ft. was added for strain relief and 1 or 2  ft. for length margin. Two wire ends are soldered to tabs and connect to separate through-hole assemblies.

Simple drilled PVC pipe Antenna End Cap

Testing/Results

After erecting the antenna and connecting to my transmitter, I characterized SWR values using the built-in meter by  sweeping amateur frequencies across 3 bands. Typical values are shown below. To my  delight SWR range was reasonably low across all three bands.

SWR Plot for 40, 20, 10m Amateur Frequencies

Again, SWR being slightly high and variable is a good reason to use an Antenna Tuner. But this minor mismatch is good enough for my transmitter. I wish I could characterize SWR over a wider frequency range, but something like a VNA or Antenna Analyzer is way beyond my means.

I am  able to hear SSB voice stations from Alaska to Costa Rica to Hawaii to Pennsylvania and make voice contacts about 2,000 miles away. Low-power digital modes (e.g.FT8, JT65) using just 30W of power yielded QSOs as far as 5,000 miles distance.

Conclusion

Due to physical area constraints at my home I was trapped in VHF/UHF world for too long. But I found a way to construct this HF antenna and have enjoyed continent-wide communications ever since.

Although this antenna’s performance is highly compromised at my site, it was still one of the most successful and gratifying amateur radio projects I’ve completed. With no antenna analysis capability, I had faith that employing good design and construction technique would get me close and that would be good enough. If you’ve been holding off getting on the HF bands because building a grand ideal antenna is not feasible or too expensive, I encourage you to try such a low cost solution .

References

Dipole Introduction

How and why an OCF dipole antenna works

Dual core 4:1 Guanella current balun

by KF7GAX, 73