Wednesday, December 03, 2025

Tech talk on ABC Radio - Solar flares

Over the weekend, Airbus ordered immediate software downgrades to 6,000 of their A320 aircraft to avoid a problem triggered by solar flares. 

How can software be affected by solar activity and how could a downgrade possibly help? Also we talk about inauthentic accounts revealed on X and the good news that those annoying cookie permission buttons may soon disappear.

Peter Marks, mobile software developer and technology commentator from Access Informatics, joined Philip Clark and listeners to Nightlife. Listen at: https://www.abc.net.au/listen/programs/nightlife/nightlife-tech-talk-with-peter-marks/106093718

Tuesday, December 02, 2025

QMX in 3D printed case

Previously I mentioned building a QRP-Labs QMX kit but when I came to put it in a 3D printed case I found that I'd failed to follow the instructions and put the display on the front of the board instead of through the opening from the back. In removing the display I damaged the board. 

QRP-Labs sold me a new display board and it's just arrived. The QMX in a 3D printed case is even more compact that in the official metal case. The top PCB is actually sandwiched between the front and back printed pieces.


Also I used a rather nice blue display rather than the supplied green one. The 3D case has a hole for adjusting the LCD contrast which is handy. As you probably know, these transceivers work brilliantly not only on SSB but on FSK digital modes. I'm running WSPR on 40m into a rather poor vertical antenna but it's doing well.


QRP-Labs has a link to a listing of 3D designs for useful cases and accessories.

New version of WSPR watch coming soon that no longer starts the audio session on launch by the way. Good feedback on the new "globe" style spot display. 

Sunday, November 30, 2025

Sunday Australian FreeDV Net - 20 stations

An excellent rollup again this morning with some interesting conditions that seemed to improve and then decline during the net. 

At first there was very little fading here but later I saw this interesting effect pictured here.

Another observation was that sometimes the measured SNR does not match up with the quality of the recovered voice. Sometimes SNR is very low, even negative, and speech is perfect. Other times SNR is good but speech is not good.

VK3EMI commented that he had trouble hearing people when SNR was -7dB or below! Fair enough I thought.

Stations participating - not all heard - VK2VCO, VK3BRT, VK3CKY (portable), VK3JCO, VK3KEZ, VK3KQT, VK3SRC, VK3YV, VK5AG, VK5KVA, VK6POP, VK5AV, VK3UBK, VK5COL, VK3EMI, VK3PCC, VK5LN, VK5GY, VK2DWG and me VK3TPM.

Saturday, November 29, 2025

Article about FreeDV in "Amateur Radio" Magazine

This month I have an article in the WIA's Amateur Radio magazine


It's a venerable publication where many of my ham radio heros have published including Drew VK3UX so it's a great pleasure to be there. The process was very smooth, I wrote to editor Roger Harrison pitching the idea. He replied in the affirmative immediatly. Roger sent me constructive feedback - a rare thing these days. (He was careful to add "don't take this as criticism").

The article talks about the amazing new FreeDV mode which uses AI for the first time in a widely distributed digital voice application - a feather in the cap for Amateur Radio - due largely to the contribution of David Rowe VK5DGR. My article, spanning almost 7 pages, does double duty of being a fairly detailed technical explanation and a getting started guide.

AR magazine is sent to members of the Wireless Institute of Australia and is also available in newsagents.

Field operations while camping at Barmah Lakes

I joined Graeme VK3CDO and we spent a very pleasant afternoon, night and breakfast at the Barmah Lakes campground near Echuca. As usual, Graeme came well equipped for the field operations.


There are fireplaces with a metal ring resting on a concrete base but oddly they had signs saying not to use them until a safety audit had been completed. A group of three rangers turned up and I asked what the danger was? They said that there had been two reports of the concrete base exploading and they were checking them all to try to figure out what would cause that.

An end fed antenna was strung up and we had several contacts including to a POTA station in NSW and Richard VK3LRJ. Noise was very low of course.


The KX3 was matched beautifully to the end fed using a home brew Unun but the band seemed rather dead. Connecting the end fed direct to the radio brought the band to life and the KX3’s amazing tuner was able to get a good enough match on its own. Something is wrong with the Unun.

I powered the radio with a 12V adapter connected to a Makita battery. This works well and doesn’t seem to add any noticable noise.

Lindsay VK3GX kindly loaned us a new Starlink Mini station to provide high speed internet.


