Temperature compensation for an Arduino ultrasonic distance sensor

161.3 cm
27.0°  347.7 m/s

Ultrasonic distance sensors can find the range out to 2-4 meters and are popular in e.g. robotics. Here I look at how the accuracy can be improved by compensating for the variation of speed of sound with temperature. It actually varies quite a lot in air and around 0 C it is:

      c = 331.3 + 0.606 * T

where c is in m/s and T is in C. The formula is good to up to at least +/-30 C. There is also a dependence of humidity, but as it is so small it is neglected here.

The equation can be analyzed for sensitivity (a little bit of differentation, you know). The result is that a two-way range measurement creates an error of 1.8 mm/C/m. That means that with a 4 degree C error, the deviation will be 14.4 mm at a range of 2 meters. Not a lot, but more than the wavelength which is 9 mm at 40 kHz. Considering how easy it is to compensate for, then why not give it a try?


I have tested this with the inexpensive HC-SR04, but the compensation is really independent of the type of sensor. First let me analyze a typical example code for this sensor:

  • For range in cm the code divides elapsed time in microseconds by 29. That corresponds to c=10,000/29=344.8 m/s. According to the equation above, this is the speed for a temperature of 22.3 C.
  • For range in inches it divides elapsed time by 74. That corresponds to c=1,000,000/74 =13513.5 inches/sec =1126 feet/sec or 343.2 m/sec. This boils down to an assumed temperature of 19.6 C. That’s 2.7 degrees lower than the calculation for cm and means that the measurement in inches is lower than that in cm by 2.7*1.8 = 4.9 mm per meter of range. 
Temperature is 27.0°, but the program doesn’t use that
value and assumes instead its standard value of
speed of sound of 344.8 m/s and finds 160.0 cm.

I integrated an HC-SR04 program from Tautvidas Sipavičius with a code from the Arduino playground that uses the DS1820 1-wire temperature sensor (the last program on that page). In the process I had to convert the range estimation from integer to floating point arithmetic. This may give a speed penalty, but at least it runs fine on my Arduino Mega 2560.

The first image in this post shows that at a temperature of 27 C, the speed of sound is 347.7 m/s and the distance from my desk to the ceiling is found to be 161.3 cm. In the picture to the right, I have disabled the temperature compensation so the default velocity of 344.8 m/s is used instead and the estimated distance falls to 160.0 cm.

In the bottom picture, I have detached the 1-wire bus to the temperature sensor, so the program believes it is 0 C, and finds that the range drops to 154.5 cm.

154.5 cm
 0.0°  331.3 m/s

Now, the HC-SR04 isn’t the most advanced of sensors. Other sensors may have a more accurate detection circuit that works more reliably and with better repeatability at longer ranges. I should also say that since I admitted a digit behind the decimal point in my code that wasn’t there in the original, my measurements wandered a bit from ping to ping also. In reality, I don’t think the HC-SR04 has much more accuracy than 1 cm. But it may have some potential for improvement as e.g shown here: “Making a better HC-SR04 Echo Locator“.

Combining a better detector with compensation for speed of sound variations with temperature should be what it takes to get the ultimate range sensor.


The Arduino sketch measures the range every 0.1 second and pauses for a second every 10 seconds to measure the temperature. The code is here (formatted with Hilite Me):

/*
Ultrasound distance measurement with compensation for temperature
Ultrasound sensor : HC-SR04
Temperature sensor: DS1820
LCD: 2 x 16 lines
Created by merging code from
http://www.tautvidas.com/blog/2012/08/distance-sensing-with-ultrasonic-sensor-and-arduino/
and http://playground.arduino.cc/Learning/OneWire (Last program on this page)

Sverre Holm, 30 May 2014
la3za (a) nrrl.no
*/

#include <Wire.h>
#include <OneWire.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
#define LCD_WIDTH 16
#define LCD_HEIGHT 2

#define FIXEDSPEED 0 // turn off temp compensation if == 1

/* Ultrasound sensor */
int pingPin = 12;
int inPin = 13;

/* DS18S20 Temperature chip i/o */

OneWire ds(24); // (4.7K to Vcc is required)

