## Vector measurements with the rtl-sdr, 7

16.10.2020 18:44

Looking back at my last few posts I feel that I was going into increasingly theoretic guesswork about the impedance mismatches in my rtl-sdr measurement setup. Even though I still think it could perform better, I would like to share some actual antenna measurements I made with it. I've also now got my hands on a NanoVNA-H, one of the many variants of the popular low-cost vector network analyzer. It's interesting to compare the measurement results between the two instruments.

Yesterday I've measured the VSWR of a few compact LTE antennas. These antennas have an adhesive backing and are meant to be mounted into mobile devices that use the cellular network for connectivity. All of these antennas come with a coax cable tail that terminates with a female U.FL connector. This was a bit problematic since both my instruments terminate in a SMA connector. So to make a connection I've used a U.FL-to-U.FL "thru" on a RF demo kit PCB I got with my NanoVNA and another short U.FL-to-SMA patch cable.

I've calibrated both my rtl-sdr setup (vect-meas-mux in the following) and the NanoVNA with the short-open-load one port method. I've used the U.FL calibration standards on the same RF demo kit. This resulted in the calibrated measurement plane on the U.FL end of the U.FL-to-SMA patch cable. Hence the measurements include effects of the "thru" and the coax cable tail that was attached to each antenna.

The vect-meas-mux setup consisted of the ERASynth Micro, rtl-sdr, my custom multiplex board and the Transverters RF bridge as the directional element. It allows measurements up to 2000 MHz, with a gap around 1200 MHz, defined by the rtl-sdr's tuning range. It's the same setup as I described in the past blog posts in this series. The NanoVNA-H was bought from Nooelec and the particular version I have is no longer listed on their website. It shows firmware version 0.4.5-1 and allows measurements up to 1500 MHz. I transferred the S11 measurements from the NanoVNA to the computer using code based on this example notebook and then calculated VSWR from S11.

In the graphs below, the VSWR measured with vect-meas-mux (orange) and NanoVNA (blue) is compared to the VSWR given in the datasheet (black) of the respective antenna. I was mostly interested in how both instruments agree with each other and how well the results were repeatable. The datasheet curve is there as a reference. I wasn't expecting to get a good match. I took care to have a reasonably clean measurement environment: as much open space in all directions around the antenna as possible, antennas mounted on a non-conductive plastic holder, etc. However obviously that can't compare with a measurement in an anechoic chamber and random objects in the vicinity were affecting the results. I also didn't use a choke on the coax tail to prevent it from radiating.

I'm pretty happy with how these measurements turned out. The results from my own instrument match those from the NanoVNA quite well. The agreement with the datasheet is often reasonably good as well although, as I said before, that's probably due to my poorly improvised environment around the antenna.

After doing many measurements the main problem with the rtl-sdr method turned out to be its slowness. NanoVNA displays the result nearly instantaneously. On the other hand a 200-point sweep from 55 to 2000 MHz with vect-meas-mux takes around 7 minutes and 30 seconds. Most of this is due to hugely inefficient way I collect signal samples from the rtl-sdr: I run the rtl_sdr binary once for each of the 200 frequency points. This results in the setup and tear down time of the rtl_sdr binary dominating the total run time. I only need to dwell on each point for about 100 ms, which would mean a sweep time of about 20 seconds. I'll probably rewrite my code to use the rtl_tcp server to fetch the I/Q samples, which should reduce the overhead significantly.

In the future I would also like to be able to estimate the error intervals of the measurement, like I did with my scalar experiments. Because this was a vector measurement and I used calibration, the relatively poor directivity of my RF bridge affected the results much less than with scalar measurements. A bigger factor was probably the limited dynamic range of the rtl-sdr. scikit-rf has some support for estimating error intervals, but I still need to figure out how to integrate that with my code.

I'm also looking for extending the frequency range of my measurements, but that will require switching to a more expensive SDR. Perhaps something like the HackRF or an USRP.

Posted by | Categories: Analog | Comments »

## Vector measurements with the rtl-sdr, 6

06.10.2020 19:58

This is another update on my project where I'm developing a system for vector signal measurements with the rtl-sdr. Back in August I was testing the performance of the time multiplex board I made. One of the more puzzling things I discovered then was that apparently the signal losses in the multiplexer varied a lot with frequency. I measured a dip in signal level of almost 10 dB at 1700 MHz. I expected a mostly frequency-flat characteristic due to attenuation on the PCB and in the MMIC switches.

My first suspicion was that I messed up the design of the grounded co-planar waveguides (GCPW) on the board. After some research however I found conflicting information on that. Some sources say that my design is correct and others say it's not. I also got the impression that even if the trace dimensions I used were slightly wrong, they shouldn't result in the signal losses I was seeing due to relatively short trace lengths.