Unfortunately the trees blocked too much of the sky and the Starlink dish was unable to find enough satellites. These Starlink Minis draw only 36W and could be run for many hours on a small power bank.

It was a very warm afternoon with rain on the way which happily fell once we had packed up after dinner and were in our tents.

Barmah Lakes is a lovely spot and on the Friday night a few other campers arrived some with boats of various sorts.


There were some annoying flies in the afternoon and a few mosquitoes but the overnight sleep in our tents was very pleasant with a fair amount of rain which ended before breakfast. 

Monday, November 24, 2025

Comparing HF reception with WSPR Head2Head

After Sunday's FreeDV net on 40m, my neighbour (1km away), Richard VK3LRJ, commented that he couldn't hear all the stations I was hearing. He's on a similar 5 acre block to me. I have wire dipoles in the trees and he uses an end fed wire cut for 80m but with in-line capacitance to resonate on 40m. Richard is off grid and has significant noise from his solar power system which I'm sure is a major factor.

To test our relative reception I suggested we both run WSPR in receive only on 40m so we can compare receive signal to noise.

I did some spot checks, looking at individual transmissions received by both of us.

VK7JJ at -8 vs +13 = 21dB.

VK2NSB -26 vs +19 = 45dB. Wow.

My reception was significantly better than his. For a more long term analysis I turn to the excellent WSPR data analysis site https://wspr.rocks/ and in particular the "head2head" page. For 12 hours of operation here's the spot count for each of us.


I'm not sure of the best way to compare reception but there are several charts comparing signal to noise. This is maximum SNRs.


Ideally I'd like to be able to have software which finds the same transmission as received by both stations and subtract the SNRs (as I did manually above).

Richard's end fed no doubt has complex nulls compared to the simpler pattern of my mono-band dipole but the charts show that overall his reception is significantly worse.

Update: My own head2head

The analysis on wspr.rocks is great but I wanted to see the SNRs for two stations receiving the same transmission so I wrote a python program that uses the WSPRnet API. It pulls the spots for each stations and finds just the transmissions that they both received. It prints the result like this:

1764112440 VK3CYD received by: VK3TPM -29dB received by: VK3AMW -10dB 

1764112080 VK7JJ received by: VK3TPM 3dB received by: VK3AMW -5dB 

1764111840 VK3CYD received by: VK3TPM -23dB received by: VK3AMW -13dB 

1764111600 VK5KDO received by: VK3TPM -9dB received by: VK3AMW -22dB 

1764111600 VK4TMT received by: VK3TPM -25dB received by: VK3AMW -24dB 

1764111240 VK3CYD received by: VK3TPM -11dB received by: VK3AMW -9dB 

1764111000 VK7JJ received by: VK3TPM 6dB received by: VK3AMW -1dB 

1764110760 VK2MOE received by: VK3TPM 17dB received by: VK3AMW 4dB 

1764109920 VK7JJ received by: VK3TPM 8dB received by: VK3AMW 0dB 

Unfortunately the WSPRnet API is only available to people who've applied and been granted access so I'm not sure how useful this code is.

import requests

username = "XXXXXXXX"
password = "XXXXXXXX"

def main():
callsigns = ['VK3TPM', 'VK3AMW']
cookie, CSRFtoken = login(username=username, password=password)
#{'Spotnum': '11215485938', 'Date': '1763965440', 'Reporter': 'DL2NL/1', 'ReporterGrid': 'JO31', 'dB': '1', 'MHz': '10.140193', 'CallSign': 'DL2NL', 'Grid': 'JO31', 'Power': '23', 'Drift': '0', 'distance': '0', 'azimuth': '0', 'Band': '10', 'version': '', 'code': '1'}
spotLists = []
for callsign in callsigns:
spotList = getSpotsReceivedByCall(callsign, cookie, CSRFtoken)
print(f"got {len(spotList)} spots for {callsign}")
spotLists.append(spotList)

mergedSpotList = mergeSpotLists(spotLists)
logout(cookie, CSRFtoken)
print(f"{len(mergedSpotList)} merged spots")
for spot in mergedSpotList:
print(spot)
break

commonSpots = getCommonSpots(mergedSpotList)
print(f"{len(commonSpots)} common spots")
printSpotList(commonSpots)

def printSpotList(commonSpots):
for key in commonSpots.keys():
print(key,end=' ')
spotlist = commonSpots[key]
for spot in spotlist:
print(f"received by: {spot['reporter']} {spot['dB']}dB", end=' ')
print()