#define MAX_DS1820_SENSORS 1
byte addr[MAX_DS1820_SENSORS][8];

int RepeatTemp = 100; // Temp measurement is done every 100*0.1 sec = 10 sec



void setup() {

lcd.begin(LCD_WIDTH, LCD_HEIGHT);
lcd.print("init ...");

//delay(1000);

if (!ds.search(addr[0]))
{
lcd.setCursor(0,0);
lcd.print("No more addr");
ds.reset_search();
delay(250);
return;
}
if ( !ds.search(addr[1]))
{
lcd.setCursor(0,0);
lcd.print("No more addr");
ds.reset_search();
delay(250);
return;
}

}

int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
char buf[20];

int cntr = RepeatTemp;

void loop() {

// *** Part 1: Measure temperature ***
//
byte i, sensor;
byte present = 0;
byte data[12];

if (cntr == RepeatTemp)
{
for ( sensor=0; sensor<MAX_DS1820_SENSORS; sensor++ )
{
if ( OneWire::crc8( addr[sensor], 7) != addr[sensor][7])
{
lcd.setCursor(0,0);
lcd.print("CRC not valid");
return;
}

if ( addr[sensor][0] != 0x10)
{
lcd.setCursor(0,0);
lcd.print("Not DS18S20 dev ");
return;
}

ds.reset();
ds.select(addr[sensor]);
ds.write(0x44,1); // start conversion, with parasite power on at the end

delay(1000); // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.

present = ds.reset();
ds.select(addr[sensor]);
ds.write(0xBE); // Read Scratchpad

for ( i = 0; i < 9; i++)
{ // we need 9 bytes
data[i] = ds.read();
}

LowByte = data[0];
HighByte = data[1];
TReading = (HighByte << 8) + LowByte;
SignBit = TReading & 0x8000; // test most sig bit -- only for C, not F
if (SignBit) // negative
{
TReading = (TReading ^ 0xffff) + 1; // 2's comp
}
Tc_100 = (TReading*100/2);

Whole = Tc_100 / 100; // separate off the whole and fractional portions
Fract = Tc_100 % 100;

if (MAX_DS1820_SENSORS == 1)
{
sprintf(buf, "%c%d.%d\337 ",SignBit ? '-' : ' ', Whole, Fract < 10 ? 0 : Fract);
}
else
{
sprintf(buf, "%d:%c%d.%d\337C ",sensor,SignBit ? '-' : '+', Whole, Fract < 10 ? 0 : Fract);
}

lcd.setCursor(0,1); //sensor%LCD_HEIGHT);
lcd.print(buf);
}
cntr = 0;
}
//
// *** Part 2: Measure distance ***
//
// establish variables for duration of the ping,
// and the distance result in centimeters:
long duration;
float cm;
float c; // speed of sound
// The sensor is triggered by a HIGH pulse of 10 or more microseconds.
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(10);
digitalWrite(pingPin, LOW);
// Read the signal from the sensor: a HIGH pulse whose
// duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode(inPin, INPUT);
duration = pulseIn(inPin, HIGH);
//
// estimate speed of sound from temperature:
//
if (FIXEDSPEED == 1)
{
c = 10000.0/29; // Original value for c in code
}
else
{
c = 331.3 + 0.606*Tc_100/100;
}

cm = microsecondsToCentimeters(duration, c);

lcd.setCursor(0, 0);
for (i = 0; i < LCD_WIDTH; i = i + 1) {
lcd.print(" ");
}
lcd.setCursor(1, 0);
lcd.print(cm,1); lcd.print(" cm");

lcd.setCursor(8, 1);
lcd.print(c,1); lcd.print("m/s");
delay(100); // measure range every 0.1 seconds
cntr++;

}

float microsecondsToCentimeters(long microseconds, float c) {
// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// -- actually 29 microsec/cm = 10000/29 = 344.8 m/s, ie 22.3 deg C
// The ping travels out and back, so to find the distance of the
// object we take half of the distance travelled.
return microseconds * c / 20000;
}

Sverre Holm, LA3ZA, is a regular contributor to AmateurRadio.com and writes from Norway. Contact him at [email protected].

New Antenna in the ATTIC!

