Mar 112017

So, as promised, the re-design of the charge controller. … now under the the influence of a few glasses of wine, so this should be interesting…

As I mentioned in my last post, it was clear that the old logic just wasn’t playing nice with this controller, and that using this controller to maintain the voltage to the nodes below 13.6V was unrealistic.

The absolute limits I have to work with are 16V and 11.8V.

The 11.8V comes from the combination of regulator voltage drop and ATX PSU power range limits: they don’t operate below about 10.8V, if you add 700mV, you get 11.5V … you want to allow yourself some head room. Plus, cycling the battery that deep does it no good.

As for the 16V limit… this is again a limitation of the LDOs, they don’t operate above 16V. In any case, at 16V, the poor LDOs are dropping over 3V, and if the node is running flat chat, that equates to 15W of power dissipation in the LDO. Again, we want some headroom here.

The Xantrex charger likes pumping ~15.4V in at flat chat, so let’s go 15.7V as our peak.

Those are our “extreme” ranges.

At the lower end, we can’t disconnect the nodes, but something should be visible from the system firmware on the cluster nodes themselves, and we can thus do some proactive load shedding, hibernating virtual instances and preparing nodes for a blackout.

Maybe I can add a small 10Mbps Ethernet module to an AVR that can wake the nodes using WOL packets or IPMI requests. Perhaps we shut down two nodes, since the Ceph cluster will need 2/3 up, and we need at least one compute node.

At the high end, the controller has the ability to disconnect the charger.

So that’s worked out. Now, we really don’t want the battery getting that critically low. Thus the time to bring the charger in will be some voltage above the 11.8V minimum. Maybe about 12V… perhaps a little higher.

We want it at a point that when there’s a high load, there’s time to react before we hit the critical limit.

The charger needs to choose a charging source, switch that on, then wait … after a period check the voltage and see if the situation has improved. If there’s no improvement, then we switch sources and wait a bit longer. Wash, rinse, repeat. When the battery ceases to increase in voltage, we need to see if it’s still in need of a charge, or whether we just call it a day and run off the battery for a bit.

If the battery is around 14.5~15.5V, then that’s probably good enough and we should stop. The charger might decide this for us, and so we should just watch for that: if the battery stops charging, and it is at this higher level, just switch to discharge mode and watch for the battery hitting the low threshold.

Thus we can define four thresholds, subject to experimental adjustment:

Symbol Description Threshold
V_{CH} Critical high voltage 15.7V
V_H High voltage 15.5V
V_L Low voltage 12.0V
V_{CL} Critical low voltage 11.8V

Now, our next problem is the waiting… how long do we wait for the battery to change state? If things are in the critical bands, then we probably want to monitor things very closely, outside of this, we can be more relaxed.

For now, I’ll define two time-out settings… which we’ll use depending on circumstances:

Symbol Description Period
t_{LF} Low-frequency polling period 15 sec
t_{HF} High-frequency polling period 5 sec

In order to track the state, I need to define some variables… we shall describe the charger’s state in terms of the following variables:

Symbol Description Initial value
V_{BL} Last-known battery voltage, set at particular points. 0V
V_{BN} The current battery voltage, as read by the ADC using an interrupt service routine. 0V
t_d Timer delay… a timer used to count down until the next event. t_{HF}
S Charging source, an enumeration:

  • 0: No source selected
  • 1: Main charging source (e.g. solar)
  • 2: Back-up charging source (e.g. mains power)

The variable names in the actual code will be a little more verbose and I’ll probably use #defines for the enumeration.

Below is the part-state-machine part-flow-chart diagram that I came up with. It took a few iterations to try and describe this accurately, I was going to use a state machine syntax similar to what my workplace uses, but in the end, found the ye olde flow chart shows it best.

In this diagram, a filled in dot represents the entry point, a dot with an X represents an exit point, and a dot in a circle represents a point where the state machine re-enters the state and waits for the main loop to iterate once more.

You’ll note that for this controller, we only care about one voltage, the battery voltage. That said, the controller will still have temperature monitoring duties, so we still need some logic to switch the ADC channel, throw away dummy samples (as per the datasheet) and manage sample storage. The hardware design does not need to change.

We can use quiescent voltages to detect the presence of a charging source, but we do not need to, as we can just watch the battery voltage rise, or not, to decide whether we need to take further action.

Oct 132016