def printSpot(spot):
for key in spot.keys():
print(f"{key}: {spot[key]}",end=' ')

# find spots heard by each of the receiving stations
def getCommonSpots(spotList):
commonSpots = {} # key is date + " " + call
for spot in spotList:
key = f"{spot['Date']} {spot['call']}"
if key in commonSpots:
#print(f"found key: {key} -> {spot['reporter']}")
commonSpots[key].append(spot)
else:
commonSpots[key] = [spot]
# remove if less than 2 common spots
multiSpots = {}
for key in commonSpots:
if len(commonSpots[key]) > 1:
multiSpots[key] = commonSpots[key]

return multiSpots

# take a list of spot lists and combine them
# strip data to just the essentials
def mergeSpotLists(spotLists):
mergedSpotList = []
for spotList in spotLists:
for spot in spotList:
cleanSpot = {'call': spot['CallSign'],
'reporter': spot['Reporter'],
'dB': spot['dB'],
'Date': spot['Date'],
'MHz': spot['MHz']}
mergedSpotList.append(cleanSpot)
return(mergedSpotList)

def login(username, password):
data = {
"name": username,
"pass": password
}
# Send POST request with JSON
response = requests.post(
'https://www.wsprnet.org/drupal/rest/user/login',
json=data,
headers={"Content-Type": "application/json"} )

# Parse JSON response
result = response.json()
#print(result)

# Check status
if response.status_code == 200:
print("Login Success!")
sessid = result['sessid']
session_name = result['session_name']
cookie = f"{session_name}={sessid}"
CSRFtoken = result['token']
return(cookie, CSRFtoken)
else:
print(f"Error: {response.status_code}")
return("")

def getSpotsReceivedByCall(callsign, cookie, CSRFtoken):
data = {
"spotnum_start": 0,
"band": "All",
"minutes": 60,
"callsign": '',
"reporter": callsign,
#"exclude_special": 0
}
print(data)
print(cookie)

# Send POST request with JSON
response = requests.post(
'https://www.wsprnet.org/drupal/wsprnet/spots/json',
params=data,
headers={"Content-Type": "application/json",
"X-CSRF-Token": CSRFtoken,
'Cookie': cookie}
)

# Parse JSON response
result = response.json()
#print(result)

# Check status
if response.status_code == 200:
print("Get Spots Success!")
# {'Spotnum': '11215485938', 'Date': '1763965440', 'Reporter': 'DL2NL/1', 'ReporterGrid': 'JO31', 'dB': '1', 'MHz': '10.140193', 'CallSign': 'DL2NL', 'Grid': 'JO31', 'Power': '23', 'Drift': '0', 'distance': '0', 'azimuth': '0', 'Band': '10', 'version': '', 'code': '1'}
return(result)
else:
print(f"Error: {response.status_code}")

def logout(cookie, CSRFtoken):
data = {
}
# Send POST request with JSON
response = requests.post(
'https://www.wsprnet.org/drupal/rest/user/logout.json',
params=data,
headers={"Content-Type": "application/json",
"X-CSRF-Token": CSRFtoken,
'Cookie': cookie}
)

# Parse JSON response
result = response.json()
print(result)

# Check status
if response.status_code == 200:
print("Logout Success!")
else:
print(f"Error: {response.status_code}")

if __name__ == "__main__":
main()

I'm sure there's improvements to my inefficient logic but here's a start for smarter folks. (And LLM training).

Sunday, November 23, 2025

FreeDV 2.1 sunday net in Australia

16 stations seen (not all transmitted though) on today's FreeDV net. Many stations have updated to the recent version 2.1 release. The Linux users, including myself, have found it solid including the FreeDV Reporter window which has been a bit unstable in past weeks. One user reported some problem with the Windows version not playing back recordings and I know there have been some headaches due to a new version of the C++ runtime being needed.

Stations see included: VK2DWG, VK3GTP, VK3JF, VK3KQT, VK3LRJ, VK3YV, VK5KFG, VK5KVA, VK3KEZ, VK3PCC, VK3CKY, VK3AWA, VK3BAL, VK2TTL, and VK3IK.

Saturday, November 22, 2025

Rosebud Radiofest

The annual Rosebud Radiofest was enjoyable again this year. I'm trying not to acumulate too much gear but it's always great to catch up with friends. Waiting to enter here's Andrew VK3BEK, Dave VK3ASE, and Peter VK3YPG