I currently don't have any professional RF equipment at hand. My gain (i.e. S12) measurements were done by using ERASynth Micro as a signal source and rtl-sdr as the detector. I measured the losses in the circuit board by routing the signal through the board, sweeping the signal in frequency at a constant output power, and recording the received power at rtl-sdr using rtl-power-fftw. I used a measurement of a male-to-male SMA through as a reference in an attempt to subtract any variability of ERASynth's output power and rtl-sdr's sensitivity.

Since I suspected that the variability in the gain I measured might also be due to impedance mismatches I did some further measurements with ERASynth and rtl-sdr to better understand what is going on. These measurements were performed in the same way as my previous one. ERASynth Micro was set to -40 dBm output level and was swept in steps from 55 MHz to 2 GHz. On each step, the rtl-sdr was tuned to the same frequency and the baseband signal power was measured with rlt-power-fftw (RF gain was set to 15 dB).

The picture below shows the six signal paths I measured:

"thru" measurement was a single rigid male-to-male SMA adapter. "thru3" was a combination of 3 adapters (male-to-male, female-to-female, male-to-male). "gcpw" was a measurement of a single leg of the PCB trace on a spare board where I soldered a SMA connector in place of the switch IC.

During the measurements involving the assembled multiplex board the switches were powered up and configured to allow the signal to pass in the measured direction. Also worth mentioning is that for measurements involving both PCBs, two male-to-male adapters were also in the signal path (one on the ERASynth side, the other on the rtl-sdr side).

Following graph shows the results. In contrast to the graph above from August, this graph is not normalized in any way and shows raw values returned by rtl-power-fftw. The gap between 1100 MHz and 1250 MHz is the band to which rtl-sdr can't tune to. The results for the "ref in - det out" path had +10 dB added on this graph to make it comparable with other traces since this path goes through a 10 dB attenuator on the board.

These results show several interesting things. The first good news is that the two identical paths through both switches show nearly identical results ("ref in - dut out" and "dut in - det out" traces). This is reassuring. It's unlikely that my board isn't soldered well or that I damaged one of the switches.

The other interesting part is that all other traces differ a lot from each other. Even just adding two adapters changes things significantly ("thru" and "thru3" traces). This suggests that the variability I was seeing is due to some mismatch between the ERASynth and rtl-sdr and not the fault in my board.

It's also telling that the only path that involves an attenuator ("ref in - det out") shows the least variability and also seems to be lower or equal to all other traces. The attenuator provides isolation between the source and the load and reduces the impact of their impedance mismatches. It changes the situation from the mismatched load and source (where gain varies with frequency) to a mismatched load and mismatched source separately (where gain does not vary with frequency). Also, in contrast to the GCPW traces, I'm pretty sure I got the 50 Ω impedance of the attenuator correct.

k = \frac{u_{max}}{u_{min}} = 2.5 \qquad [8 \mathrm{dB}]
|\Gamma_g\Gamma_l| = \frac{k-1}{k+1} = 0.43 \qquad [-7.3 \mathrm{dB}]

The measured power in the un-attenuated paths at frequencies above 1 GHz varies for about 8 dB. This translates to a product of reflection coefficients of ERASynth and rtl-sdr of about 0.4 (-7 dB). I don't have any data for ERASynth. The datasheet for E4000 tuner in the rtl-sdr states a typical return loss of 15 dB for a 50 Ω system, but my rtl-sdr has some components in front of the tuner which might make it worse. I measured the return loss of my rtl-sdr at about 11 dB at 70 MHz, so 7.3 dB at 1 GHz combined with ERASynth doesn't sound too much off.

In summary, this all points to the rtl-sdr's poor 50 Ω matching to be the culprit. There are some ways I could make the frequency response flatter. The simplest solution would be adding another attenuator to the board in front of the DET OUT connector. I'm using the lowest RF gain setting on the rtl-sdr so there should be enough reserve in terms of signal level. I don't want to do anything more elaborate like a rtl-sdr specific matching network since I want this board to be usable with other small SDRs as well.

Anyway, I think I'll leave the multiplex hardware as it is for now. I still have some planned improvements on the clock recovery code. I've also found Henrik's blog and his wonderful posts about the homemade VNA. His project is orders of magnitude more advanced than mine, but some of the details he writes about are still very useful for me. Thanks to him I found out about the scikit-rf Python library which I will gladly use instead of my home brew calibration code. I also found his directional coupler design very interesting and I might eventually make a copy of it to replace the RF bridge I'm currently using.

Posted by | Categories: Analog | Comments »

## Weirdly clogged inkjet nozzle

30.09.2020 16:01

Recently I noticed some unusual red dots and lines on the printouts from my Epson L310. It was interesting because it seemed like extra dots were getting added to the paper. This is just the opposite of the usual problem of clogged nozzles. In that case, dots (or whole lines) are missing on the paper. The extra dots also looked well-defined and didn't look like ink was just getting smudged onto the paper by a dirty print head.

I've ran the nozzle check using escputil -n and this is how the test area looks like:

It looks like one magenta nozzle is spewing ink at an angle. At first I thought it was an electrical problem and somehow one nozzle got shorted to another. But this looks more like the ink from that nozzle gets deposited onto the paper a bit to the top and left from where it should be. The line from that nozzle looks a bit more blurry than the other ones, which also suggests that something is interfering with the ink flow.

I don't remember seeing something like that before. Anyway, I just thought that was interesting. So far it didn't bother me too much and maybe it will go away during printer's regular self-cleaning cycles. If it doesn't fix itself I'll probably try to clean it up manually.

Posted by | Categories: Life | Comments »

## Parking the CubieTruck

19.09.2020 15:30

Back in 2013 I bought the CubieTruck, a single-board computer based on the Allwinner A20 ARM system-on-chip. Soon after I got it up and running with Debian I began using CubieTruck as a tiny home server. I eventually migrated this blog to it as well after my other server was knocked off-line by ice. It's been happily running on a shelf for almost 7 years now and has been an incredible value for its original 100 € price. It has been showing it's age though and with Debian Jessie running out of security support it was time to move on. I had a spare Zotac CI327 ready as a replacement and a few weeks ago I finally managed to move the last services off CubieTruck.

My CubieTruck really had a very good track record as far as reliability goes. It currently has a 464 day uptime and in recent memory only got reset because of a short power outage. In its early days I had problems with CRC errors on the SATA bus. This mostly got resolved after I changed to stock cable that came with it with a different one. At least it never again caused filesystem corruption (that I know of). The UDMA CRC error count reported by SMART currently sits at 276. It still incremented by 1 every once in a while, most often when I was doing something in the physical vicinity of the CubieTruck. I suspect the SATA signal integrity was still pretty marginal, even with a different cable.

Unfortunately, the long uptime is also a symptom of the largest problem I had with it: hugely outdated kernel. The SoC requires running a special Allwinner fork of the Linux kernel and it was soon severely outdated. I'm very grateful that Daniel Andersen kept the kernels updated with upstream patches for as long as the 3.4 branch was officially supported by kernel developers. Still, the last released one which is running on it right now, 3.4.112, is ancient by modern standards.

There was an effort to merge all the required code to the upstream kernel. As far as I remember it did come to a point where running the upstream kernel was perfectly viable, but I never did it. The problem was that NAND flash was never well supported. CubieTruck boots off 8 GB of on-board flash. Without support for it in the kernel you can't access the boot partition from Linux, which in practice means no easy kernel updates, which is the whole point. The alternative is to boot off an SD card, but I wanted to avoid that at all costs.

The machine I'm replacing CubieTruck is a Zotac Zbox nano CI327. It is itself outdated at this point and has a quad-core Celeron N3450 and 4 GB of RAM. I've also installed a Kingston 120 GB SSD (SA400S37120G). Unfortunately I haven't done a comprehensive HTTP benchmark comparison like I did last time I moved my blog installation. Mostly because I forgot about it, but there's also the fact that I don't know how to properly benchmark a HTTP service anymore. Apache Benchmark I used last time doesn't give representative results because it doesn't support SSL session caching.

I did measure how long it takes to rebuild the blog though. This is a single-threaded Perl process that builds around 25 MB of HTML files. The following shows user space time as reported by the time utility. I recorded the fastest run out of three on each machine:

CubieTruck Zotac
CPU time to rebuild static pages 51.4 s 9.0 s

As you can see, Zotac really leaves CubieTruck in the dust in this test. The CubieTruck numbers here aren't comparable to my old test. Even though the method was the same, my blog now has more entries and hence takes more effort to build. Also, in my previous test the CubieTruck was still running of an SD card, before I installed a SATA SSD.

As far as HTTP performance goes, I did notice this nice drop in the page load time graph after migration to the Zotac. This is from a Munin plug-in that runs on some other host on the Internet and requests my blog's homepage. On the other hand, server's 90 percentile response times for regular traffic haven't changed noticeably. In any case, CubieTruck was already fast enough to handle HackerNews home page traffic without major problems.

In conclusion, CubieTruck has been a joy and one of those machines that leave a lasting good impression. Even though it's inviting to scavenge its SSD I will very likely keep it around in case I need an ARM build machine or something similar. As far as I know it is still one of the rare ARM-based single-board computers that has decent storage performance due to it's native SATA interface. It's unfortunate that later Allwinner SoC versions abandoned it. It was only recently that the new Raspberry Pis with USB 3 got significantly better throughputs, although I would still like to see some long-term reliability figures for USB 3-attached storage.

Posted by | Categories: Life | Comments »

## Transmission line mismatched on both ends

14.09.2020 20:30

In one of my previous posts I mentioned a result of a RF gain-versus-frequency measurement that looked like a sine wave. I said the sine wave probably means that there is some impedance mismatch in the measured signal path. I wasn't completely sure back then so I did a quick refresh on transmission line theory. Indeed, if you have a transmission line that is driven by a mismatched source and also has a mismatched load on the other end at the same time, the amplitude on the load will vary periodically in relation to the signal frequency.