Well, today’s mail had a surprise.  Back about 6 years ago, I was sub-contracted to Jacques Electronics to help them develop some device drivers for their video intercom system.  At the time, they were using TI’s TLV320AIC3204 and system-on-modules based on the Freescale i.MX27 SoC.

No driver existed in the ALSA tree for this particular audio CODEC, and while TI did have one available under NDA, the driver was only licensed for use with a TI OMAP SoC.  I did what just about any developer would do, grabbed the closest-looking existing ALSA SoC driver, ripped it apart and started hacking.  Thus I wound up getting to grips with the I²S infrastructure within the i.MX27 and taming the little beast that is the TLV320AIC3204, producing this patch.

As the code was a derivative work, the code was automatically going to be under the GPLv2 and thus was posted on the ALSA SoC mailing list for others to use.  This would help protect Jacques from any possible GPL infringement regarding the use of that driver.  I was able to do this as it was a clean-room implementation using only material in TI’s data sheet, thus did not contain any intellectual property of my then-employer.

About that time I recall one company using the driver in their IP camera product, the driver itself never made it into the mainline kernel.  About 6 months later, another driver for the TLV320AIC3204 and 3254 did get accepted there, I suspect this too was a clean-room implementation.

Fast forward to late August, I receive an email from Jeremy McDermond on behalf of the Northwest Digital Radio.  They had developed the Universal Digital Radio Controller board for the Raspberry Pi series of computers based around this same CODEC chip.  Interestingly, it was the ‘AIC3204 driver that I developed all that time before that proved to be the code they needed to get the chip working.  The chip in question can be seen up the top-right corner of the board.

Universal Digital Radio Controller

Timely, as there’s a push at the moment within Brisbane Area WICEN Group to investigate possible alternatives to our aging packet radio system and software stack.  These boards, essentially being radio-optimised sound cards, have been used successfully for implementing various digital modes including AX.25 packet, D-Star and could potentially do FreeDV and other digital modes.

So, looks like I’ll be chasing up a supplier for a newer Raspberry Pi board, and seeing what I can do about getting this device talking to the world.

Many thanks to the Northwest Digital Radio company for their generous donation! 🙂

Sep 032016