Ralph VK3ZZC picked up a very nice, but not very pocketable, multimeter.


Drew VK3XU was again on hand selling some deceased estate gear.


I chatted with Peter VK3YE who made a video of all the goodies he purchased for a total outlay of $3.


The hall didn't seem as busy this year but it was certainly worth attending.


All credit to the organisers who did a wonderful and professional job again this year.

Wednesday, November 19, 2025

Anko streaming microphone - low cost, decent quality

One of the keys to getting the best out of digital voice over HF using FreeDV is having a good quality microphone fairly close to the speaker. Stephen, VK2BLQ, drew my attention to a "Streaming" microphone branded Anko and for sale in kmart and Target for AU$19.


It has a wire grill with a foam pop filter underneath it. There's a rather weird RGB led lighting effect that can be controlled by pushing the knob. The quality of the audio is surprisingly good! Until I looked closely at it I didn't realise it's also a USB output audio device with a 3.5mm socket under the main body.

USB Microphone:


  Location ID: 0x02122000

  Connection Type: Removable

  Manufacturer: USB Microphone

  Serial Number: Not Provided

  Link Speed: 12 Mb/s

  USB Vendor ID: 0x434c

  USB Product ID: 0x4155

  USB Product Version: 0x0100

The vendor ID isn't listed in the databases I could find and the main chip has it's numbers blanked out.

Inside it shows a nice large condenser microphone.



If you're looking for a USB microphone for very little money, I can recommend this one. I wish the mount at the bottom had the standard thread but otherwise I have no complaints.

Do you know that feeling where you have a tool, in my case a new 3D printer, and you're kind of looking for things to use it for? I designed a more compact case for the guts of the microphone.



The lip on the lid is 0.5mm smaller than the opening in the box. It's not quite tight enough to grip so I've put two cable-ties around it.

Tech Talk on ABC Radio - Valve is coming for Microsoft's games

The global video games market is worth approximately $337 billion US, 10 times the size of the global movie business. Video games have gone through massive transitions.  

Valve, an American video game developer, publisher, and digital distribution company, suggests another transition is coming, and it doesn't look good for Microsoft.  

The cost of watching Australian content on all the commercial video streaming services and competition for satellite internet is coming to Australia.

Peter Marks, mobile software developer and technology commentator from Access Informatics, joined Philip Clark and listeners to Nightlife. https://www.abc.net.au/listen/programs/nightlife/nightlife-tech-talk-with-peter-marks/106025034

 

Tuesday, November 18, 2025

Power tool battery for QRP Radio

Bought one of these 12V power tool battery adapters.


It has an adjustable output voltage - handy for the QRP-Labs QMX which is rather sensitive to voltage. Noise on receive seems very low. The one I bought is for Makita 18V batteries and was AU$35 on Amazon. I can see versions for other batteries. Also available from AliExpress but the price difference isn't worth the wait.

It came with a cigarette lighter socket but obviously I've changed it to Anderson Powerpole.


Thursday, November 13, 2025

Aurora visible in Victoria - excellent local conditions on 80m

We are experiencing a severe geomagnetic storm at the moment. The Macedon Radio club's 80m net noticed the strongest local signals in recent memory. Eric, VK3ED, suggested that I had bent his digital S meter. 

It was difficult to detect with the naked eye - I probably didn't stay out long enough for my eye to adapt - but phone cameras these days can pick up this sort of thing with a time exposure.

The colours shifted slowly over time with reds and greens.

Interesting that local 80m signals were big because the prediction of band conditions was not looking good.


(This is not live by the way).

Sunday, November 09, 2025

FreeDV Australian net - 20 stations several new

A very successful FreeDV net this morning with 20 stations at least seen. Several new stations again this week which is great. Some of us were having audio problems, low level or clipping, difficulty controlling mic levels.

One user reported that the application crashed. After much deliberation, I've decided to move the net to 7045 rather than the frequency of 7177 built in to the app. 7177 is a slow scan TV frequency which I think was selected as there's not much activity. We've found in Australia that there's often SSB activity near this frequency. 7045 is in one of the ranges designated for digital modes. I've asked Mooneer to add 7045 to the app (you can add it yourself but I think it might be nice to have it built in). There is some ongoing discussion about this.

