Sunday, November 21, 2021

Canon EOS Remote Intervalometer

To create a time lapse video, you need to take a bunch of still images and stuff them into a video editor. The trick is you don't want to have to stand there with a stopwatch for hours, snapping hundreds of photos. Thus the need for an intervalometer - a device which repeatedly trips the camera's shutter. Some cameras already have this feature, and there's custom firmware such as Magic Lantern or the Canon Hack Development Kit which implement the feature, but I wanted to have the opportunity to experiment a little. My main goal is to make videos of the Milky Way as it rotates across the sky. On my camera (a Rebel SL1), I use a 15 second exposure at ISO 12800, and then the camera takes about 20 seconds to process each image. For this reason, I decided to start with a 60 second interval. At this interval, every hour in real-time compresses down to two seconds of video. 

My camera uses an infrared remote, which is ideal, because there's less chance of bumping the camera, causing a shaky image. I have a remote like this. According to various sources on the web, the remote triggers the camera by sending out two 32 kHz pulse trains. If the pulse trains are 5.35 mS apart, the camera triggers with a two second delay accompanied by beeping. If the pulse trains are 7.35 mS apart, the camera triggers immediately. To confirm that this is how it works, I disassembled a photo-interrupter, and removed the phototransistor. I then connected it to a 5 volt source through a 1 kOhm resistor. Because the frequencies involved are rather low, I was able to use my DSO Shell oscilloscope, which has a max speed of only 10 uS per division. 


Sure enough, there were two pulse trains at 32 KHz. I set an Arduino up to drive a 950 um LED at 32 kHz every 5.35 mS and to my surprise it only worked if I waved it all around the camera. If I pointed it directly at the receiver in the front of the camera's hand grip, it didn't work at all. The signal looked good...


Going back to the Amazon remote, I noticed that even if you held the button down, it only sent two pulses trains. I had though that if I sent more pulse trains, the remote would be more reliable. Since that wasn't the case, I added a button to the project that allowed only two pulse trains per button-push. Now it worked reliably. 

One other improvement I added, was that I wired the infrared LED in parallel with the Arduino Nano's internal LED on pin 13. That way you can tell when the LED is on. There's another way you can tell, though. Look at the LED with an old or inexpensive webcam. In the image below, you can see the infrared LED glowing white when viewed through my webcam.
 

This infrared-viewing trick used to work with the camera in my old Palm Pilot, but it doesn't work with my  iPhone. I assume it's because Apple added an infrared filter to the higher quality iPhone camera.

The next step was to make it send two pulse trains every 60 seconds. That was easy but I wanted a count-down timer so I'd be able to tell if the intervalometer was running, and to see how long until the next exposure. In my junk box I had three HP 5082-7340 LED display modules from the 1970s. These displays have nice-looking numbers compared to most seven-segment displays and have on-board memory so your microcontroller doesn't have to tie up processing cycles doing a multiplexed driver scheme. In the days when microcontrollers were expensive these displays were a great idea. Now they're just nostalgic - but I was surprised to see some vendors asking as much as $20 on Ebay, especially since you can get an OLED graphical module for less than $10 these days. 

Here's how the current project looks. Please ignore my ugly wiring! Whenever I try cutting leads to some exact length, they always come out either slightly too long or worse yet, slightly too short. I really need to make some kind of template. So for now, I just use longer jumpers and let the wires go everywhere! 


I have the first digit displaying the letter A, just because it can. Maybe that will be some kind of mode designator in the future. One thing I don't like about these LED displays is that they get kind of warm. That's probably causing excessive battery drain when I'm powering it that way. In the future I may use the display's blanking control as a dimmer so it doesn't use so much juice.

Another thing I want to change is the brightness of the power LED on the Nano. It's so distracting! Rather than attempting to change the microscopic resistor in the circuit, I may just put some white paint over the LED!

Finally another feature I'd like to add is a start/stop button and a way to adjust the interval.

You can find the Arduino source code here.

Friday, October 22, 2021

A Little Background on Yagi Antennas

