Wideband Transmission #6

Happy New Year 2015!

2014 was a bit of a mixed bag here. It's been a transition year for Etherkit, as I reorganize and reorient the business for a renewed push to get the CC1 and other new products to market. I believe that good things are beginning to happen there.

On a personal level, my two boys have been doing fantastic. Noah started preschool and is really enjoying it. Eli is at a bit of a difficult age (the Terrible Twos) and is between baby and little kid, but he's got an amazing personality and is growing up so quickly. Jennifer and I celebrated five years of marriage and 11 years since our first date! Things haven't been perfect in the extended parts of our families, but at least in our household we've all been pretty healthy and have been able to enjoy many blessings.

Si5351A Breakout Board Campaign

There have been a fair number of neat projects I've seen using the Si5351A Breakout Board that I posted on OSHPark, along with my Si5351 Arduino library, which is absolutely wonderful. However, I realize that it's a pain to order PCBs and all of the parts separately, and that a kit or a finished board would be ideal.

I've decided to try something new in order to bring the Si5351A Breakout Board kit to market: we're going to try crowdfunding the first batch of kits. I'm going to set a modest goal to trigger the funding, but all orders will be welcome over the goal amount. In fact, I intend to set a stretch goal at some higher funding level to devote a certain number of hours to improving the Si5351 Arduino library, including:

  • Add tuning from 8 kHz to 1 MHz
  • Add tuning from 150 MHz to 160 MHz
  • Fix the bug that does not allow output over 125 MHz
  • Implement access to the phase register
  • Implement sub-Hz tuning for modes like WSPR
  • Other bug fixes

I also intend on lowering the BOM cost by removing the broadband output transformers, and offering multiple variants of the kit, including the option to add SMA connectors and a TCXO. I'm composing the campaign on Indiegogo right now, and I'm shooting for a launch in about 10 days. I'm hoping to gain experience with this campaign with the goal of using it to fund CC1 kitting later in the year.

Why am I telling you this now? Because I would like to let those of you are are interested in purchasing one (or otherwise interested in supporing Etherkit) get advance notice so that you can order on the first day that the campaign goes live. This will help to give the campaign more momentum and perhaps help to spread the word further. I will be sure to make a blog post here when the campaign goes live and tweet about it as well, so keep an eye on those channels if this is something that intrigues you.

Simple WSPR Transceiver using Si5351A

I came across this simple WSPR transceiver from KC3XM driven by one of my Si5351A Breakout Boards via @wm6h and Dangerous Prototypes. The WSPR transmitter is simply a BS170 driven by one of the Si5351 outputs, which is buffered by a logic gate and keyed by a standard PNP keying switch. Control of the Si5351 and keying of the transmitter is performed by a plain vanilla Arduino Uno (the code has been posted to GitHub).

This looked so simple to build that I had to give it a try. I quickly built up the transmitter portion, tacked on a 10 meter LPF (the original version is for 30 meters), modified the code for my callsign and grid, and changed the Si5351 output frequency to the 10 meter band. The transmitter put out nearly exactly 1 watt of RF (with only about 1.2 watts of DC input total) into 50 ohms and ran quite cool. Hooked up to my Moxon, it had no problem generating spots when pointed east and started on an even minute so as to properly synchronize. Fun stuff!

Generating PSK with an Arduino

If you haven't been following the blog of KO7M, you should be. Jeff has been doing a lot of experimentation with with NB6M and other home experimenters in Washington state, especially with stuff like the Minima and using microcontrollers in ham radio projects.

Lately, Jeff has been working on getting an Arduino to output PSK audio. He has a series of recent posts about it, but these two are probably the most important. The character timing is not quite right yet, but the basics of how to generate PSK via PWM audio signals are here. Good stuff!

Si5351 and Raspberry Pi

Another really great homebrewer blog is M0XPD's Shack Nasties (oh you Brits and your silly names) blog. Paul has been doing a lot of work with the Si5351 as well, and his latest post about the Si5351 is details of how he interfaced it with the Raspberry Pi. Excellent information to have, as the RPi is of course much more powerful than your garden variety Arduino.

Si5351A Investigations Part 3

