Sunday, October 10, 2021

Optimizing Yagi Design Parameters

There are so many different Yagi designs published in books, magazines, and on the web. But what's the difference between them? For a basic three-element Yagi, design parameters include the spacing, length, and diameter of the elements. Performance parameters include standing wave ratio (SWR) characteristics, gain, and front-to-back ratios. When I see a design, I wonder what the designer's goals were, and if I change one parameter, how will other parameters be affected? 

I started out with the impressive National Bureau of Standards Technical Note 688, titled Yagi Antenna Design. The author built antennas and measured their performance as parameters were varied. I wanted to do something similar using NEC2 simulation software in an effort to understand the relationship between design and performance parameters. I used the PyNEC library so I could programmatically try many different combinations. Using a Python script is much more efficient than using any of the NEC2 applications, because I can simulate and compare hundreds of configurations in a matter of minutes. 

Starting with one of the basic three-element Yagi designs in the technical note, I noticed that the spacing between the elements was the same, and that the spacing was one quarter of the antenna's design wavelength. What would happen if the spacing between elements remained equal, but was increased or decreased. I updated the script yagi_3_element.py to measure the forward antenna gain and plot it. And wouldn't you know it? The script predicted maximum gain at one-quarter wavelength which matched what was measured in the technical note.



The radiation pattern shows a forward gain of almost 9.

And the SWR across the VHF ham band is only slightly more than two, which is easily handled by most radios. 



Then the next question was: could gain be increased with unequal spacing? I wrote yagi_optimize_spacing.py to independently vary the two spacing parameters, creating a surface and plotting it. 

The answer was yes. Gain was increased slightly: half a dB. This could be done by increasing the director spacing to 0.325 λ and reducing the reflector spacing to 0.055 λ, but that seemed really strange. I've never seen an antenna like that, there had to be a catch. Plotting the SWR revealed the problem. 


The SWR was super-high. The complex matching network required for an antenna such as this would more than cancel any of the gain improvement. 

So what I learned was that quarter-wavelength spacing is best for a three-element Yagi. 

The next questions are: what happens if the element lengths are varied? How do Yagis with arbitrary numbers of elements behave? And, if I build one of these on my workbench, how closely will its performance match these designs? 

Saturday, January 23, 2021

Garden Logger Schematic and Voltage Divider Script

There are a few features I want to add to the Garden Logger, but now the wiring's getting complicated. I'm adding three soil moisture sensors, a battery voltage measurement circuit, a voltage reference, and an LED with an annunciator. I need to use a CAD tool to draw the schematic, so I tried gEDA Schematic Editor. It's pretty easy to use and there is a library of user generated parts. You can also easily generate your own parts and modify existing ones. I used the symbol editor to create a soil moisture probe and a temperature/humidity sensor. Once you've created the symbol, you have to move it to /usr/share/gEDA/sym/local. 

For the battery voltage measurement circuit, I needed to calculate what resistor values to use for the voltage divider.  I wrote a little script to calculate this, and in the process found a neat library called "engineering_notation". The library makes it easy to display values in powers of three using the correct SI notation. 

Here are the results:

Enter input voltage: 15
Enter output voltage: 5
Enter current in mA: 1

r1 value => 10kΩ
r2 value => 5kΩ
voltage  => 5.0 volts
current  => 1.0 milliamps
r source => 2.50kΩ
r1 power => 10.0 milliwatts
r2 power => 5.0 milliwatts



Monday, January 11, 2021

Web Server for the Garden Logger

I'd like to be able to see how the Garden Logger's doing. Is it still running? What values is it reading now?

I'd like to stick a Raspberry Pi in the bento box with the Arduino, run a web server on the Pi, and have have the Pi serve up web pages showing the logger's status;  and maybe even control which channels are scanned at what speed.

I was going to develop it on a Pi Zero W, using VSCode via SSH. No dice -  VSCode didn't support the Pi Zero's Processor. Same thing with RasPi 2. It does work with a RasPi 3, but I didn't have any to spare, so I wrote the code on my Linux Mint workstation.

I thought it would be great if logger could send a nice JSON package across to the Pi, but it was better to keep things simple on the Arduino and to put those smarts into the web server. So for now, every time the Arduino writes data to the SD card, it also sends a string of data channel names followed by a string of the data from those channels.

The first thing to do is to install the serial and web server libraries. For some reason, I needed to "pip uninstall" the serial library, then "pip install" the pyserial library. I "pip install"ed the Flask library for the web server.