Consider the following circuit. You have a sine wave source ug with a source impedance that has a reflection coefficient Γg. The source is connected through a transmission line to a load with its own reflection coefficient Γl. The transmission line has a characteristic impedance Z0, length d and propagation speed c. I've also marked the forward voltage wave in the transmission line uf and the reverse voltage wave ur.

We keep the amplitude of the signal source ug constant and vary the frequency. If we measure the amplitude of the signal on the load ul the amplitude will vary with applied frequency in a sinusoid like on the following graph. Note that the horizontal axis is frequency, not time. The vertical axis shows amplitude, not instantaneous voltage:

The amplitude on the load ul will show peaks every Δf. At the peaks, the signal will have the amplitude umax and in the valleys it will have the amplitude umin.

It turns out that Δf has the following relation to transmission line length and propagation speed:

\Delta f = \frac{c}{2 d}

This equation can be useful in debugging since it can point to the part of the signal path where the mismatch is happening. For example, if you know the propagation speed it allows you to calculate the length of the mismatched segment.

The ratio of the maximum and minimum amplitude (in linear scale) on the load depends on the reflection coefficients at the source and the load ends of the transmission line:

\frac{u_{max}}{u_{min}} = \frac{1 + |\Gamma_g\Gamma_l|}{1 - |\Gamma_g\Gamma_l|}

This last equation is interesting. At the first glance it makes sense. If either of the ends is perfectly matched (Γg = 0 or Γl = 0), then the ratio is 1 and there is no dependency on frequency. This is the expected result. A transmission line that is mismatched on only one end still has a non-optimal power transfer but the amplitude on the load is constant and doesn't depend on the signal frequency.

A signal flow diagram, similar to the one mentioned in this article, can also be used to verify its correctness.

The equation for the ratio of amplitudes on the load is very similar to the equation for the voltage standing wave ratio:

\mathrm{VSWR} = \frac{1 + |\Gamma_l|}{1 - |\Gamma_l|}

In a VSWR calculation you only have a mismatched load. In the case where you have two mismatched ends, it then kind of makes sense that you multiply both reflection coefficients together.

However if you think about it, it's quite weird that it turns out this way. In the VSWR case you are calculating the ratio of the sum and difference of the forward wave (uf = 1) and the reflected wave (reflected once off the load, hence ur = Γl). Since the source is perfectly matched in that case, the reflected wave doesn't reflect back the second time. It's obvious that the formula for the ratio is this simple.

On the other hand in the case where both the source and load are mismatched, you get an infinite number of reflections. When the source first gets switched on, the first forward wave driven by the source reflects off the load with Γl. When the reflected wave gets to the source it reflects off the mismatched source impedance with Γg and travels back to the load superimposed on the original forward wave. This combination of the signal driven by the source and the first reflection again reflects off the load and so on to infinity. The steady-state amplitude of the signal on the load is the sum of all those infinite reflections.

If you think about it this way, it's surprising that the ratio ends up being this simple equation that is the same as if the signal only reflected once from the load and once from the source.

Posted by | Categories: Analog | Comments »

## P57 feed-through terminator

26.08.2020 17:57

A quick note about this thing. It's a BNC feed-through terminator I've bought for cheap off AliExpress when I was on a kind of an RF accessory buying binge. After months of shipping delays it recently dropped into my mailbox. This one is marked "P57 load resistor 50 Ω". I've seen very similar looking devices being sold under various other names and brands. I've bought it because my TDS 2002B scope does not have a low-impedance input option.

The label says that the terminator is rated from DC to 1 GHz. The analog bandwidth of my scope is only 60 MHz, so that shouldn't be an issue. The DC resistance between signal pin and ground measures exactly 50.0 Ω on my Keysight U1241C. That's a good sign that it doesn't just have a standard carbon 51 Ω resistor inside.

The build quality looks fine at the first glance, although with the plastic body I wouldn't use this where any kind of significant power would be dissipated on the load.

