VK2ZOI’s Flower Pot Antennas

I made a brief mention of this website a few weeks ago on Twitter, but thought I should also archive a link to it here. If you are looking for some nice VHF and/or UHF antennas, these seem pretty neat, with clear directions. They also have the benefit of being stealthy: disguised mostly as flower pots.

VK2ZOI’s Flower Pot Antennas

As is true of many things that I find interesting, Alan, VK2ZAY has also been down this road, and constructed one of these for 2m himself. Check out his notes here.

My speech bot, using irclib.py

Okay, revamped the basic idea, now using the irclib, which in spite of a lack of documentation, actually proved to be pretty easy to use. You should be able to figure out what it does, and modify it to use your own nicks and channel.

#!/usr/bin/env python

import sys
import os
import optparse
import irclib

network = "irc.freenode.net"
port = 6667
channel = "#somechannel"
nick = "SomeNick"
name = "SomeNick is a bot."

irc = irclib.IRC()
server = irc.server()
server.connect(network, port, nick, ircname = name)
server.join(channel)

lastspeaker = None

def handlePubMessage(connection, event):
        global lastspeaker
        target = event.target()
        speaker = event.source().split('!')[0]
        msg = event.arguments()[0]
        print target, ">", speaker, ":", msg
        p = os.popen("festival --tts", "w")
        if speaker != lastspeaker:
                p.write(speaker + " says ")
        p.write(msg)
        p.close()
        lastspeaker = speaker

irc.add_global_handler('pubmsg', handlePubMessage)

irc.process_forever()

Mini hack o’ the day: Making IRC talk…

Okay, it’s been a while since I posted anything: I’ve been busy with travel and the holidays, and now I’m trying to get my home office/shack setup so I can pursue some other projects. It is one of those rooms that has piles of crap, some of which I haven’t seen in years, so I’m carefully working through it, tossing stuff that is useless and organizing the remainder.

As a result, I’m trying to also make the space a bit more engaging, so I’ll spend more time there. My eventual goal is to get some of my radios in here so I can listen to more shortwave and ham traffic, but I also spend a fair amount of my off hours on IRC (mostly on the #hamradio channel on irc.freenode.net using my callsign K6HX as my nickname). Instead of forcing me to sit reading a screen, I thought it would be less intrusive and allow me to get more work done if I could monitor the channel by having a voice synthesizer read the msgs that appear in the #hamradio channel. That way, I could just go about my business, but still hear the conversations.

So, that was my idea.

My first thought was to simply run pidgin (a fairly nice IRC client that runs on multiple platform) and just use the pidgin-festival plugin for voice synthesis. But it turns out it was more difficult than I had hoped: nothing I tried seem to make it work. When I cracked open the source code after an hour of flailing, I was annoyed to find a bunch of really questionable code (hence my comment on twitter earlier about chimps writing code), and I soured on the idea. I turned off the computer and went to bed.

On the drive home from work yesterday, I thought about the problem again. I knew that festival could do the speech synthesis. I knew that the curses based irc client epic5 could write a log file of each msg. I then hatched a simple idea: I’d write a little bit of Python glue that would basically act like tail -f: it would repeatedly scan for new lines at the end of the irc.log file, and then use popen to the festival voice synthesizer, spew out what needed to be read, and then continue.

So, here’s the code!

#!/usr/bin/env python

import sys
import os
import select
import time
import re


msgpat = re.compile("<([A-Za-z0-9_]+)> (.*)$")
actpat = re.compile("\* (.*)$")

def say(nick, s):
        p = os.popen("festival --tts", "w")
        p.write('''%s says %s''' % (nick, s))
        p.close()

def act(s):
        p = os.popen("festival --tts", "w")
        p.write(s)
        p.close()

def process(s):
        m = msgpat.match(s)
        if m:
                say(m.group(1), m.group(2))
        else:
                m = actpat.match(s)
                if m:
                        act(m.group(1))


f = open("irc.log", "r")
f.seek(0, 2)

while True:
        l = f.readline()
        while l:
                process(l.strip())
                l = f.readline()
        time.sleep(1)

It works fairly well. There are a couple of things that I need to work on. First, I think the main loop is fairly inelegant. What I want is a version of readline() that works more like a read from a pipe: blocking when there is no further data to be read. But overall, this code mostly prevents the busy wait that would result without the sleep call.

There really isn’t any reason not to use an irc client library and capture the events that you want to speak directly. I didn’t go that way because frankly I didn’t want to spend more than 10 minutes testing out the idea. I’ll probably code up that soon though.

Other things:

  • It doesn’t do good things with emoticons like :-). You could build a dictionary to map things like that to words like smile or grin. Ditto for things like “hmmm” and “hahaha”.
  • It announces the speaker before every message. If the next message is the same person, it could just say what they said without the redundant introduction.
  • It doesn’t generalize to reading my twitter feed.
  • It should also drop things that look like URLS (they aren’t interesting to hear read out loud.)