66′ Dipole ready for the attic!

Over the 3 day weekend I finally squeezed in some time to get my 66 foot ladder fed dipole up in the attic.  One leg of the antenna is basically straight, but the other leg had to do a bit of zig-zagging through the trusses – it gets a bit crazy up there!

The ladder line drops down into my garage and then down to the basement where my shack is located.

Last night I built the BL2 1:1 or 4:1 balun from Elecraft.  The ladder line terminates at the balun and a 3′ piece of coax goes from the balun to my KX3.

Wrapped this all up last night about midnight – and then started doing some testing.  The internal tuner on the KX3 tunes ALL bands 40-10 meters almost down to 1:1 SWR.  Very nice.

I tuned around 40 meters and only heard a couple stations that time of night.  The noise level last night was between S4 and S5 – not sure if this is the normal noise level or not, but I suspect it is.

I did a bit of testing using the RBN – I called CQ on 40 meters for a few minutes and ended up with spots North, South and East of Kansas – good sign.  Then I switched antennas back to my 9:1 UNUN 30′ wire in the attic and did the same thing – so reports.  So good news is that my performance on 40 meters is GREATLY improved.  The reports on my 66′ Dipole were from 10-18 DB SNR on the RBN – all with 5 watts out of the KX3.

At 1:00 am local time I heard  K0GPA calling CQ – he was 559 here.  So I threw out my call and he came back to me with a 559 as well.  Turns out he was running a KX3 also – he was at 10 watts, and I was at 5 watts.  The QSB got him a bit, but I think he was using some type of loop – just missed what type.  It was a nice QSO with Bob – and it proved I was getting out!

So now I am looking forward to putting it through the paces a bit more and see just how much my reception will improve with more wire in the air!  I hope to at least have time to look at the waterfall tonight on 20 meters PSK31 to see what it looks like compared to my old antenna.

I will keep you posted!


Burke Jones, NØHYD, is a regular contributor to AmateurRadio.com and writes from Kansas, USA. Contact him at [email protected].

Not a great day, but a better evening

My lunch time QRP session was the pits.  I didn’t work anyone and I kept getting jumpy SWRs.  The KX3 kept wanting to re-tune and I couldn’t get a decent SWR on 15 Meters, which had never been a problem until today.  Last night, I re-soldered the connections to my magmount as the shield connection snapped.  I brought the base in last night, cleaned everything up and re-soldered the wires to new connectors.  When I reassembled the pieces, I thought I had screwed everything down tight.  But when I took the Buddistick apart today at the end of my lunch time session, the threaded stud part of the magmount, that the radiator screws into, was turning pretty freely. Obviously, I didn’t tighten things as well as I had thought. I took care of THAT this evening with the help of two good Craftsmen Hex Grip wrenches.  Tomorrow should be better. Even if I don’t end up working anyone, the KX3 should be a happier camper than it was today.

Tonight however, was a different story. I worked W1AW/7 in WY and W1AW/0 in MO on 30 Meters, back to back. Then I hopped on over to 15 Meters just in time for the grayline to give me a hand.  Although I used QRO power (75 Watts), I was able to snare two good ones – E51KJW, South Cook Island and FW5JJ, Wallis and Futuna Islands.  I had to work FW5JJ twice, as the first time he had me in his log as “W2LO”. Big time dilemma. At that point, what do you do?  I knew he had me wrong, but I didn’t want to call again right away, so I went and worked E51KJW who got my call right the first time. After working Nakayama, I thought I’d give FW5JJ a second shot. I was worried that I would get the dreaded “WRKD B4”, but this time he heard me correctly and I clearly heard “W2LJ” this time. Two new DXCC entities in the log – Booyah!

Going to shut the rig down now and head upstairs to watch “The World Wars” series that is running on The History Channel.  I’ve been watching it since Monday night. So far it’s been a very good documentary assessing how World War II was really just a continuation of World War I. And although I always considered myself pretty familar with the histories of both wars, there have been some new tidbits of information that were new to me, which is always fun.

72 de Larry W2LJ
QRP – When you care to send the very least!


Larry Makoski, W2LJ, is a regular contributor to AmateurRadio.com and writes from New Jersey, USA. Contact him at [email protected].