This is the result of a quick test I did. I connected the ERASynth Micro to the oscilloscope CH 1 over a coax cable. The red plot shows the signal amplitude measured at various frequencies without the terminator (so terminated with 1 MΩ at the scope's probe input). The blue plot shows the amplitude with the cable terminated with P57 on the scope end. The amplitudes were measured with the FFT function and hence only take into account the base frequency, without any harmonics.

The ERASynth Micro was always set to 0 dBm output level. If everything would be perfect, the blue plot would be at -13 dBV and the red plot would be 6 dB higher (twice the amplitude). Falling amplitude beyond 60 MHz is expected because of the limited analog bandwidth of the scope's front end.

I've measured between 8 and 5 dB difference between the terminated and unterminated amplitudes, which seems fine. Or at least not excessively wrong. There's a lot of unknown errors in this measurement. Cable and adapter loss, ERASynth Micro output matching and level accuracy and so on.

In conclusion, it does what it says in the description and seems good enough for my purpose.

Posted by | Categories: Analog | Comments »

## Vector measurements with the rtl-sdr, 5

18.08.2020 18:01

Here is a quick update on my project to measure the phase of a reflected RF signal using rtl-sdr and what is basically a simple home-brew vector network analyzer. I'm using a cheap RF bridge from eBay as the directional element in the measurement and a board I've developed to multiplex two signals into the rtl-sdr's single ADC. In my last post I've assembled the time multiplex board. I've also shown some basic tests of its performance using the ERASynth Micro microwave synthesizer, such as signal attenuation on the PCB traces and cross talk through the switches. Now I finally have tests to show of the complete vector measurement system, although only in pass-through (i.e. S12) mode without using the reflection bridge.

To test out if I can correctly measure the phase of the signal using my system, I performed several tests where I connected the DUT IN to OUT with different lengths of a coaxial cable. In theory, different lengths of the cable should introduce different delays into the signal. I should be able to measure the delay as a difference in the phase of the signal arriving into the DUT IN input.

I've swept the frequency of the signal generator from 100 to 1000 MHz, which covers most of the useful region of the rtl-sdr. For each frequency, I performed the vector measurement using the delay-and-divide method I outlined earlier. I ran the test with three lengths of SMA patch cables I had at hand: 15, 30 and 45 cm.

The measured amplitude in all cases should be around +10 dB. The reference signal, against which the input signal is compared, is attenuated by 10 dB in the multiplex board. Because of this, an unattenuated 0 dB signal passing between DUT OUT and IN compared to a -10 dB reference is seen as +10 dB by my device. I did this to optimize the receiver dynamic range, since many directional couplers and RF bridges have around 10 dB of coupling.

Anyway, this measurement is about what I would expect. For all lengths of cable the mean is around 10 dB. Cable loss is too small to be visible. The variations in amplitude of around ±2 dB depending on the frequency are more than I would like. They are probably because of multiple bad impedance matches somewhere in the signal path. I've also seen these in my previous measurements.

This is the phase component of the same measurement. It shows that the input signal lags versus the reference and that the phase difference increases with frequency. It's also clearly visible that the slope depends on the length of the cable. Such a linear phase characteristic is exactly the expected result for a constant signal delay. The phase plot has been unwrapped here using the numpy.unwrap method.

By dividing the measured phase with the angular frequency, the measurement can be shown directly in terms of time delay:

This is a very nice result. Each lengthening of the cable by 15 cm increased the average time delay by about 0.8 ns. This gives a relative velocity of propagation through the cable of around 0.63 c, which is a reasonable number. I don't have the exact data for my no-name patch cables. A cable with a solid polyethylene dielectric, typical for low-end cables, has the velocity factor of 0.66. This is close enough to my result and the electrical length of my cables isn't very well defined anyway.

Another interesting thing I can get from these results is the delay for a theoretical cable of length 0 cm. This is the intrinsic signal delay in my system and is about 0.15 ns based on these measurements. This should correspond to the difference in electrical lengths on my multiplex board between the reference signal path and the DUT connector path. If I estimate the velocity factor of the coplanar waveguides to be:

VF = \frac{1}{\sqrt{\varepsilon_r}} = 0.48

This gives a length difference of about 22 mm. This is again a reasonable result. By measuring PCB trace and connector lengths I roughly estimate the real difference to be about 30 mm.

In conclusion, I'm quite happy with these results. They show that my basic time multiplex idea works correctly for vector measurements. As far as the whole system is concerned there are still several rough spots however. Clock recovery code still needs some more polishing since running it on real data revealed some corner cases that didn't show up in simulations. Thankfully I see nothing fundamentally wrong with it as far as I can see and fixing it should be just a matter of writing some better software.

The bigger problem is the bad overall RF performance of the multiplex board. I've discussed before that there seems to be something very wrong with impedance matching which causes large deviations in measured signal amplitude. I still haven't completely figured out what's wrong there. One mistake I did found on the PCB design was that my coplanar waveguides don't have the width much larger than height over the ground plane (see e.g. slide 41 in RF/Microwave PC Board Design and Layout). This is one of the assumptions of the equations for their Z0 I used. This error might be what's causing some of my problems, but fixing it unfortunately means making a new PCB.

Another, even more puzzling problem, is that the RF bridge seemingly loses its directivity when used in this system, even at low frequencies. Since I made this vector measurement system specifically for reflection measurements (S11) this is kind of disappointing. I don't really understand yet why that happens. It's not because of switch cross-talk. I've measured that and it should be negligible. The mismatches on the board also shouldn't be affecting the bridge in this way, especially at low frequencies where they don't have much effect. Scalar measurements work just fine with rtl-sdr and ERASynth Micro. I've also measured that my bridge has reasonable directivity below 1 GHz when used without the multiplex.

Posted by | Categories: Analog | Comments »

## Vector measurements with the rtl-sdr, 4

31.07.2020 15:29

I'm developing a method for performing vector reflection measurements using a cheap, single channel software-defined radio receiver. To measure the phase of the reflected signal I need to receive two RF signals coherently, a reference and the actual measured signal. I'm using time multiplexing to do that since I'm restricted to only a single analog-to-digital converter. In my last post I've described a circuit I developed that performs the multiplexing in the analog domain. The demultiplexer as well as all other signal processing is done by software in the digital domain.

I ordered the bare printed circuit boards from AISLER using their 2-layer/HAL surface finish process. This is the first time I've used their service. I was looking to have the boards made in Europe since I'm seeing large shipping delays recently due to COVID-19 (I'm still waiting for some components I ordered from overseas back in April). After looking at a few local PCB prototyping services, AISLER looked like by far the best bet. I got the boards in my mailbox in less than a week for a price that was comparable to ordering them from China.

Between the HAL and ENIG surface finishes offered I decided on HAL since it should have better performance at high frequencies. I also removed the soldermask from the top of the 50Ω coplanar waveguides in an attempt to further reduce the losses. I was pleasantly surprised that AISLER offers precise stackup specifications, including εr. That's something that I've often missed in similar services and it probably made my trace impedance calculations somewhat more accurate. However this wasn't manufactured as a controlled impedance board.

I assembled the boards manually using a hot air station. The boards had some leftovers from panelization breakaways right at the locations of the edge-mounted SMA connectors. I had to smooth the edges with some sandpaper to get the connectors to fit nicely. The QFN packages of the MMIC switches were also a bit tricky to solder, but I recently got a lot of experience soldering tiny AVRs at work so that wasn't too troublesome. The only thing I'm never completely sure with QFNs is how well the ground pad gets connected. The datasheet says that is important for good RF performance of the switch.

The big question of course is whether it works or not. For testing I've connected the board to my rtl-sdr receiver and the ERASynth Micro microwave synthesizer. I've used short, rigid male-to-male SMA adapters between the instruments to keep down the losses. I've also shorted the device-under-test in/out (DUT) ports with a short length of a coax cable. In this setup the expected 100 Hz 3-state multiplex pattern is visible on the rtl-sdr baseband. The board switches between an off state (no signal), the reference signal which is the input attenuated by 10 dB, and the signal that passes through the DUT (which in this case is the full input signal, minus any attenuation in the coax cable):

So the basic multiplex functionality appears to be working, but is it any good? What are the losses and crosstalk in the switches and the PCB? Estimating the RF performance is where it gets a bit tricky. I've attempted to do that using the setup pictured above. To estimate the attenuation of the signal I've swept the input frequency and measured the received signal power at the rtl-sdr using rtl-power-fftw. I've performed the same measurement with the multiplex board locked into dut state and into ref state.

Since the rtl-sdr isn't a calibrated power meter I've also performed a third measurement where I directly connected the rtl-sdr to the signal generator using one of the rigid SMA adapters. This was the reference against which I compared the other two measurements. It's shown as 0 dB and the dotted black plot in the figure above. This way I subtracted any variability in the rtl-sdr sensitivity versus frequency. In all cases I manually locked the gain of the rtl-sdr to 14 dB.

Ideally, I would expect the blue dut plot to be near 0 dB. It should show only the loss in the PCB, switches (around 0.7 dB according to the datasheet) and the coax cable. Similarly, the ideal orange ref plot should be near constant -10 dB, because the board includes a 10 dB attenuator in that signal path.

As you can see, the reality is not nearly as perfect as the theory. The gain of both signal paths varies quite a lot with frequency. There seem to be one slowly varying component that's common to both paths (with minimums at around 600 MHz and 1600 MHz) and one that's only on the dut path (with periodic minimums every 250 MHz or so). This seems to suggest that there is more than one bad impedance match somewhere. It's not necessarily in the design of the board itself. I don't know how well ERASynth Micro is matched to 50Ω and I also don't have any specs for the rtl-sdr (I've been speculating on it's return loss before). I also don't have much confidence in the quality of SMA adapters and the coax cable I was using.

Finally, this is the result of the crosstalk test I did. Here I'm comparing the signal power with the board in the off state (blue plot) with the receiver noise floor (dotted black plot). The measurement in the off state was done with the same setup as above. I've measured the receiver noise floor by terminating the rtl-sdr input with a 50Ω terminator. As you can see, both plots are basically identical, which shows that there's no significant leakage of the signal when the switches are turned off.

A better way to show this result is by subtracting the noise floor from the off measurement in linear scale. This new plot now gives directly the isolation of the signal when the board is in the off state. 0 dB on the graph is again the input signal level, same as on other graphs.

Ideally, this plot would be at minus infinity. It is not because the two switches are not perfect (around 60 - 70 dB isolation per switch according to the datasheet) and some signal also probably leaks through the PCB and the space around it. When I was measuring this I also realized that the layout where I have the signal generator and the detector right next to each other might not have been the best choice to keep isolation high. Neither ERASynth Micro nor the rtl-sdr have metallized enclosures, so some signal might also leak out that way.

In any case, I think 50 dB isolation is more than good enough for my purpose. It goes down to 40 dB near 2 GHz, but that might be because rtl-sdr sensitivity is getting really bad in that range. This measurement is not very precise, since the crosstalk signal is below the noise floor of the receiver. It's unlikely that I will be using this board with bridges or directional couplers that would have directivity better than 40 dB. Hence isolation in the multiplex board shouldn't be the limiting factor in the accuracy of my measurements.

I would like to better understand where the unexpected variations in the signal path attenuation come from. Did I make an error in the board design or is it caused by cables and other equipment I'm using? I have some more experiments planned related to this. I also still need to take my signal processing code out of the simulation I wrote and use it on the data from the real hardware. In the end the only thing that matters is the quality of the final measurement result.

Posted by | Categories: Analog | Comments »

## My experience with Firefox containers

25.07.2020 19:17

For the past months I've been using the Firefox Multi-Account Containers (MAC) extension. This extension makes it possible to maintain several isolated browser states at a time. By a browser state I mean everything that websites store in the browser: cookies, local storage and so on. In practical terms that means logins on websites with "remember me" functionality, shopping baskets, advertisement network IDs and other similar things. You can setup the extension so that certain websites always open in a certain container. The Temporary Containers (TC) extension further builds upon MAC by dynamically creating and deleting containers as you browse in an attempt to keep the browser from accumulating long-term cookies.

I have a few reasons to use such a setup: First is that I commonly use company and personal accounts on websites. I want to keep these logins completely separate for convenience (no need to constantly log-out and log-in to change accounts). I've also once had an instance where a web shop silently merged accounts based on some hidden browser state. Even though that was most certainly unacceptable behavior on that web shop's end I would like to avoid another case where my personal projects end up on corporate order history.

The second reason is privacy and security. I think is harder to exploit weaknesses in browser's cross-site isolation, or do phishing attacks, if the default browser instance I'm using doesn't store authentication cookies for any important accounts. The fact that most websites see a fresh browser state without cookies also slightly raises the bar for tracking my browsing habits between different websites.

I used to have Firefox set so that it cleared all cookies after every session. This took care of accumulating cookies, but meant that I needed to continuously re-login to every website. This wasn't such a inconvenience on my end. However recently more and more websites started treating new logins from a cookie-less browser as a security breach. At best I would constantly get mails about it, at worst I would get accounts blocked or thrown into a captcha-hell for unusual behavior.

I would still prefer to have this setting enabled for default browsing, combined with a few permanent containers for websites that do this sort of unusual behavior detection. However MAC doesn't allow you to set this independently for each container. In theory, using TC fixes that problem. Opening up a website in a fresh temporary container that is used once and then deleted after closing the browser tab has the same effect as clearing cookies.

My foremost problem with containers is that in practical use they don't really contain the state between websites. It's trivial to make a mistake and use the wrong container. If I click a link and open it in a new tab, that tab will inherit the container of the original tab. The same also happens if you enter a new URL manually into the address bar. It's very easy, for example, to follow a link a coworker shared in a web chat and then spend an hour researching related websites. If I forget to explicitly open the link in "a new Temporary Container" that browsing will all happen in the permanent container that I would prefer to only be used for the web chat service. The tab titles get a colored underline that shows what container they are using, but it's easy to overlook that.

All it takes is one such mistake and the container is permanently polluted with cookies and logins from unrelated websites that I would not like to have in there. These will persist, since to retain the web chat login I have to set the browser to retain cookies indefinitely. Over time I found that all permanent containers tend to accumulate cookies and persisting logins for websites I frequent which defeats most of the benefits of using them.

There is the "Always Open This Site in..." option, but it works the other way I would want it to. You can define a list of websites that need to be opened in a certain container, but you can't say that a website outside this list needs to be opened outside of a container (or in a Temporary Container). The "Always Open This Site in..." also has the additional problem that it's annoying if I want to use a website in two containers (e.g. work and personal ones). In that case I have to constantly click through warnings such as this:

Again, the Temporary Containers extension attempts to address this. There is a group of preferences called "Isolation". In theory you can set this up so that a new temporary container is automatically opened up when you navigate away to a different website. It also takes effect when using the permanent containers.

It's possible that I don't understand exactly how this works, but I found any setting other than "Never" to not be useful in practice. The problem is with websites that use third-party logins (e.g. a website where you log in with your Google account, but is not hosted under google.com, I'm guessing through a mechanism like OpenID). Isolation completely breaks this authentication flow since the log-in form then opens up in a new container and whatever authentication tokens it sets aren't visible in the original one.

Finally, both extensions are somewhat buggy in my experience. For example, I'm occasionally seeing tabs opened in no container at all even though I have Automatic Mode turned on in TC, which should automatically re-open any tab that's not in a container in a temporary one. I can't find a reliable way to reproduce this, but it seems to only happen with tabs that I open from a different application and might be related to this issue.

Cleaning old temporary containers often doesn't work reliably. Again, it's hard to say what exactly isn't working and if that's one of the known bugs or not. I often find that the browser has accumulated tens of temporary containers that I then need to clean up by hand. This is especially annoying since a recent update to MAC made container deletion unnecessarily tedious. It takes 4 mouse clicks to delete one container, so deleting a few tens is a quite a chore.

There is also a very annoying couple of bugs related to Firefox sync. MAC allows the container settings to be synchronized between all Firefox installations linked to the same Firefox account using Mozilla's servers. This is an incredibly useful feature to me since I commonly use multiple computers and often also multiple operating systems on each one. Needless to say, synchronizing browser settings manually is annoying.

Unfortunately, running MAC and TC with sync enabled runs the risk of permanently breaking the Firefox account. Because of the bugs I linked above it's very easy to accumulate so many temporary accounts that you exceeded the storage quota on the sync server. It seems that once that happens the sync server will not even let you delete the offending data that's stored there before erroring out. The result is that add-on sync will no longer work on that account and even cleaning up your local setup afterwards will not fix it.

In conclusion, I'm not very happy with this setup (or the modern web in general, but I digress). Multi-Account Containers is certainly an improvement over a setup with multiple separate Firefox profiles that I was using previously. It does work well enough for keeping work and personal accounts separate. On the other hand, it doesn't seem to be very effective in isolating cookies and other state between browsing sessions. I'm not sure what exactly a better solution would be. I feel like I'm leaning more and more towards a setup where I would just use two completely separate browsers. One for heavy web apps that require a login, persistent local storage, Javascript and another one that's more aggressive at cleaning up after itself for everything else.

Posted by | Categories: Code | Comments »

## Vector measurements with the rtl-sdr, 3

12.07.2020 18:48

After doing some scalar reflection measurements using an rtl-sdr and an RF bridge I recently started exploring the possibility of capturing phase information as well using a similar setup. I came up with a relatively simple method that does most of the signal processing in software. I already validated that the method works well enough in simulation. All I need now to try it out in practice is a simple multiplex circuit board. I need that to coherently record two RF signals with rtl-sdr's single channel analog-to-digital converter.

At the time of my last post I already had most of the circuit sketched out on paper and the basic calculations done. I've spent the last couple of days finishing up the design and transferring it from paper into the computer. This is a 3D render of the current draft of the circuit board:

It's a two-layer design on a 1.6 mm FR-4 substrate. All RF and almost all the other tracks are routed on the top layer, leaving the bottom for a mostly uninterrupted ground plane. I'm not sure yet about the surface finish and solder mask. Signal connections are using edge-mounted SMA connectors.

I had to revise the schematic a few times when I was making the PCB layout. The 50 Ω coplanar waveguides can't overlap or change layers and I wanted to have the RF part of the circuit laid out as cleanly as possible. Fortunately, the input and output ports on the MMIC switches I'm using are interchangeable. This gave me enough flexibility to come up with a combination of ports where such a layout was possible. By a lucky coincidence the exact combination I ended up using also inverted the sense of one switch. This had an added benefit that I could omit an extra quad-NOR gate from the driver circuit.

The rest of the circuit is quite straightforward. I'm using a HEF4017 Johnson counter to drive the switches in the correct sequence. I ended up going with a three-state "off-ref-dut" switching cycle to aid the clock recovery like I mentioned in one of my earlier posts. There's a selector switch that allows the sequence to be driven by an internal oscillator, a manual button or an external clock coming into the fifth SMA connector on the bottom right of the board.

I've added the manual button to aid in testing. It will allow me to lock the RF circuit in a specific configuration and perform measurements on that specific signal path. Two LEDs show the currently selected path.

The internal oscillator is a simple 100 Hz astable multivibrator using a low-voltage variant of the classic 555 timer. Its frequency will be very inaccurate, but that shouldn't be a problem. The software needs to do full clock recovery anyway over several full switching cycles and the clock only needs to be roughly in the vicinity of 100 Hz and stable for around 10 cycles. If it later turns out that I've missed something and do need a better clock source I can still bring it in from an external source.

I probably need to go over the design once more time in case I missed something, but otherwise the PCB layout seems ready to be sent out to a prototyping fab. I getting curious. For the sub-2 GHz frequency range that the rtl-sdr and my current RF bridge can handle I think the hardware should work well enough. For the full 8 GHz rating of the switches I have some more doubts, mainly due to the 10 dB attenuator made from 0603 components and loses in the FR-4 substrate.

Posted by | Categories: Analog | Comments »