After connecting the Arduino to a USB port, the sever app needs to find the port that the Arduino's attached to. This is the code snippet I used. It's hard coded to use a specific "Seeeduino", so the process is that the list of hardware IDs needs to be printed using the first two lines in the code snippet, then after the right ID is determined, it gets hardcoded into the server app.

for port in list(list_ports.comports()):
print(port.hwid)
if port.hwid.startswith('USB VID:PID=0403:6001'): # change this if using something other than Seeeduino.
print('Arduino on: ' + port.device)
arduinoPort = port.device

I used this tutorial as a starting point for learning Flask

After I got the example working I needed to start a thread running that would wait asynchronously for data from the Arduino, then parse it, and save it into a global variable for the web server.

print('starting data acq')
dataAcq = threading.Thread(target=monLogger)
dataAcq.start()

The next step was to start the web server. Here's where I hit a problem. When I started it in the VSCode IDE, it was bringing up a second instance of the logger monitor thread. I was really stumped until I came across a web posting that said debug must be disabled on the server. I changed that, and the problem was fixed!

print("starting server")
app.run(debug=False, host='0.0.0.0') # debug=False should prevent restart and doubling dataAcq

Now the final step was to get the data into a Jinja2 template for display. With a few more lines of code, I can now monitor the Garden Logger from anywhere on my network!




Saturday, January 9, 2021

Adding an External Hard Drive with Samba to a Raspberry Pi

I started with an out-of-the-box 4TB Western Digital Blue drive. I put it into a Sabrent enclosure, powered it up and plugged it in. First step is to find the drive:

pi@raspberry:/mnt$ sudo lsblk -o UUID,NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL,MODEL
UUID                                 NAME        FSTYPE  SIZE MOUNTPOINT LABEL  MODEL

                                     sda                 3.7T                  WDC_WD40EZRZ-22GXCB0
                                     mmcblk0             3.7G                   
4AD7-B4D5                            ├─mmcblk0p1 vfat    256M /boot      boot   
2887d26c-6ae7-449d-9701-c5a4018755b0 └─mmcblk0p2 ext4    3.4G /          rootfs 

Now to format it:

pi@raspberry:/mnt $ sudo mkfs.ext4 /dev/sda

Create a directory:

pi@raspberry:/mnt $ sudo mkdir /mnt/ext_storage

Mount the drive in the directory:

pi@raspberry:/mnt $ sudo mount /dev/sda /mnt/ext_storage

Reboot:

pi@raspberry:/mnt $ sudo reboot

You'll get kicked out. Login again.  Verify that it's mounted:

pi@raspberry:/mnt/ext_storage $ sudo lsblk -o UUID,NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL,MODEL
UUID                                 NAME        FSTYPE  SIZE MOUNTPOINT       LABEL  MODEL
7dd94502-35a2-4bd3-a218-7cf76e350c7b sda         ext4    3.7T /mnt/ext_storage        WDC_WD40EZRZ-22GXCB0
                                     mmcblk0             3.7G                         
4AD7-B4D5                            ├─mmcblk0p1 vfat    256M /boot            boot   
2887d26c-6ae7-449d-9701-c5a4018755b0 └─mmcblk0p2 ext4    3.4G /                rootfs 

pi@raspberry:/mnt/ext_storage $ sudo blkid
/dev/mmcblk0p1: LABEL_FATBOOT="boot" LABEL="boot" UUID="4AD7-B4D5" TYPE="vfat" PARTUUID="80a50d6c-01"
/dev/mmcblk0p2: LABEL="rootfs" UUID="2887d26c-6ae7-449d-9701-c5a4018755b0" TYPE="ext4" PARTUUID="80a50d6c-02"
/dev/sda: UUID="7dd94502-35a2-4bd3-a218-7cf76e350c7b" TYPE="ext4"
/dev/mmcblk0: PTUUID="80a50d6c" PTTYPE="dos"

Now set up Samba:

sudo chown pi /mnt/ext_storage

sudo apt-get update
sudo apt-get install samba samba-common-bin

sudo nano /etc/samba/smb.conf
[ext_storage]
path = /mnt/ext_storage
writeable=Yes
create mask=0777
directory mask=0777
public=no


sudo smbpasswd -a pi
sudo systemctl restart smbd


After doing the above, I had a few issues. First, the external hard drive wasn't remounting when the Pi was rebooted. To fix this. I added the following to /etc/rc.local:

sudo mount /dev/sda /mnt/ext_storage


Next, some directories like the user home directory and the non-existent printer directories were showing up on some Samba clients like Macintosh and AppleTV VLC Player. The solution was to comment out the following sections in /etc/samba/smb.conf:

[home]
[printers]
[print$]

Monday, December 28, 2020

Messages from Space

Between Christmas and New Year's Day, 2020, the International Space Station is celebrating 20 years of ARISS (Amateur Radio on the International Space Station) by sending slow-scan TV images back to Earth. SSTV is something like a fax, sending one line at a time. To receive these images, you need an FM receiver tuned to 145.800 MHz. Unlike many other signals from space, you don't need a Yagi antenna. Because the signal from the ISS is relatively strong, the ground plane antenna I made worked just fine. The audio then needs to be sent to your computer for processing. I used an application called QSSTV. To know when the ISS is going to be overhead an iPhone app like SatSat works very well. There are web sites that track the ISS, too. Overhead passes come in groups of two or three per day spaced 90 minutes apart.

It took me three passes to get it right. 

For the first pass, I tried recording on my iPhone. I though I was recording, but alas, I wasn't.

On the second pass, I connected the radio output to my computer and recorded the signal with Audacity. I saved in several formats, but when I tried importing it into QSSTV, I got  an invalid header error.

On the third pass, I tried QSSTV in live mode with automatic save enabled. There are some noise artifacts because the pass wasn't particularly high above the horizon, but I did get an image. ISS been sending images of different contacts that have made and organizations they have worked with. This image shows astronauts on the space station along with members of AMSAT, the Amateur Radio Satellite Corporation. At the bottom are the Russian and American call signs used aboard ISS: RU0ISS and NA1SS.


Friday, December 25, 2020

Raspberry Pi Password Tricks

With a whole fleet of Raspberry Pi boards, it's sometimes a chore remembering all the passwords. Short of writing the password on a post-it stuck to each Pi, here are a few tricks.

Set up ssh authentication. If you haven't already, generate the private/public key-pair on your workstation. 

ssh-keygen

Answer all questions with <Enter>. 

This will generate your private key.

~/.ssh/id_rsa

And your public key.

~/.ssh/id_rsa.pub

Now copy your public key to the raspberry pi.

ssh-copy-id pi@raspberry.lan

Now you no longer need a password when logging in from your workstation because the pi trusts it.

ssh pi@raspberry.lan

You will still need the password when logging in from other devices, but if you ever forget it, you can do a password reset without knowing the password with the following command.

sudo passwd pi


Wednesday, December 23, 2020

Orbits of the Galilean Moons

In the previous post I described my measurements of Jupiter's moons - four of which were discovered by Galileo. One fascinating thing about the inner three moons is that they are tidally locked into a [4:2:1] orbital resonance. That means that Io orbits twice as fast as Europa, which orbits twice as fast as Ganymede. I though it would be neat to take some measurements of these moons and try to verify that resonance. Observing an orbiting object side-on, it appears to oscillate back and forth in a sinusoidal pattern; that is, as long is the orbit isn't too elliptical. Fortunately these moons have a small eccentricity. I was able to get five measurements over a week, and then one more, three weeks later. That's not many. Ganymede, the outer-most of the three tidally locked moons orbits Jupiter once per week, so I figured I had enough samples to get it's orbital period. The other two moons, having periods of half and one quarter of Ganymede were too under-sampled to make the calculation, but I figured if I plotted their predicted orbits based on the Ganymede data I could claim success if the few sample points I had lined up on the predicted curve. 

 To fit a sine wave to my data points I used the curve_fit function in the SciPi Python library. You can find the source code to the Python script I wrote here. Plugging the data in, I got this:

The dots are the measured distances and the line is the best-fit curve. The calculated orbital period was 7.22 days. According to Wikipedia, the actual orbital period is 7.15 days. Looks like I'm off by about 1%. Not bad at all. 

Now to overlay the predicted and measured orbits of Europa and Io. When I first did this, the measured points were nowhere near the predicted curve. It turns out that each moon is 180 out of phase with its neighbor. I hadn't seen that mentioned in any of the literature. I did, however, notice it in an animated simulation of the orbits of the three moons. When I added the phase shift, the dots stayed pretty close to the line, although not perfectly. I'm sure there was plenty of measurement error in my technique!
Now that Jupiter is starting to be obscured by the setting sun, I don't think I'll be able to take more measurements until next year when Jupiter is once more visible.