So after a long hiatus, some of it involving some yak shaving (e.g. #Open-source debugWire debugger yes, I’ll get back to that), I managed to get a version of the firmware together for the power controller that seems to be doing what I ask of it.

The means of overcoming the road block was knocking up a very crude (and slow!) UART driver so I could print data out on the serial port. I avoided doing this previously because I didn’t have an easy way to interface to a TTL serial port. Recently though, I bought some FTDI serial cables, one 5V and one 3.3V, so now I had little excuse.

I feel these will give me some valuable insights into tacking the debugWire project.

I was able though, to bit-bang a UART using avr-libc’s _delay_us, and get a respectable 4800 baud serial stream out. This obviously dropped to 300 baud when I had other tasks running, but still, that’s enough to do what I’m after. (Once upon a time, that was considered fast!)

After figuring out where I was going wrong… perhaps I had been sniffing too much solder smoke that day… I re-wrote my firmware, using this UART library as a means of debugging the code. I set up Timer1 to run at 1.2kHz, which meant I could also use it as a baud rate generator for my software UART and upping the baud rate to 1200bps.

Some further work on a breadboard, and I had more-or-less working firmware.

I’ve thrown the code up on GitHub, it’s very much in a raw state, and I might do a second revision of the PCB, since this prototype seems to be more or less on the money now.

Mar 312013

Recently I purchased a second hand Kantronics KPC-3 packet TNC. Brisbane Area WICEN make heavy use of packet at one particular event, the International Rally of Queensland, where they use the 1200-baud network to report the scores of rally cars as they progress through each stage.

Now, I’m a newcomer to radio compared to most on the band. I got my license in 2008, and I’ve only had contact with packet for the last two years, and even then, mostly only at a distance.  I had a hand-held that did APRS, and I’ve also done some APRS using soundmodem and Xastir.  Full-blooded AX.25 has taken me some time, and I’m slowly coming to grips with some of it.

One thing I wanted to try and figure out, is how to re-lay traffic from a host connected to the RF world, to a host on a local network.  I knew there was some protocol that did it, but didn’t know what, or how it worked.  Turns out the protocol I was thinking of was AXIP, which basically overlays AX.25 frames directly atop IP.  There’s also a version that encapsulates them in UDP datagrams; AXUDP.

The following are my notes on how I managed to get some routing to happen.

So, my set-up.  I have my FT-897D set up on 145.175MHz FM, the APRS frequency in Australia.  (I did go hunting for BBSes the other night but came up blank, but since APRS uses AX.25 messaging, it’ll be a start.)

To its data port, I have the KPC-3, which connects to my trusty old P4 laptop via good ol’e RS-232 (the real stuff, not pretend USB-RS232, yes the laptop is that old).  This laptop is on my local LAN, with an IP address of

In front of me, is my main workhorse, a MacBook at the address of  Both laptops are booted into Linux, and my target is Xastir.

First thing I had to do was compile the AX.25 kernel modules, and the ax25-tools, ax25-apps.  The userspace tools needed for this are: ax25ipd and kissnetd.

On the RF-facing system

This is the P4 in my case, the one with the TNC. First step is to get the TNC into KISS mode. In the case of Kantronics TNCs, the way to do this is to fire up your terminal emulator and run int kiss followed by reset.

Important note: to get it back, shut down everything using the serial port then run echo -e '\0300\0377\0300' > /dev/ttyS0. This sends the three-byte exit-kiss-mode sequence (0xc0 0xff 0xc0).

Configure /etc/ax25/ax25ipd.conf. Three things you’ll need to set up:

  • mode: should be tnc
  • device: should be whatever your serial device is (more on this later)
  • your default route: this is the host that will receive ALL traffic

In my case, my ax25ipd.conf on the P4 laptop looks like this:

socket ip
mode tnc
device /dev/ttyS0
speed 9600
loglevel 2
broadcast QST-0 NODES-0
# This points to my MacBook; d means default route
route 0 d

Once done, we start the ax25ipd service as root, it should fork into the background, and checking with netstat should show it as listening on a raw socket.

On the client machine

Here, we also run a AXIP server, but this time to catch the packets that get flung our way by the other system. We want Xastir to pick up the traffic as it comes in. Two ways of doing this.

One is to configure kissattach to give us a PTY device which we then pass onto ax25ipd, then run Xastir as root and tell it to use the AX.25 stack directly. Gentoo’s Xastir ebuild ships with this feature disabled, so not an option here (unless I hack the ebuild like I did last time).

The AX.25 tools also come with kissnetd: this basically generates several PTYs and links them all together so they all see eachother’s KISS traffic. So ax25ipd will receive packets, pass them to its PTY, which will then get forwarded by kissnetd to the other PTY attached to Xastir.

There is one catch. Unlike in kernels of yore, kernel 2.6 and above (3.x is no exception) do not have statically configured PTY devices. So all the AX.25 docs that say to use /dev/ptyq0 for one end and /dev/ttyqf for the other? Make that /dev/ptmx for one end, and the tool will tell you, what the other end is called. And yes, it’ll change.

Run kissnetd -p 2; the parameter tells it to create two PTYs. The tool will run in the foreground so make a note of what they’re called, then hit CTRL-Z followed by bg to bring it into the background.

vk4msl-mb stuartl # kissnetd -p 2
kissnetd V 1.5 by Frederic RIBLE F1OAT - ATEPRA FPAC/Linux Project

Awaiting client connects on:
/dev/pts/1 /dev/pts/4
[1]+  Stopped                 kissnetd -p 2
vk4msl-mb stuartl # bg 1

Now, in this example, PTYs 1 and 4 are allocated. I can allocate either one of them to Xastir or ax25ipd, here I’ll use /dev/pts/4 for ax25ipd and the other for Xastir. It is possibly best if you make symlinks to these, and just refer to the symlinks in your software.

# ln -s /dev/pts/4 /dev/kiss-ax25ipd
# ln -s /dev/pts/1 /dev/kiss-xastir

Whilst you’re at it, change the ownership of the one you give to Xastir to your user/group so Xastir doesn’t need to run as root.

Set up /etc/ax25/ax25ipd.conf on the client. Here, I’ve given it a route for all WIDE* traffic to the other host. It might be possible to just use 0 as I did before, I wasn’t sure if that’d create a loop or not.

socket ip
mode tnc
device /dev/kiss-ax25ipd
speed 9600
loglevel 2
broadcast QST-0 NODES-0
# This points to my P4, attached to the TNC; d means default route
route WIDE* d

Now start up ax25ipd and Xastir, you should be able to bring up the interface and see APRS traffic, more over, you should be able to hit Transmit and see the TNC broadcast your packets.

Some stations visible direct via RF

Some stations visible direct via RF (click to enlarge)

Jun 082011

Well… has anyone noticed anything different about the ‘net?

stuartl@atomos ~ $ host is an alias for is an alias for has address has address has address has address has address has IPv6 address 2404:6800:4006:802::1011

I knew World IPv6 day was coming up, but it seems it snuck up on me and I barely noticed. Likely a testament to the fact we run a dual-stack network here, and so everything magically Just Worked™ as it should. Indeed, a lot of websites are now dual-stack, as is much of the infrastructure, Google (as seen above), FaceBook, and numerous other sites.

Sadly, a lot of ISPs here in Australia did the demented ostrich act when it came to IPv6. I wonder how many technical support calls they received, with users complaining about websites being slow to load up or failing to connect.

iTel, formerly “Global Info-Links”, now calling themselves “South East Community Telco“… were one of the masses that drove their RFC791-only heads in the sand and pretended that the entire Internet can be compressed into 32-bits of address space. We’ve been waiting to hear back from them on their plans for addressing since January as we’d like to upgrade the 512/128kbps ADSL link we use here. (Anyone noticed this site tends to load up a bit slow? That 128kbps figure is the reason why.)

We’ve been with this ISP since 1996. That’s quite a long innings… We’ve stayed put because until now we’ve been happy with the service. 512kbps was quite fast when we upgraded from 56kbps PSTN dialup (14.4kbps dialup when we first started… still have that modem too!). These days it plods along, but the 128kbps uplink is a notable thorn in my side with my telecommuting. So we’re looking at ADSL2+.

However, there’s one hitch. iTel is only a fairly small ISP. At the moment they do the noble thing of providing static public addresses on IPv4 for all fixed-broadband customers, but how long will that last? The last thing I want, is to sign up a contract for 12 months, then find out that in 6 months they need to move us behind CGN (Carrier grade NAT) to squeeze in some more customers. That won’t fly for us. I’d ideally like to ditch the 6-in-4 tunnel I have with AARNet and go native, or at the very least, swap it with one terminated at the ISP, but that doesn’t seem to be happening anytime soon.

At the moment there is only one ISP I know of that offers any sort of IPv6 connectivity. Internode. Kudos to them for taking the pioneering step! I’m seriously looking in their direction. I’m also hoping the NBN that we keep hearing about, is IPv6 enabled… and I’m holding out with the hope that our little suburb might soon be getting the long strands of glass laid down our street. If it’s only another year or so, it may be worth just hanging on with ADSL1 until then.

Thankfully, we do have the 6-in-4 tunnel through AARNet (and my greatest gratitude to them for providing it). There is a growing community on this newer protocol… I’m also happy to report absolutely 0 spam via IPv6… any spam or malware thus far has been via IPv4 … although I know this won’t last. The good news there is that with one unique address per computer (instead of per customer, or worse, per 100+ customers), it should be easier to track down the guilty party causing such Internet shenanigans. CGN by comparison is likely to be a spammer’s playground.

What am I doing about IPv6 deployment? Aside from my small-time tinkering with the network here… any socket programming I do today is at the very least dual-stack. One of my hobby projects is a digital mode stack for amateur radio… if I get my way it’ll be IPv6-only when used on a computer network.

One of my work projects involves interfacing some proprietary software to some power meters using RS-232 and RS-485 to Ethernet bridging devices. Even though the devices themselves are IPv4 only (and will be for the foreseeable future), I’m designing the software to handle IPv6. Doing this, future proofs the software. Surprisingly, I’m finding it easier to just design for dual-stack than it is to develop a IPv4-only application. If you’re building an application today, dual-stack IMHO must be part of the strategy if the application is going to work beyond this decade.

Some have asked about IPv6 on packet… sadly AX.25 packet does not go anywhere near fast enough to make IPv6 (or indeed, IPv4) networking a viable option on packet radio using existing TNCs… however I think IPv6 will, and should, play a much bigger part in amateur radio communications than it presently does… we can’t expect to hold on to the subnet for much longer.

To the ISPs that are lagging behind, I say get moving! IPv4 is older than I am! This is especially true of the smaller ISPs… if you don’t move, you will get squeezed out of the future Internet connection market as address space gets consumed. To the nay-sayers who keep telling us that something else will replace IPv4, to you I say get moving… you haven’t got long to invent this magical silver bullet, in fact I say you’ve left it too late.

May 162011

This weekend just gone I was at Imbil helping out with the International Rally of Queensland, reporting scores for the car rally there.  This was my first look at packet radio in action.  Prior to this I had enabled the amateur radio options in the kernels I built, but never tried actually hooking radio to computer.  I shall be posting some notes on how I got this working…

zhouman ~ # uname -a
Linux zhouman #2 Wed Oct 13 00:42:58 EST 2010 mips64 ICT Loongson-2 V0.3 FPU V0.1 lemote-yeeloong-2f-8.9inches GNU/Linux
zhouman ~ # ifconfig sm0
sm0 Link encap:AMPR AX.25 HWaddr VK4MSL
inet addr: Bcast: Mask:
RX packets:365 errors:0 dropped:0 overruns:0 frame:0
TX packets:36 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:10
RX bytes:24236 (23.6 KiB) TX bytes:6850 (6.6 KiB)

zhouman ~ # mheard
Callsign Port Packets Last Heard
VK4EA-9 sm0 6 Mon May 16 17:59:12
VK4NRL-9 sm0 1 Mon May 16 17:58:40
VK4VP-1 sm0 8 Mon May 16 17:58:38
VK4RAI-3 sm0 9 Mon May 16 17:57:58
VK4TIM-9 sm0 14 Mon May 16 17:57:56
VK4TDI-1 sm0 2 Mon May 16 17:57:39
VK4DC-1 sm0 15 Mon May 16 17:57:07
VK4TEC-9 sm0 120 Mon May 16 17:56:08
VK4FY-1 sm0 18 Mon May 16 17:54:38
VK4RMO-3 sm0 1 Mon May 16 17:54:33
VK4RGC-3 sm0 3 Mon May 16 17:52:48
VK4RC-1 sm0 8 Mon May 16 17:51:29
VK4FIL-1 sm0 4 Mon May 16 17:46:44
VK4RIL-13 sm0 4 Mon May 16 17:45:43
VK4RBR-3 sm0 5 Mon May 16 17:42:59
VK2RDO-3 sm0 2 Mon May 16 17:41:19
VK4RRC-13 sm0 3 Mon May 16 17:36:39
VK2JUB-1 sm0 2 Mon May 16 17:34:44
VK4BNQ-1 sm0 1 Mon May 16 17:26:58
VK4LDA-9 sm0 2 Mon May 16 17:24:59
VK2POO-9 sm0 9 Mon May 16 17:21:24
VK2XFL-9 sm0 1 Mon May 16 17:21:09
VK4RSR-3 sm0 1 Mon May 16 17:20:04
VK4IE sm0 1 Mon May 16 17:15:04
VK4ALJ-3 sm0 1 Mon May 16 17:15:00
VK4HPW-9 sm0 5 Mon May 16 17:13:23
zhouman ~ #

Set-up consisted of:
Linux kernel on Lemote Yeeloong, latest soundmodem driver, Yaesu FT-897D, homebrew interface cable plugged into Yeeloong’s onboard sound card, USB serial driving BC547 in interface cable for PTT.

zhouman ~ # cat /etc/ax25/soundmodem.conf
<?xml version="1.0"?>
<configuration name="FT897-D">
<chaccess txdelay="150" slottime="100" ppersist="40" fulldup="0" txtail="10"/>
<audio type="alsa" device="plughw:0,0" halfdup="0" capturechannelmode="Mono"/>
<ptt file="/dev/ttyUSB0"/>
<channel name="Channel 0">
<mod mode="afsk" bps="1200" f0="1200" f1="2200" diffenc="1"/>
<demod mode="afsk" bps="1200" f0="1200" f1="2200" diffdec="1"/>
<pkt mode="MKISS" ifname="sm0" hwaddr="VK4MSL" ip="" netmask="" broadcast=""/>
zhouman ~ #

I’ve shut it down for now, but I’ll give it a bit more work on 145.175MHz tomorrow. Once I get something working, I might set something up using the O2 or one of the Fulongs (probably the latter) and see about getting soundmodem back into Gentoo.

Update: After hand-editing the ebuild to enable APRS support, I can successfully report that not only is soundmodem working, but so is Xastir on my Yeeloong, as can be seen on