Since the previous Si5351 Investigations post, I've made quite a bit of progress integrating the Si5351 into a grabber receiver. First, let's look at the grabber receiver architecture and how the Si5351 is used in it.

GrabberRXBlockDiagram

Above you can see the basic block diagram of the receiver. The front end has two switchable plug-in bandpass filter modules (which is switched by a pair of TI TS5A3157 analog switch ICs controlled by the AVR microcontroller). An ADE-1 diode-ring mixer is fed directly from one of the Si5351 ports set for the lowest output level (which is about +8 dBm). The pair of IF amplifiers are TriQuint AG203-63G MMICs, and the actual IF filter is a 6-crystal ladder filter with a bandwidth of 3 kHz (filter plots provided below). Another ADE-1 is used as the product detector, with the BFO signal provided by another output port on the Si5351. Finally, the recovered audio is amplified to line level by a NE5532 op amp and delivered to a 3.5 mm stereo socket by way of a transformer in order to provide good ground isolation between the receiver and sound card.

grx1 grx2

As an interesting side note, you can see my modular bandpass filter boards below. They are your standard double-tuned circuits placed on a 20 mm x 50 mm piece of copper clad, with 0.1 in SIP headers soldered to pads cut out of the material with a rotary tool. There are some extra pins which are reserved for a future module identification system.

DSCN0641

Happily, the receiver mostly worked as expected right out of the gate. A few minor tweaks need to be made, such as in the gain of the AF amplifier, but I'm pretty happy with the results so far. Although it's my intention to pair this receiver with a Raspberry Pi running LOPORA in my garage, right now the receiver is sitting on my bench capturing WSPR RF on various bands, and looks to be doing a fine business job doing that. Frequency stability looks at least as good as my IC-718 on WSPR, based on an eyeball assessment of WSPR spots.

WSPR

The Si5351 seems to do a bang-up job acting as both the VFO and BFO. What's nice is that I can easily switch sidebands merely by changing the output frequency of the CLK1 BFO output with one line of code. I haven't seen any indications of spurious products affecting the receiver yet.

My Si5351A library for avr-gcc is still pretty rough, so I'm not quite ready to publish it yet. Next up on my todo list is to get it in a state where I'm ready to put it up on GitHub, then implement the USB control protocol and client program so that the grabber receiver can be tuned via command line (especially handy when using SSH).

At this point, I'm fairly confident that the Si5351 will make a very fine oscillator system for a grabber receiver. My next line of investigation is to look at the temperature stability of the Si5351 via a thermal chamber lashup. I've got a nice Styrofoam cooler, an Arduino knockoff, a 120 V relay shield, a temperature sensor, and a frequency counter I can read via serial port, so I just need a heat source (probably in the form of an incandescent bulb) and I should be good to go. Keep watching for more experiments!

Fancier Minecraft Pi Game of Life

[pe2-image src="http://lh5.ggpht.com/-8gmHvJD2jyc/USH1uxHIu4I/AAAAAAAAC1I/ptVGYQdSylk/s144-c/IMG_20130218_012053.jpg" href="https://picasaweb.google.com/100175922620194527589/InstantUpload#5846223975109671810" caption="IMG_20130218_012053.jpg" type="image" alt="IMG_20130218_012053.jpg" ]

I spiffed up my last bit of Minecraft Pi Edition code by making the Game of Life fit into a smaller area of the world, making the world grid and live cells easier to see (by making dead cells Obsidian and live cells Diamond Blocks), and even adding a nifty little stepped wall around the playing field. In the two photos, you can see the new Game of Life as seen from the ground inside of the playing field and hovering above it. It runs a fair amount faster now that it's only updating a 64x64 grid. Still not going to break any speed records (even from 1980) but it's a bit more fun to play with now.

[pe2-image src="http://lh3.ggpht.com/-h_Gc8m4Sl-Y/USH1qSqIu3I/AAAAAAAAC08/EO05SuWfSE4/s144-c/IMG_20130218_011949.jpg" href="https://picasaweb.google.com/100175922620194527589/InstantUpload#5846223898215496562" caption="IMG_20130218_011949.jpg" type="image" alt="IMG_20130218_011949.jpg" ]

 