Alan Yates’ Laboratory – G3XBM’s XBM80-2 Trivial 80 Metre CW Transceiver

My “on-this-day” blog sidebar indicates that I was looking at Roger, G3XBM’s XBM80-2 transciever: a fiendishly clever low parts count CW transciever for 80m. I’ve been pondering it a bit as something I should just tack together (I think I have all the parts in my junk box) so I’ve been staring at the design a bit, and it surprised me not at all to find that Alan, VK2ZAY had already built one with some modifications.

Alan Yates’ Laboratory – G3XBM’s XBM80-2 Trivial 80 Metre CW Transceiver

I think I’ll spend some time today finding the parts in my junk bins, and maybe I’ll tack one of these together this week if I have time.

PA1B’s QRPP page

Thanks to Roger, G3XBM for the link to PA1B’s QRPp page. QRP operation is operating with an output power of 5w, QRPp operation is operating with output powers down in the mw range. Bert, PA1B has some nice links to this kind of operation, and includes some designs for 20db attenuators that are easy to build and effective. These can step your 5w QRP rig down to just 50mw, or the FT-817 on minimum power down to a teensy 5mw. Roger did 1310 km using just 5mw on 80m using the WSPR mode, which I think is pretty amazing.

Bookmarked for future reference.

PA1B page of VERON department Nieuwegein (A29) and surroundings..

Simulating a 40m bandpass filter in LTSpice

A few days ago, I created a small program to compute bandpass filters using the equations from Experimental Methods in RF Design. Basically, you can pick a given inductor value, and then it solves for all the necessary capacitors. What wasn’t immediately obvious from the equations and the values that are generated was how these values interacted to alter the shape of the filter, and how variations in their value (perhaps to match easy to find capacitors) could change the frequency response.

So, I decided to go ahead and play with it using LTSpice.

Here’s an example filter that I got by specifying a 7.1Mhz center frequency, with a 250khz bandwidth. The source and load impedance are both specified to be 50 ohms. Using the program that I posted before, I got the following component values:

I then could go ahead and simulate the filter using LTSpice’s AC analysis, which yielded the following frequency response:

It looks pretty good. Using LTSpice, it’s pretty easy to check how (for instance) variations in the source or load impedance change the shape of the filter, or how small variations in the value of components affect the losses.

One thing that I didn’t immediately figure out was how to employ the inductor Q. LTSpice doesn’t include a place to enter Q, but it’s easy to compute the necessary parallel resistance (it’s just 2.0 * pi * F * L * Q) which LTSpice can use.

I really need to build one of these for the DC40B.

Getting data from APRS-IS using ncat…

I wanted to log a bunch of APRS-IS traffic for analysis, but didn’t really want to write any code (my brain hurts today), so I tried to figure out what the magic incantation is. It wasn’t necessary for me to inject any new info into the network, so it’s actually pretty easy.

Type:

ncat -C noam.aprs2.net 14580

This should connect you to a Tier 2 APRS server for North America. If you are in some other part of the world, google for “APRS Tier 2 Servers” and fine one for your local area. 14580 is the port number, and probably will be the same whatever server you choose.

Now, you need to login. Type:

user callsign pass -1 vers ncat 1.0 filter r/lat/lng/dist

Your callsign should be your amateur radio callsign. Specifying a password of -1 means that you are asking for a receive-only feed. The vers keyword introduces the software name and a software version, which is followed by a server command. In this case, we are following it by a “range filter”. If you insert a latitude and longitude, and a range expressed in km, the server will only return the information for sites within range of the specified latitude and longitude. There are other potential commands you can use, but I’ll leave that to another time. For instance, I entered:


user K6HX-15 pass -1 vers ncat 1.0 filter r/38/-122/1500

And then the necessary feed data started to spew:

# javAPRSSrvr 3.15b08
# logresp K6HX-15 unverified, server T2SJC, adjunct "filter r/38/-122/1500" OK - Filter definition updated
KC7FFI>APU25N,KINPRT*,WIDE3-2,qAR,KB7KSU:@170733z4254.31N/11235.35W_218/019g024t045r000p012P000b10100h74FWXNWS-POCATELLO {UIV32N}
K5MTS>APK102,WIDE2-2,qAR,W5AOX-10:=3500.04N/10620.91W_234/010g   t034r000p000P   h64b10182KDvs
WB6YTE>APU25N,WIDE1-1,qAR,KD6DCN-5:=3238.05N/11702.01W-Monitoring all local repeaters {UIV32N}
k2lca-14>APRS,TCPIP*,qAC,THIRD:@170737z3736.00N/12206.00W_340/013g020t023r000P000h64b10198
VA7MXA>BEACON,qAS,VA7TWM:>146.960T100 CAMPBELL RIVER VOICE REPEATER
SLIDE>APNU19,qAR,KB7PUX:!3918.76NS11953.03W#PHG7831/W3,NVn, WA6TLW, Slide Mtn., NV A=009700
K9AZZ-10>APS227,BRNSVL*,WIDE2-1,qAR,AB7FS:@170735z4408.72N/12235.25W_234/004g008t054r000P000p000h88b10245
KD6LAY>APW285,WA6YLB-5,WA6TK,WIDE2-2,qAR,W6MIN-15:_01170738c054s000g000t050r000p000P000h90b10174wU2K
KE6JDC>APRS,TCPIP*,qAC,T2TUS:@170737z3347.47N/11806.50W_360/002g...t052r...p...P000h87b10133.DsVP
VE7ZKI-10>APWW05,TCPIP*,qAC,T2VAN:>170737zAPRSISCE/32 Testing Status report
W7KZO-1>APRS,TCPIP*,qAC,MTAPRSNET:@170737z4528.87N/10942.87W_282/031g043t055r000p000P000h29b09997.DsVP
N7OKG>APU25N,TCPIP*,qAS,N7OKG-1:@170737z4805.12N/11725.93W_123/000g000t041r000p014P012h92b10047uLCrs
WA7ZVY-4>APRS,NEWPRT*,LINCON,qAR,W7KKE-6:@073702z4438.50N/12403.36W_214/009g019t052r006p448P047h00b10219.WxDG
KOPEAK>APN382,SOMTN,WIDE2*,qAo,WE7U-3:!4627.66NS12332.96W#PHG5660/W2,WAn,KOPEAK WA7RW
KC7HXC-9>APOTC1,W7PFR-1,WIDE1*,WIDE2-1,qAS,WW7CH:/170737z4725.71N/12206.70Wj263/004/A=000471 12.7V
NI6M-2>APNU3B,WIDE2-1,qAR,K6TJS:!3703.52NS11924.41W#PHG5360 Mile High, Ca 4690'
KD6RSQ-5>APRS,XE2K-1,KF6ILA-10*,WIDE3-1,qAR,N6EX-3:$ULTW005E00DC026600C027B7FFFC8B0F00010233000F058C00000039
KD6RSQ-5>APRS,XE2K-1,INDIO*,WIDE3-1,qAR,K6JV-11:$ULTW005E00DC026600C027B7FFFC8B0F00010233000F058C00000039  
DIAMON>APN391,BEAR*,WIDE2-1,qAR,CRVLS-1:!4314.44NS12206.59W#PHG5700/W7ZQD OR DIAMOND LAKE APRS
W0LTA>APRS,TCPIP*,qAC,T2BERN:@170737z4007.00N/10456.23W_178/004g006t038r000p000P000h66b10042.DsVP
XE2K-1>APN391,KF6ILA-10,WIDE2*,qAR,N6EX-3:!3238.88N/11530.04W#PHG73604/Mexicali B.C Digi @ XE2K's Station DM22fp www.xe2k.net
W8GWP-7>SV2PXP,WA6YLB-5*,WIDE2-1,qAR,K6MAR-10:`/CDl!>/`"4d}_#

And so on. The format of the individual lines is beyond the scope of this informational post, and is left as an exercise for those who like to read software specifications.

Addendum: Playing with this basic idea, I decided to limit output to just those stations reporting their symbol code as a balloon (APRS primary symbol “O”). I found out that station DL2FX-11 was reporting its position, with its status of “in der Luft” which even in my primitive knowledge of German I know to translate as “in the air”. So, I surfed over to aprs.fi to find out if the station was in fact a balloon, and it was. Apparently it was on its way down too, after reaching a height of 112K feet. Very neat.

Here’s the aprs.fi screen grab:

Colossus: The secrets of Bletchley Park’s code-breaking computers

As long time readers of my blog might remember, I’ve been fascinated by old cryptographic machines. I spent quite a bit of time tinkering around with them back when I was working on Simon Singh’s cipher challenge in his book. In particular, I spent a considerable amount of time reading up on the German Enigma machine, and eventually managed to break Stage 8 of that challenge using an Enigma machine simulator that I coded up. I also have a fair number of books on Enigma.

For all that, I didn’t actually know much about the other great code breaking effort at Bletchley Park: the break of the German “Tunny” code using Colossus, an even more impressive machine than the “Bombe” which allowed the breaking of Enigma. My lovely wife scanned my Amazon wishlist at Christmas, and picked up this book for me for my Kindle.

Colossus: The secrets of Bletchley Park’s code-breaking computers

If your tastes in reading are sufficiently refined to the point where reading about sixty year old code machines is interesting, I think you’ll enjoy the book. It isn’t too technical/nuts-n-bolts, but it does give a good basic idea of how the Tunny operated, and how the British developed an advanced code-breaking bureau that saved thousands of British lives and allowed the preservation of important supply lines in the face of German U-boats. If you are more interested in the history, you might do well to also pick up a copy of Codebreakers: The Inside Story of Bletchley Park, but Colossus includes more technical details on the Tunny.

After the war, the British destroyed Colossus, and most of the records of its function were lost or classified. But in 2000, the British released the “General Report on Tunny with Emphasis on Statistical Methods” which was written in 1945, and details much of the techniques they used to attack the Tunny. It’s online at alanturing.net and also makes for some interesting (and free!) reading.

Morse on Arduino code, now at Arduino Playground

A long time ago, I wrote some code to send simple morse messages by toggling a pin of an Arduino. It could either blink an LED, or if you wired a bias resistor and transistor to it, you could use it to (say) act like a key for the FT-817. But then I lost the code (it’s probably on my old laptop somewhere).

So, I rewrote it. This time I included some additional code so that it could generate a PWM signal that would beep a small speaker or buzzer. Some people seemed to like the code and thanked me for writing it. No biggie. I got some requests to reuse the code, I placed no restrictions on its reuse, but said that it would be great if they mentioned my name and blog when they redistributed it.

Erik Linder, SM0RVV, did just that. He tidied up the code, and submitted it to the Arduino Playground. Awesome! Thanks Erik. Hope others find this little code fragment to be of some use.

Arduino playground – Morse.

Codec 2 good for voice, but not so much for CW

I’ve been thinking about making a kind of “codec2 robot” that people can telnet to and get responses from, and toward that end, I thought I’d see how it did on synthetic speech, since I thought being able to use a speech synthesizer for responses would be good. I had a file generated from my “mscript” Morse code tutorial generator thingie lying around, and passed it through Codec2.

Original sound clip, voice generated on MacBook, downsampled to 8khz.
Compressed via Codec 2.

It’s quite starting, but the segments containing morse simply disappear. I’m not sure I’d call that a flaw, but it may limit the usability of the codec in certain cases (like the CW practice nets held on some repeaters). Does anyone know if D-Star/AMBE does a similarly bad job of reconstructing these relatively pure tones?

Just curious.

Batsocks – Text on TV – Introduction

The chaps over at the Batsocks blog sell a cute little gadget called the “Tellymate”: a nice little serial->video converter that is very, very simple. It uses a single Atmel AVR Mega, and handful of other extra components to implement a full character mapped 38×25 character display terminal which reads characters from a serial input port. But what’s really great is that they have all sorts of good information on how the gadget actually works, meaning that you can adapt the techniques and ideas for your own use. Very cool.

Batsocks – Text on TV – Introduction.

The interesting bit that the Tellymate implements is a higher density display than can be achieved with the arduino TV-out library that I mentioned a few days ago. It does this by leveraging the SPI output to automatically clock out bits 9 at a time, which gives you enough time to actually stream out 38 characters (about double what I can achieve with the Arduino library). Very neat, but there are some details which are a bit crufty. Lots of good information.

My Morse Code practice generator…

A while ago, I worked up a simple little program that could generate both computer generated speech and Morse code at various speeds to make up some sample recordings I could use to brush up on my Morse skills. I apparently left it in a pretty broken state though: it could use some work. But it does generate pretty pretty reasonable sounding audio using the voice synthesis system on the Mac and my own relatively nicely filtered morse wave forms. I should clean this up, and then use it to brush up on my code skills.