Music and Mountains

This past Monday was Memorial Day in the US. A day to remember those who paid the ultimate sacrifice in defense of Freedom and our Country. I am grateful for the dedication and patriotism of these Americans.

Memorial Day Weekend is therefore a Holiday weekend that finds many of us enjoying a three day weekend. The weekend was busy and memorable one for me. The weekend began with a 300 mile drive to play a show with my band, The No Refund Band, at a venue in Crystal Beach, TX. Crystal Beach is on the Bolivar Peninsula, east of Galveston Island on the Texas Coast. We had a great show there. (You can check out my band at norefundband.com )

The next morning (Sunday), my XYL Cris and I got in the Jeep and headed to the Ouachita Mountains in Oklahoma. This would be a 430 mile drive with the purpose of getting as many SOTA points as possible. The drive from Houston was very nice. North of Houston you take Hwy. 19 which goes through the piney woods of east Texas. Of course Texas is a big state and on this highway alone I went through Palestine, Athens, Canton and Paris. The road is nice and the speed limit is 70 - 75 mph and the traffic was light. As long drives go, this one wasn't bad.

The Ouachita Mountains cover southeastern Oklahoma and west central Arkansas. Along with the Ozark Mountains, the Ouachita Mountains form the U.S Interior Highlands, one of the major mountainous regions between the Rocky Mountains and the Appalachian Mountains. It is a beautiful area that is very green and lush with mountains and valleys that induce tranquility.

From a SOTA perspective I had done my research to find the most efficient route to accumulate the most points in relatively short amount of time. I had to be backon Tuesday for work, so I would have 24 hours get as many points as possible.

Sycamore Lookout W5O/OU-005 (8 pts)*

We arrived 20:15 UTC. The summit has easy access from the highway and I was QRV by 20:35. I set up next to the commercial antenna's with no RF issues. The bands were not in good shape and the WPX contest was in full swing. I made 10 QSO's in 25 minutes on 17 and 40 meters and decided to move on to the next one.

Peak 2210 W5O/OU-006 (8pts)*

This summit is just up the road a few miles and the highway is in the activation zone. I did ascend about 50 feet vertically to the summit. I set up just below the summit ridge. Unfortunately, the cell service was spotty and I wasn't able to spot myself. For some reason I wasn't picked up by the RBN network either. Consequently I called CQ for 10 minutes on 17m with no responses. I finally had cell service long enough to get a call off to Fred, KT5X, to ask him to spot me. It still took me 10 minutes after the spot to get my 4 QSO's. Conditions were not good.

Winding Stair Mountain W5O/OU-002 (10 pts)*

Winding Stair Mountain is a nice hike. The trail head is across the road from the Campground and the hike is about 3 miles roundtrip. We encountered a troop of Boy Scouts training for their upcoming 68 mile trek at the Philmont Scout Ranch in New Mexico. Conditions were only marginally better, I made 11 QSO's in 25 minutes.

After this summit we made out way to the Green Country Inn in Heavener, Oklahoma where we had a room. The hotel is a great place to stay if you find yourself in the area. The next morning began early to make sure we got to the summits we planned.

Lynn Mountain W5O/OU-001 (10 pts)*

Getting to this summit is best done with a 4WD vehicle. While a 2WD would make it most days, a 4WD is preferred. The road does enter the activation zone, but I took an ATV trail for the short walk to the summit. This summit is very green and overgrown so I operated from the trail. The weather was overcast and as I left the Jeep it started to rain. We were prepared with rain gear and umbrellas to provide a mini-shack on the summit. There was a light rain during the entire activation. Conditions were a little better and, since the WPX contest was over, 20m was available again. I was on the air at 1335 UTC, so I think I was a little early for propagation and some late rising operators. I made 12 QSO's on 20m and 40m.

Pigeon Benchmark W5O/OU-013 (10 pts)*

This summit is off the same road as Lynn Mountain. The hike to the activation zone is a 2 mile round trip. The trail to the summit is an overgrown ATV trail. The walking is easy with about a 220 foot elevation gain over the mile to the top. The grass on the trail is knee high and it was wet from the rain, so it was a very wet hike. Conditions were much better as I was QRV at 1510 and made 20 QSO's on 20 and 40 meters.