I just realized that I've been going on and on about different parts of the Yagi antenna without providing much background. A document describing the Yagi antenna, or more properly a Yagi-Uda antenna, was first published in 1926. Many people are most familiar with this antenna in the form of over-the-air TV antennas that were mounted on the rooftop of nearly every house decades ago. Here's a link to a Google Doodle celebrating Yagi Hidetsugu's birthday that illustrates what I'm talking about.

https://www.google.com/doodles/hidetsugu-yagis-130th-birthday

Each of the metal cross-pieces on the antenna is called an element. There may be as few as three elements, but there can be as many as ten or even more elements. There are three types of elements. The longest element is called the reflector and it's located at the "back" of the antenna, and it redirects signals arriving from the other elements towards the "front" of the antenna. The element next to the reflector, and in the middle of the three element array, is called the driven element. It's slightly shorter than the reflector, and is split into two segments. The two segments are connected to a radio transmitter or receiver. Finally there are one or more directors that focus the radio waves into a narrow beam. The directors are shorter than the driven element, and sometimes get even shorter as more are added.

In the above sketch of a Yagi antenna, the "back" is to the left and the "front" is to the right. If the antenna's connected to a radio transmitter, the direction of greatest signal strength is to the right, or in the direction of the director. If the antenna's connected to a radio receiver, the direction of greatest sensitivity is from the right, or from the direction of the director.

Characteristics of the antenna vary with, among other things, the spacing between the elements and the relative lengths of the elements. In my reference design, the elements are about a quarter wavelength apart. The driven element somewhat less than a half wavelength long. A wavelength is roughly equal to the speed of light divided by frequency of the signal of interest. The reflector is four percent longer than the driven element and the director is four percent shorter than the driven element.

One desirable characteristic of the Yagi is gain - that is the increase in signal strength. This increase is not the same in all directions. In fact, signal strength to the sides and back decrease as forward signal strength increases. You don't get something for nothing! 

This trade-off in signal strength results in other desirable characteristics; for example, directionality. Because the Yagi antenna is most sensitive in one direction it's useful in applications such as wildlife tracking.

The optimizations I'm making in these blog posts are no great new discovery. I'm just starting with a reference design and exploring what happens when I vary certain design parameters in a simulation. The purpose is to give me an opportunity to play with the simulation software, and to get a more intuitive understanding of an antenna design that's always fascinated me.

Thursday, October 21, 2021

Further Optimization of Yagi Antenna Parameters

In the previous post, I documented my experiments with the spacing between elements in a three element Yagi antenna. What about the length of the antenna elements? 

In a Yagi, the reflector is longer than the driven element, and the director is shorter than the driven element. In the reference design I've been using, the difference in element length was four percent in both cases. Is this optimum? In fact it appears to be. I wrote this script to explore the question: 

https://github.com/umeda/nezumi/blob/master/Projects/antenna_sim/yagi_optimize_length.py

I assumed the difference in lengths to be the same in both cases, then simulated antennas with zero to ten percent difference in their lengths. 


As you can see in the above plot, gain gets better as the difference in element lengths get lesser, but  SWR gets better (lower) as the element lengths get greater. Since most radios prefer an SWR of less than two, we can move a little bit to the left of four percent element length difference before getting into trouble with our final drive transistors. Gain is a little over 8X, which is quite satisfactory. However, if we are at an SWR of two at our design frequency, what are we going to look like over the entire band?

 
And the answer is: we're going to have to give up some more gain if we want an SWR of less than two (indicated by the green area) over the entire band, at least for the two meter ham band. It looks like an element difference between four and five percent would do nicely. Of course if I wanted to design an antenna for a single frequency I could get more gain.

The first time I generated this plot, the green area representing the area of acceptable SWR was skewed way down to the lower band edge. Looking at some reference designs, I realized that the driven element was usually somewhat shorter than a half wave length. So I tweaked the scale factor to bring the best SWR to the middle of the band.

The other thing I realized, is that I should probably go back to my element spacing script and see what the acceptable frequency range was for various element spacings. However, I'm currently more interested in moving forward, so we'll revisit that later.

The next question to be investigated is: what if we let the reflector and director elements vary independently?

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$]