# pilife.py
#
# Jason Milldrum
# 18 Feb 2013
#
# www.nt7s.com/blog

import minecraft.minecraft as minecraft
import minecraft.block as block
import numpy
import random

mc = minecraft.Minecraft.create()

# World size in x and z axes
#worldSize = 64

# Bounds of x and z axes
negLimit = -32
posLimit = 31

# Bounds of y axis
yNegLimit = -64
yPosLimit = 64

# Y coord of Life world floor
worldFloor = 0

# Number of steps in the surrounding wall
maxWallHeight = 5

# Initialize the Life world
theWorld = numpy.zeros((posLimit - negLimit + 1, posLimit - negLimit + 1), dtype=numpy.bool)
theNextWorld = numpy.zeros((posLimit - negLimit + 1, posLimit - negLimit + 1), dtype=numpy.bool)
for x in range(posLimit - negLimit):
	for y in range(posLimit - negLimit):
		theWorld[x][y] = random.randint(0,1)

# Clear everything at the world surface and above inside the Life play area
mc.setBlocks(negLimit - (maxWallHeight * 2), worldFloor, negLimit - (maxWallHeight * 2), posLimit + (maxWallHeight * 2) - 1, yPosLimit, posLimit + (maxWallHeight * 2) - 1, block.AIR)

# Let's create stairsteps around the Life world

# Start with the +x direction
x = posLimit
stepHeight = worldFloor
# Up
while stepHeight <= maxWallHeight:
	mc.setBlocks(x, worldFloor, negLimit - stepHeight - 1, x, stepHeight, posLimit + stepHeight, block.BEDROCK)
	x += 1
	stepHeight += 1
# Down
stepHeight = maxWallHeight
while stepHeight >= worldFloor:
	mc.setBlocks(x, worldFloor, negLimit - stepHeight - 1, x, stepHeight, posLimit + stepHeight, block.BEDROCK)
	x += 1
	stepHeight -= 1

# Now the -x direction
x = negLimit - 1
stepHeight = worldFloor
# Up
while stepHeight <= maxWallHeight:
	mc.setBlocks(x, worldFloor, negLimit - stepHeight - 1, x, stepHeight, posLimit + stepHeight, block.BEDROCK)
	x -= 1
	stepHeight += 1
# Down
stepHeight = maxWallHeight
while stepHeight >= worldFloor:
	mc.setBlocks(x, worldFloor, negLimit - stepHeight - 1, x, stepHeight, posLimit + stepHeight, block.BEDROCK)
	x -= 1
	stepHeight -= 1

# Next the +z direction
z = posLimit
stepHeight = worldFloor
# Up
while stepHeight <= maxWallHeight:
	mc.setBlocks(negLimit - stepHeight - 1, worldFloor, z, posLimit + stepHeight, stepHeight, z, block.BEDROCK)
	z += 1
	stepHeight += 1
# Down
stepHeight = maxWallHeight
while stepHeight >= worldFloor:
	mc.setBlocks(negLimit - stepHeight - 1, worldFloor, z, posLimit + stepHeight, stepHeight, z, block.BEDROCK)
	z += 1
	stepHeight -= 1

# Finally the -z direction
z = negLimit - 1
stepHeight = worldFloor
# Up
while stepHeight <= maxWallHeight:
	mc.setBlocks(negLimit - stepHeight - 1, worldFloor, z, posLimit + stepHeight, stepHeight, z, block.BEDROCK)
	z -= 1
	stepHeight += 1
# Down
stepHeight = maxWallHeight
while stepHeight >= worldFloor:
	mc.setBlocks(negLimit - stepHeight - 1, worldFloor, z, posLimit + stepHeight, stepHeight, z, block.BEDROCK)
	z -= 1
	stepHeight -= 1

# Set the player right in the middle of the world
mc.player.setPos(0, worldFloor, 0)