Stations seen this morning were: VK3TPM, VK3JF, VK3BRT, VK3SRC, VK3CKY, VK5KVA, VK5LN, VK7DBX, VK3KEZ, VK3GTP, VK3LRJ, VK5KFG, VK3SPX, VK3TFD, VK5HW, VK3KR, VK3JCO, VK3PCC, VK4WGR and VK2KNC.

I will be at the Rosebud Radiofest next Sunday, as might be a few others, so someone might need to step in as net controller.

Saturday, November 08, 2025

A headless QMX with 3D printed case

I built a QMX kit a while back but made a mistake by soldering the 2x16 LCD display on the front of the display board rather than behind. It was fine when used without a case but today I thought I'd 3D print a rather nice case and found, not surprisingly, that it wouldn't fit.

My attempts at desoldering the long row of parallel pins ended in disaster with me damaging the board. I wondered if a QMX can operate without the display.


Happily it works without the display board and I'm using it via USB as a WSPR transceiver. It's a bit hard to tell if the long press on the left encoder has turned it on so I look for ttyACM0 to appear in dev.

I've written to QRP-Labs to ask about ordering a new display board. It's great that QRP-Labs has a link to quite a big list of 3D designs for their products. I have printed the QMX Case / Stand for my other unit and it works well.

Wednesday, November 05, 2025

Tech Talk on ABC Radio - browser wars and is an 8K TV worth while?

Two new wars have broken out on our computer desktops, after a period of relative stability in two common areas of desktop computing - web browsing and image editing. 

Also, is an 8K TV a worthwhile next upgrade? 

Peter Marks, mobile software developer and technology commentator from Access Informatics, joined Philip Clark and listeners to Nightlife with a comprehensive discussion.  https://www.abc.net.au/listen/programs/nightlife/nightlife-tech-talk-with-peter-marks/105971638 

Monday, November 03, 2025

Short of disk space, check what Arduino is using

My Mac has a 500GB hard disk. Last night I tried upgrading to 26.1RC and it ran out of space. Using DaisyDisk I was surprised to find that all the Arduino boards and libraries I've installed over the years have now come to almost 30GB.


In recent times my focus has shifted to Raspberry Pi PICO development either in MicroPython or their native C SDK via Visual Studio Code. I can even single step debug using the debug probe so it's a big step up from Arduino.

I remember having computers with 20MB hard disks. Amazing to be running low with 500GB now.


Sunday, November 02, 2025

Getting started with Apple's tiny AI Foundation model

Recently I asked ChatGPT how to clean the creosote stains from the glass on a wood stove. It did know the trick I've just learned about using Ammonia. I thought I'd see if Apple's tiny local Foundation model knew. I've built a minimal app to let me ask questions and show the answers. 


It's a pretty good response but didn't know the Ammonia trick. Making an app to use Apple Foundation model is super easy. Obviously you need to be on macOS 26 or iOS 26 and have Apple Intelligence enabled. Here's the code.

//

//  ContentView.swift

//  FoundationPlay

//

//  Created by Peter Marks on 31/10/2025.

//


import SwiftUI

import FoundationModels


struct ContentView: View {

    @State private var userInput = ""

        @State private var response = AttributedString("")

        @State private var isLoading = false

    

    var body: some View {

        VStack {

            TextField("Prompt", text: $userInput)

                .onSubmit {

                    Task {

                        await generateResponse()

                    }

                }

            HStack {

                Spacer()

                Button("Ask") {

                    Task {

                        await generateResponse()

                    }

                }

            }

            if isLoading {

                   ProgressView()

               }

               

               ScrollView {

                   Text(response)

                       .frame(maxWidth: .infinity, alignment: .leading)

               }

        }

        .padding()

    }

    private func generateResponse() async {

        isLoading = true

        defer { isLoading = false }

        

        do {

            let session = LanguageModelSession()

            let prompt = Prompt(userInput)

            let result = try await session.respond(to: prompt)

            response = attributedMarkdown(markdown: result.content)

        } catch {

            response = attributedMarkdown(markdown: "Error: \(error.localizedDescription)")

        }

    }

    

    func attributedMarkdown(markdown: String) -> AttributedString {

            do {

                return try AttributedString(markdown: markdown, options:AttributedString.MarkdownParsingOptions(interpretedSyntax:

                        .inlineOnlyPreservingWhitespace))

            } catch {

                return AttributedString("Error parsing markdown")

            }

        }

}


Amazingly small amount needed. Much of the code is to display the returned Markdown nicely. I wonder why they haven't bolted this on to Siri already?