Rough Mountain W5O/OU-014 (8 pts) *

The road to this trail head requires a 4WD. The road crosses the Ouachita trail a about a mile in from Hwy. 259. This is nice 2.5 mile round trip hike with about 500 ft. elevation gain over the 1.25 miles to the summit. The trail is nice. I made 22 QSO's from here.

*Additional details on how to get to these summits can be found on the SotaWatch page for each summit

So there you have it, 54 SOTA points in 24 hours. We had a 500 mile drive home that we made in about 8 hours. So in total we traveled 1,200 plus miles to enjoy music and mountains to make memorable Memorial Day weekend.

A short highlight video can be found here:

https://www.youtube.com/watch?v=NZhGh-XATJ0





Mike Crownover, AD5A, is a regular contributor to AmateurRadio.com and writes from Texas, USA. Contact him at [email protected].

Homebrew Buddipole

In a couple earlier posts, I wrote about making a homebrew Buddistick using Budd Drummand’s (W3FF) plans. His plans can be found on his page located here: https://sites.google.com/site/w3ffhomepage/.

I knew when I started building my station that I wanted a couple of portable antennas. I like making things, and decided to give his antennas a shot after deciding that I might be able to actually make an antenna that worked following Budd’s directions. I made the Buddistick first, then later made the Buddipole. Both are easy to make and work well. I use them both (not at the same time) for my main antenna right now, until I can get a full size dipole hung up, and coax run to the house etc. I am fairly new to the HF world and I don’t have my home station complete yet, so these antenna were a quick and easy way for me to get started on HF.

Pictured first are the components of the Buddipole. Starting at the top-left are the two 20 meter coils. To the right, the shorter coil set is for 15 and 17 meters. To their right is the “T” component for mounting the antenna on a painters pole. The black adapter changes the threads from PVC to the painters pole. In the middle are the two antenna whips, mounted in some CPVC with speaker wire coming out of the ends allowing for connections to be made to the whips. The bottom two pieces are CPVC arms with speaker wire running through them, and connectors.

The following picture shows the Buddipole set up with the painters pole extended. The length of the extended painters pole in this picture is about 10 ft.

The plans that Budd published has the coax line ending with the spade connectors. I bought a piece of 50ft coax with PL-259’s installed already on both ends and I did not want to cut one of them off, so I made the following adapter. It is simply a small project box from Radio Shack, with a SO-239 mounted in it and speaker wires connected to the SO-239 center and ground. The orange line is old fly fishing line for hanging the box from the antenna. I use a velcro strip for this.

Here is a table that I made showing how I setup the antenna and the resulting SWR measurements. I think the higher SWR on 20 and 6 meters is due to the proximity of the metal eve troughs that the antenna is near with extended. If I orient the antenna parallel to the gutter, the SWR goes up. My house sits approx SW-NE so pointing the red end of the antenna North puts it at about 45 degrees to the gutter and the SWR goes down. This is the most convenient place to set up the antenna within reach of the radio inside allowing for the 50ft run of coax. The whip column is how many additional sections of the whip I need to extend not counting the 1 section length it is with all the sections pushed in. I think if I got this away from the house a few more feet, the SWR would come down on 20 & 6m.

 

BandCoilRed WhipBlack WhipRes FreqMin SWRHeightRed Orientation
20M20M3 + 10 in514.1751.512N
17M15/173 + 1.25 in518.1271.0612N
15M15/172 + 2 in321.2501.2412N
10Mnone4 + 5 in428.8501.1912N
6Mnone0 + 4.375 in051.8501.212N

 

I have made SSB and PSK31 contacts on 20, 17, & 15 meters. I have not made contacts yet on 10 or 6. Someday I’ll do that.

Below are the graphs from my antenna analyzer showing the antenna setup for each band in the table above.

20 Meter

17 Meter

15 Meter

6 Meter

 

Overall I am happy with the antenna. I don’t expect it to work like a full size dipole, but for the ease of setup and take down, it’s working for me. I have talked to South America, Europe and all over the US with both  the home-brew Buddistick and Buddipoles.