# Main processing loop
while True:
	# Display theWorld
	for x in range(posLimit - negLimit):
		for y in range(posLimit - negLimit):
			if theWorld[x][y] == True:
				mc.setBlock(x + negLimit, worldFloor, y + negLimit, block.DIAMOND_BLOCK)
			else:
				mc.setBlock(x + negLimit, worldFloor, y + negLimit, block.OBSIDIAN)

	# Check number of neighbors alive
	for x in range(posLimit - negLimit):
		for y in range(posLimit - negLimit):
			
			if x == 0:
				xMinus = posLimit - negLimit
			else:
				xMinus = x - 1

			if x == posLimit - negLimit:
				xPlus = 0
			else:
				xPlus = x + 1

			if y == 0:
				yMinus = posLimit - negLimit
			else:
				yMinus = y - 1

			if y == posLimit - negLimit:
				yPlus = 0
			else:
				yPlus = y + 1

			alive = 0			

			if theWorld[xPlus][yPlus]:
				alive += 1
			if theWorld[x][yPlus]:
				alive += 1
			if theWorld[xMinus][yPlus]:
				alive += 1
			if theWorld[xPlus][y]:
				alive += 1
			if theWorld[xMinus][y]:
				alive += 1
			if theWorld[xPlus][yMinus]:
				alive += 1
			if theWorld[x][yMinus]:
				alive += 1
			if theWorld[xMinus][yMinus]:
				alive += 1

			# Calculate which cells live and die in next generation
			if theWorld[x][y] == False:
				if alive == 3:
					theNextWorld[x][y] = True
			else:
				if alive < 2:
					theNextWorld[x][y] = False
				elif alive > 3:
					theNextWorld[x][y] = False
				else:
					theNextWorld[x][y] = True
	# Copy array
	theWorld = theNextWorld.copy()

Conway's Game of Life in Minecraft Pi Edition

Also known as "The slowest implementation of the Game of Life in 2013". This is what happens when you have insomnia.

[pe2-image src="http://lh3.ggpht.com/-pIMUUJNK__k/URzHojTQSAI/AAAAAAAACxQ/MCZeLIlpebE/s144-c/IMG_20130214_031548.jpg" href="https://picasaweb.google.com/100175922620194527589/InstantUpload#5844765915904755714" caption="IMG_20130214_031548.jpg" type="image" alt="IMG_20130214_031548.jpg" ]

What I did was first clear out the entire world, then place a plane of glass across the entire world at y=1. The actual Life cells are Cobblestone blocks on the y=0 plane (the grid is on the Minecraft x-z axis). The Life grid is initialized with a random seed, then set off to work. This code for the Game of Life is about the dumbest and slowest implementation there is. I've done no optimization at this point. It only updates about one generation (over the entire world) every few minutes. But it does seem to work, as you can see above.

Next time I need a break from electronics, I'll refine the code and post it again (or you can follow the Gist). It's way too slow to run the entire world as a Life simulation, so I think I'll just clear out a 64x64 space in the middle of the world and confine the world to that size, which should make things run about an order of magnitude faster, I would hope. I know, this is crap code, but I'm still trying to really get into the Python frame of mind and this was a quick hack any way.

I'll let this thing run for a while and post a screenshot of the evolved world to Twitter and G+ later on. Also, thanks to the shoutout from the new http://mcpipy.wordpress.com/ blog!

Exploring Minecraft Pi Edition

If you are a Raspberry Pi enthusiast, you may have seen that Minecraft Pi Edition was officially released yesterday. I don't have the time to game like I used to, so I haven't really played Minecraft, but this version looked intriguing since it's free and it has an open API. So I downloaded it yesterday during a break when both of the boys were napping and give it a quick run. The performance of the game is surprisingly responsive, which shows that the GPU in the Pi is fairly capable, even if stock Raspian X Windows is slow.

With a bit of digging into the very sparse API docs included with the program, and a little Internet help, I was able to get a bit of code up and running. All it does is create a sphere 10 blocks away from the player's location in the Z direction. Here's the quick and dirty code:

You can see the results in this photo:

[pe2-image src="http://lh3.ggpht.com/-mpxhCovV3jw/URqfv6RtGBI/AAAAAAAACwY/jwlRM6KiZb0/s144-c/IMG_20130212_120032.jpg" href="https://picasaweb.google.com/100175922620194527589/InstantUpload#5844159111912822802" caption="IMG_20130212_120032.jpg" type="image" alt="IMG_20130212_120032.jpg" ]

Pretty fun stuff, even if it's very basic. I know that the hardcore MC fans have already been scripting some pretty fantastic stuff in the PC version. It should be interesting to see what people do with the Pi version.

HNY

Yes, a belated Happy New Year greetings! It's hard to believe that 2013 is already well under way. I figured it was about time to give you a quick update on what's going on in the shack right now.

First up is the discrete component grabber receiver for 14.141 MHz that I prototyped to be paired with the OpenBeaconMini project. The receiver itself consists of a roughly 2 kHz wide crystal filter on the front end, feeding into a single-balanced diode ring mixer, which drives an AF amp using 2N4401 and 2N4403 transistors. Because I'm not able to put up a proper outdoor antenna for the grabber right now, I decided to put the VE7BPO cascode active antenna on it instead. It seems to work well, but I don't know for sure because there are basically no signals on this part of the band. I intended to use my Raspberry Pi with the receiver as a grabber, but I had no luck getting either LOPORA or QRSSVD to work properly and reliably. It may just be asking too much of the poor beast. So I'm going to try to appropriate another PC in order to get the grabber receiver QRV so that on-air testing of OpenBeaconMini can begin in earnest.

Discrete component monitor RX for 14.141 MHz
Discrete component monitor RX for 14.141 MHz

Next, I wanted to give you a very brief overview of my most recent purchase for the lab: a Rigol DS1022U arbitrary waveform generator. As far as I can tell, this appears to be pretty much the same as the DS1022A model that is sold in the US. But being a typical ham, I wanted to save a few dollars, so I purchased it off of eBay from seller who says he is an authorized Rigol dealer.

Rigol DG1022U Arbitrary Waveform Generator
Rigol DG1022U Arbitrary Waveform Generator

The DG1022[U|A] has two channels that can output a sine wave up to 25 MHz in 1 mHz (as in millihertz) steps. It can also provide square, ramp, pulse, noise, and arbitrary waveforms at lesser frequencies. It can modulate the waveform in a variety of ways, including AM, FM, PM, PWM, and FSK. It can, of course, also do sweeps of various parameters. The output amplitude into 50 Ω ranges from 10 Vpp on Channel 1 or 3 Vpp on Channel 2 down to 2 mVpp on both channels (or -50 dBm). The shielding on this AWG seems to be excellent. Using my HP 355C/355D attenuator combo, I can get a signal down to about -140 dBm (disclaimer: not a scientific measurement, made using my ear as a detector and listening on my IC-718). The dual outputs makes it very useful for a variety of two-tone receiver measurements, one of the big reasons driving my purchase. The Channel 2 output also doubles as a 200 MHz frequency counter input. Paired with the USB connectivity of the device (it seems to enumerate as a usbtmc device), that will be extremely handy for measuring oscillator drift. The DG1022 can also link the two channels together and give them a specific phase difference, as you can see below. This will make it very handy as a I/Q LO when I want to experiment with phasing and SDR rigs.

I/Q Output from DG1022U

So far, I've been very pleased with my purchase. I don't feel like I've had it or used it long enough to give you a full review, but I thought that this preview would at least be a bit helpful for those thinking about using it. One of my goals for the new year is to do a much better job of characterizing everything that I build. Since I intend to start selling transceivers in the near future, it's doubly-important that I can make accurate measurements of my products so that I can properly state their specifications. To this end, I've decided to sell off a bunch of my unused or replaceable test equipment (please take a look at the for sale posting) in order to finance the new, calibrated test gear. Next up on my purchase list is a Rigol DSA815TG spectrum analyzer (just reviewed favorably in the February 2013 QST), but that's going to require the sale of everything on that page!

Finally, I've got the CC1 prototype PCBs on their way from Seeed Studio right now. It looks like they just cleared customs in the US, so hopefully they will be in my hands in the next few days. With any luck, I'll have the first one built by the weekend and will be well on the way to a new beta test. I'll put up a quick post to show off the PCBs, and when the first prototype unit is completed. Stay tuned!