My email address is on my QRZ.com profile. If anyone has questions, I’ll be glad to respond to any email.

 



Wayne Patton, K5UNX, is a regular contributor to AmateurRadio.com and writes from Arkansas, USA. Contact him at [email protected].

ALTV Episode 67 stream

Who’s up for some AmateurLogic.TV streaming Thursday evening. Tommy and George will be putting the Dayton Episode together. Begins around 6PM CDT, 2300 UTC.
The show won’t be released until next month, but you can get an advanced viewing as we put it together.
The stream is live now. Watch it here live:

Chat room is at www.amateurlogic.tv/chat


George Thomas, W5JDX, is co-host of AmateurLogic.TV, an original amateur radio video program hosted by George Thomas (W5JDX), Tommy Martin (N5ZNO), Peter Berrett (VK3PB), and Emile Diodene (KE5QKR). Contact him at [email protected].

Time to play with GPS and Arduino

I’ve always enjoyed playing about with time. Accurate time is not really a fascination but I do like a clock to tell the time. The MSF 60khz time signal is one source and I have played about with that system with an Arduino and it works well, when there is a good signal for a whole minute. GPS time has always been a bit of a thing for me because you can set it to UTC and it’ll always show UTC and frankly there are a lot more libraries available to play with. GPS Tiny & GPS Tiny+ are two of those and this evening I ‘forked’ a sketch to use a cheapo off the shelf gps module to tell the time and date on a 16×2 LCD. Nothing spectacular but hey if I can do it then so can anyone. Here’s a short sweet video of it in action (near the window!)

sketch goes a little like this


#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <LiquidCrystal.h>
/*
This sample sketch demonstrates the normal use of a TinyGPS++ (TinyGPSPlus) object.
It requires the use of SoftwareSerial, and assumes that you have a
4800-baud serial GPS device hooked up on pins 8(rx) and 9(tx).
*/
static const int RXPin = 8, TXPin = 9;
static const uint32_t GPSBaud = 9600;
// The TinyGPS++ object
TinyGPSPlus gps;
// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup()
{
ss.begin(GPSBaud);
lcd.begin(16,2);
lcd.setCursor(1,0);
lcd.print("Tiny GPS+ Time");
delay(3000);
lcd.setCursor(1,2);
lcd.print("by Alex, g7kse");
delay(5000);
lcd.clear();
}
void loop()
{
// This sketch displays information every time a new sentence is correctly encoded.
while (ss.available() > 0)
if (gps.encode(ss.read()))
displayInfo();
if (millis() > 5000 && gps.charsProcessed() < 10)
{
lcd.print("No GPS detected");
for (int positionCounter = 0; positionCounter < 20; positionCounter++) {
while(true);
}
}
}
void displayInfo()
{
lcd.setCursor(4,0);
{
if (gps.time.hour() < 10) lcd.print(F("0"));
lcd.print(gps.time.hour());
lcd.print(F(":"));
if (gps.time.minute() < 10) lcd.print(F("0"));
lcd.print(gps.time.minute());
lcd.print(F(":"));
if (gps.time.second() < 10) lcd.print(F("0"));
lcd.print(gps.time.second());
}
lcd.setCursor(3,2);
{
if (gps.date.day() < 10) lcd.print(F("0"));
lcd.print(gps.date.day());
lcd.print(F("/"));
if (gps.date.month() < 10) lcd.print(F("0"));
lcd.print(gps.date.month());
lcd.print(F("/"));
lcd.print(gps.date.year());
}
}


Alex Hill, G7KSE, is a regular contributor to AmateurRadio.com and writes from Cumbria, UK. Contact him at [email protected].

Subscribe FREE to AmateurRadio.com's
Amateur Radio Newsletter

 
We never share your e-mail address.


Do you like to write?
Interesting project to share?
Helpful tips and ideas for other hams?

Submit an article and we will review it for publication on AmateurRadio.com!

Have a ham radio product or service?
Consider advertising on our site.

Are you a reporter covering ham radio?
Find ham radio experts for your story.

How to Set Up a Ham Radio Blog
Get started in less than 15 minutes!


  • Matt W1MST, Managing Editor