A really simple C# async example

Asynchronous programming is awesome, and C# makes it very easy.  At a high level, asynchronous programming is all about not letting independent tasks block each other so you can do more than one thing at a time.  One common analogy used to describe the asynchronous pattern is cooking.  Let’s say I am a chef in a restaurant, and a breakfast order comes in for eggs, toast, and an apple.  If I were to prepare this meal synchronously, I would crack an egg on the griddle, wait for it to cook, and put it on the plate.  Then I would put bread in the toaster, wait for it to pop up, and put the toast on the plate.  Finally, I would get the apple from the refrigerator, and put it on the plate to complete the order.  But this is clearly an inefficient way to get the work done, and in the real world we would never do this – there’s no need to wait for the eggs to complete before starting the toast and vice-versa.  It makes more sense to prepare the meal asynchronously.  To more efficiently do all the work required to prepare the meal, I would crack the egg on the griddle, then put the bread in the toaster.  While I’m waiting for those two long running tasks to finish, I can get the apple from the fridge and put it on the plate since the execution of that task is not blocked or prevented by making eggs or toast.  Now I can just wait until both the eggs and toast are done, and I can complete the order.  I’ve created a significant gain in efficiency by letting two independent tasks run at the same time, and doing the comparatively shorter task(s) while waiting for both to complete.

Let’s take this example of waiting for long running tasks to complete into some code.  Suppose your application needs to call three methods to get the data required for constructing a new object.  Following the same synchronous approach as the first breakfast order, we call each of the three methods one after the other, and use the data returned to construct the new SampleData object. Here’s a quick example:

public static void DoStuff()
    var foo = Foo();
    var bar = Bar();
    var baz = Baz(); 

    var sample = new SampleData(foo, bar, baz);


There is nothing inherently wrong with this code, but what if one or more of those methods take a significant amount of time to execute?  Suppose Foo() makes an HTTP request to an API that is responding slowly, Bar() is application code that performs a lengthy calculation or database query, and Baz() is something that executes very quickly.  Since none of these three methods are dependent on the return values of each other, we can gain significant performance by running them all at once, and then waiting for the potentially longer operations to complete before creating our SampleData object – this is asynchronous programming.

There are many, many documents, articles, and blog posts out there that do an excellent job of dissecting and explaining asynchronous programming with C# in detail, so I’m not going to rehash that same information here.  One of my favorites is Async and Await by Stephen Cleary.  I would also recommend Asynchronous programming with async and await (C#) from Microsoft for a more in-depth look at what happens behind the scenes with asynchronous method execution.  And without trying to further complicate the issue, I think it’s important to point out that asynchronous programming is not the same thing as multi-threaded programming in C# – see: What is the difference between asynchronous programming and multithreading?

This post is for people like myself – programmers who learn better from jumping right into code and stepping through each line to see how a program executes.  When I’m first exploring an unfamiliar concept, reading documents and looking at sample code snippets can sometimes be a bit confusing or overwhelming.  In many cases, I learn best when I can see a concept in a working, concrete form.  I’ve created a small .NET 4.7.1 console application that will walk you through asynchronous programming with C# using a complete and practical example.  The repository is accessible here:


Let’s get started!  Clone the repository, and open up the solution. You will see two source code files inside, Program.cs and SampleDataLayer.cs.

Let’s look at the Main() method in Program.cs – this is our application entry point.  You will notice that the method declaration of Main() includes the “async” keyword.  This is because inside Main() we will be calling and awaiting on some asynchronous methods.  Always remember that the “async” keyword simply enables the use of the “await” keyword inside a method.  Inside Main(), we are going to run a small experiment by calling two methods: RunDemoSynchronous() and RunDemoAsync().  The methods both contain nearly the same code, but RunDemoSynchronous() will execute synchronously and RunDemoAsync() will execute asynchronously.  We will compare the performance of each.  Here is the entire Main() method:

static async Task Main()
    Stopwatch s = new Stopwatch();

    // RunDemoSynchronous() will call three methods in SampleDataLayer synchronously

    Console.WriteLine("RunDemoSynchronous() complete. Elapsed seconds: " + s.Elapsed.TotalSeconds + Environment.NewLine);

    // RunDemoAsync() will call three methods in SampleDataLayer asynchronously
    await RunDemoAsync();
    Console.WriteLine("RunDemoAsynchronous() complete. Elapsed seconds: " + s.Elapsed.TotalSeconds + Environment.NewLine);

    Console.WriteLine("Demo complete.");


To begin, let’s run the application and see the output:

Inside Main(), we create a Stopwatch object and use it to capture the elapsed execution time when calling RunDemoSynchronous() and RunDemoAsync(). We can see from the console output that RunDemoAsync() ran about 3 seconds quicker than RunDemoSynchronous().  So what’s happening when each of these methods are called?

The first half of the experiment starts by calling RunDemoSynchronous() and a message is logged to the console to indicate we have begun execution of this method (“RunDemoSynchronous()  start.”).  Inside, three methods are called to fetch the data necessary to construct our SampleData object:

var dataA = GetDelayedApiResponse(_apiWaitTime);
var dataB = SimulateLongProcess(_methodWaitTime);
var dataC = Foo();


GetDelayedApiResponse() calls an API that waits for a specified number of seconds before responding to simulate a lengthy API request.  Here is the GetDelayedApiResponse() method as it is written in SampleDataLayer.cs:

public static string GetDelayedApiResponse(int seconds)
   using (WebClient client = new WebClient())
      Console.WriteLine("GetDelayedApiResponse() start.");
      var message = client.DownloadString(string.Concat(_apiUrl, seconds));
      Console.WriteLine("GetDelayedApiResponse() complete.");
      return message.Trim('"');


The program also outputs a message to the console here when we enter the method, and again after the WebClient received the response.  The app will output similar console messages throughout so we can see the current status of the program as it is executing – this is just some good old fashioned printf() debugging.

After exiting GetDelayedApiResponse(), we move on to the next line in RunDemoSynchronous(), calling SimulateLongProcess().  This method simulates long running application logic in our code by simply pausing for the specified number of seconds.  This method could represent a CPU-intensive calculation, a database query, or any other lengthy process in your code.

public static string SimulateLongProcess(int seconds)
    Console.WriteLine("SimulateLongProcess() start.");
    Thread.Sleep(seconds * 1000); 
    var data = "Hello, world!";
    Console.WriteLine("SimulateLongProcess() complete.");

    return data;


The last method we call before we can construct or SampleData object is Foo().  This method simulates short running work in application code, and will return almost immediately.

public static int Foo()
   Console.WriteLine("Foo() start.");
   var n = Bar(10);
   Console.WriteLine("Foo() complete.");

   return n;

private static int Bar(int n)
   return 100 * n;


Back inside RunDemoSynchronous(), we have now called three methods and stored their return data in three variables.  We can now create our SampleData object, exit the method, and stop the currently running Stopwatch.

SampleData sample = new SampleData(dataA, dataB, dataC);


The three methods we just called, GetDelayedApiResponse(), SimulateLongProcess(), and Foo(), were blocking because they were called synchronously, one after the other.  We can verify this by looking at the console output:

GetDelayedApiResponse() starts and completes, then SimulateLongProcess() starts and completes, and finally Foo() starts and completes.  RunDemoSynchronous() took about 7 seconds because we set the delay time for GetDelayedApiResponse() and SimulateLongProcess() to 4 and 3 seconds, respectively.  The execution time of Foo() is comparatively much quicker, adding only a fraction of a second to the total execution time.

We can achieve a significant performance gain by implementing an asynchronous pattern and running those methods all at once, waiting for each to complete before we construct the SampleData object.  GetDelayedApiResponse() and SimulateLongProcess() do not need to know about each others’ output, so we can execute both at the same time.  While we wait for the output of those two methods, we can call Foo().

Back in the Main() method, the second part of the experiment is run by calling RunDemoAsync().  This method will demonstrate asynchronously executing the exact same workflow as we did above.  As a result, we will see a significant performance gain.  First, we reset the stopwatch and call RunDemoAsync().  Notice the change in syntax when calling this method:

await RunDemoAsync();


RunDemoAsync() is a an async method, and we need to wait for it to complete before stopping our stopwatch by using the await keyword.  Once we’re inside RunDemoAsync(), we get variables dataA, dataB, and dataC in a similar fashion as we did above, but we are now calling GetDelayedApiResponseAsync() and SimulateLongProcessAsync() instead.  These are asynchronous versions of GetDelayedApiResponse() and SimulateLongProcess().  Async methods usually return Task, which is just an asynchronous operation that can return a value.  (If the async method returns null, Task is returned).

Task dataA = SampleDataLayer.GetDelayedApiResponseAsync(_getDelayedApiResponseWaitTime);
Task dataB = SampleDataLayer.SimulateLongProcessAsync(_simulateLongProcessWaitTime);
int dataC = SampleDataLayer.Foo();


Let’s take a closer look again at the console output and see how the execution flow differs inside RunDemoAsync().

Notice this time that GetDelayedApiResponseAsync() is started, but instead of the next console line reading “GetDelayedApiResponseAsync() complete” as we saw in the first example, we see “SimulateLongProcessAsync() start” and “Foo() start” on the next lines.  From this output, we can see that the next two lines of code were called without waiting for the first line to finish executing.  Let’s take a look at GetDelayedApiResponseAsync():

public async static Task<string> GetDelayedApiResponseAsync(int seconds)
    using (WebClient client = new WebClient())
        Console.WriteLine("GetDelayedApiResponseAsync() start.");
        var message = await client.DownloadStringTaskAsync(string.Concat(_apiUrl, seconds));
        Console.WriteLine("GetDelayedApiResponseAsync() complete.");
        return message.Trim('"');


The method return value is now a Task, and the method declaration also includes the “async” keyword.  Remember that using the async keyword enables the use of the “await” keyword in a method.  We’re using the WebClient class to make the request to the API.  GetDelayedApiResponse() used the WebClient.DownloadString() method to make the API request, but in GetDelayedApiResponseAsync(), we will use WebClient.DownloadStringTaskAsync() instead.  Because we made our method async, we can await on DownloadStringTaskAsync().  The program will execute up until this line, and while awaiting for DownloadStringTaskAsync() to come back with our API response, the execution flow will return to the next line in RunDemoSynchronous().

SimulateLongProcessAsync() is written in a similar fashion – the return type is now a Task, and we’ve added the async keyword to the method declaration:

public async static Task<string> SimulateLongProcessAsync(int seconds)
    Console.WriteLine("SimulateLongProcessAsync() start.");
    await Task.Delay(seconds * 1000);(seconds * 1000);
    string data = "Hello, world!";
    Console.WriteLine("SimulateLongProcessAsync() complete.");

    return data;


We are just pausing execution of the program here as we did in SimulateLongProcess(), only this time we will call an async method inside, awaiting on Task.Delay() rather than calling Thread.Sleep().  Once again, making our method async simply means enabling the use of the “await” keyword within.  Just like GetDelayedApiResponseAsync(), once we reach this line:

await Task.Delay(seconds * 1000);(seconds * 1000);


The execution flow of the program returns to the method that called our async method.  Now that we have called those two async methods, we’re back at this line in RunDemoAsync():

var dataC = Foo();


Foo() remains unchanged in the second part of our experiment – it is still a synchronous method and we still call it synchronously.   We know that Foo() gets called and executes very quickly, so we will need to wait for the other two methods to return before we can create our object:

SampleData sample = new SampleData(await dataA, await dataB, dataC);


As soon as the program is done awaiting dataA and dataB, the SampleData object will be constructed, and the Console will output the “SampleData object ‘sample’ created” message along with the values of each property in the object. Method RunDemoAsynchronous() will exit, and we return to the Main() method where the final messages indicating that RunDemoAsynchronous() is complete are written to the console.  The elapsed time to complete the second half of the experiment is just over 4 seconds – a little bit more than a 3 second improvement in total execution time over the RunDemoSynchronous() method!

This represents quite a significant improvement in the application’s performance.  By implementing an asynchronous pattern in the program, we get where we need to be more quickly than we did before, and the benefit is easy to see.  This is just one example of asynchronous programming, and it only scratches the surface.  There are many ways to implement the asynchronous programming pattern and I hope this post serves as a jumping off point for others to leverage similar patterns in their C# applications.

Refurbished Radio Shack Pro-2021

Recently, I was on the hunt for a desktop scanner for my desk at work. I didn’t need anything new or high tech since this would just be for casual listening to the VHF local and wildfire comms, area ham and GMRS repeaters, NOAA, etc. I love old radios, especially Realistic/Radio Shack, so I began hunting for an old RS scanner that I could turn into a little low-budget project and keep an old radio in service. I found a Pro-2021 locally on Craigslist for $20. It powered up and received OK, but the pots were scratchy and it was kinda dingy looking:

I’m definitely not a skilled electrical engineer so finding a scanner in good working order was important. I popped off the cover and an was quite surprised to see that it looked brand new inside. This scanner appears to have been well taken care of, despite a somewhat cosmetically unappealing exterior:

While I had the scanner open, I hit the volume and squelch potentiometers with a tiny bit of Deoxit, and the scratchiness on the output when operating them went away. The volume works smoothly across the range and audio output quality is excellent. A whole lot of elbow grease took care of cleaning up the exterior including the front panel and controls.

The next step was getting a decent antenna for the scanner – a flimsy telescoping back-of-set antenna did not work well for me inside the steel and concrete office building, and height/placement is very limited in a crowded office. In the spirit with keeping the budget low, I dug around my parts bin to see what I could come up with. On hand, I had a NMO bracket mount I ended up not using on my F-150 install. I sanded, primed, and painted the mount black to match the radio:

Almost there! I picked up a Laird A150/450C online for $25, and stopped by a local radio shop for an NMO mount + BNC terminal for $20. All in for $65 at this point for the Pro-2021 mini project. I fastened the antenna mount to the back of the radio like this:

The additional 2 inches of antenna height on this bracket really makes a difference! The coax is terminated with a right angle BNC => Motorola connector. Here is the final result:

It’s not too pretty, but it looks OK on a software developer’s desk! The audio quality and reception is great, I’m hearing distant VHF stations clearly inside my office. This radio will be in use for many more years to come.


One bad crimp job on the BNC terminal later, I finally have the scanner all set up on my desk at work. I had initially brought the radio into work, but soon realized that I did not properly terminate the coax from my antenna mount, and reception was becoming noticeably poor. I ordered one more NMO mount and a BNC connector, re-did the coax with extra care, and now I finally have a working radio for my desk!

I have the audio from the scanner, audio from the laptop next to it, and audio from my phone all feeding into a Behringer Micromix 400 that is sitting on top of the Pro-2021. This allows me to use one pair of headphones for listening to everything while at my desk.

How to get a GMRS license

General Mobile Radio Service (GMRS) is a land-mobile UHF radio service in the United States, near 462 and 467 MHz. GMRS shares the same frequencies with the Family Radio Service (FRS), however output power is limited to 0.5 or 2 watts on FRS, depending on the channel. A license is required to operate on the GMRS band, and the licensee is allowed up to 5 or 50 watts of output power (also depending on the channel). A GMRS license also grants permission to operate on the repeater input frequencies.  Both the increased output power and the repeater access granted by a GMRS license can dramatically increase the effective range a GMRS radio has over a FRS radio.  Because they share the same frequencies, GMRS radios are allowed to communicate with FRS radios via simplex.

To obtain a GMRS license and call sign, you must file an application with the FCC and pay a $70 fee.  No exam is required, and the license is valid for 10 years.  The FCC’s Universal Licensing System (ULS) is is an online portal to manage your FCC applications/licenses, and pay any applicable fees via a single account. The ULS eliminates the need for paper applications and submitting via snail mail. You may also view the status of pending licenses in the ULS.  Once registered with the ULS, you will receive an FCC Registration Number (FRN).  This is a 10-digit number that is assigned to a business or individual registering with the FCC, and is used to identify the registrant’s business dealings with the FCC.  Once you have this ID number – save it!  This will be your user name to log in to the Universal Licensing System.

Before continuing, I want to highlight one very important consideration when dealing with FCC licenses.  Your call sign and license information is public information and is easily searchable in FCC databases and other records.  Should you choose to register with your home address, this will be visible to anybody if they have your call sign.  Exposing personal information on the internet is a concern now more than ever, so one approach to limiting the amount of personal information in FCC databases is to use a P.O. Box as your contact address.  Here is what my GMRS license information looks like when queried in the FCC database – WRAA720:

I use this P.O. Box address in the center of my local metro area as my primary contact location for all FCC forms and dealings. My actual home address is not associated with any of my FCC licenses and will not be in any FCC databases or in other databases that use FCC data such as QRZ.com.

Step 1: Create an FCC Universal Licensing System account

If you are a first time user, create a new ULS account here (skip this step if you have an existing ULS account).  Select “Register” to be issued a new FCC Registration Number:

Some questions are asked before proceeding, then you can fill out an application with your name, address, password, etc:

Step 2: Log in to the ULS

After creating the account, or if you have an existing ULS account, log in here.

Once you are logged in, you will be taken to this screen which shows your current and applied for licenses:

Step 3: Begin application for a GMRS license

Now we can apply for a GMRS license and pay the fee.  On the left hand side menu click “Apply for a New License.”

On the next screen, select “ZA-General Mobile Radio Service” from the very bottom of the drop down menu and click Continue.

The next step is to answer these applicant questions.  Most people can leave “no” selected for each:

Click continue after these questions, and on the next screen supply the licensee name and address:

Once this is complete, click Continue.  The next step is to answer the following question, then click Continue again:

The next step will show you a summary of the application.  Verify all the information supplied is correct, and click “Continue to Certify.”

Step 4: Submit the application

The final step before submitting application is reading all the certification statements, which summarize the rules you are agreeing to follow as a GMRS license holder.  Electronically sign the application and submit:

When you submit the application, you will be prompted to complete payment.  After that, all you can do is wait!  Applications will appear in ULS Application Search in about one or two businesses days after the application is filed. If you made an error in the application – don’t worry!  You can file an amendment to the application.  See the Applying for a New License in the Universal Licensing System FAQ for more information about the application process for FCC licenses.

I have read posts online where people have reported getting their license within a day, and I’ve read posts where people said it took three weeks, so I can’t give an accurate answer to the “how long until I receive my call sign?” question.  I applied for my GMRS license around the holidays and it took two weeks to receive my call sign.

Step 5: Receive call sign and download authorization documents

Check back to the Universal Licensing System daily, and when you see the call sign under “My Licenses” you are ready to get on the air!  To download or print a paper copy of the license authorization, click Download Electronic Authorizations:

Select your GMRS call sign from the “Filter by Radio Service” box and add it to the “Authorizations to Download” box then click Download:

The GMRS Authorization looks like this:


The history behind 462.675 MHz and the travel tone

I came across the North Shore Emergency Association’s website recently and found their club history page interesting:


This link briefly discusses how the “travel tone” of 141.3 Hz and the national calling/emergency frequency of 462.675 MHz came to be. NSEA was one of the very first adopters of GMRS in the early 1970s, then the Class “A” Citizens Band. Here’s a quick snippet from the link

NSEA members were instrumental in bringing UHF technology to other public service groups in CB, especially R.E.A.C.T. (Radio Emergency Associated Citizens Teams). Beginning in 1976 key NSEA members spent extensive time meeting with REACT teams in more than a dozen-and-a-half different states, bringing a portable repeater, together with a number of mobile and portable units for field demonstrations…As a result, over 200 personal use repeater systems (all on the same frequency [462.675 MHz]) were set up throughout the United States. In recognition of this trend of explosive growth the Federal Communications Commission formally recognized our frequency [462.675 MHz] as the national emergency and traveler’s assistance channel in the Part 95A Rules and Regulations.

Here is another good quick read about the travel tone, written by Doug Smith, KAF9830:


Pretty cool slice of radio history!

K7MFC Field Report: Four Peaks, AZ

The Tonto National Forest in Arizona lifted all fire restrictions on Friday morning, so me and a buddy threw the camping gear and some radios in the truck and headed up the Four Peaks Road. For those unfamiliar with the area, about 30 miles north on AZ Highway 87 from Highway 202 in Mesa, AZ is the entrance to the Four Peaks Wilderness Area, part of the Tonto National Forest. After exiting the highway, it’s about a 20 mile drive on Forest Rd 143, which will take you all the way up to Browns Peak. This video from azoffroad.net shows what the drive is like. We made it up about 3/4 of the way before sunset and made camp at about 4500′. The next day we broke camp and headed to the peaks, where we encountered a locked gate. Some firefighters in a UTV arrived to unlock it for the public, but some idiot had apparently shot at the padlock attempting to open it themselves and damaged it so that the combination would not work. I noticed that one of the firefighters working on the gate was radioing for some tools, and observed frequency 168.35 MHz and tone 123.0 Hz in use on the his handheld. This is the FEDTRVL channel. This and FEDCOMN1 on 168.1 MHz are common channels used for communications between units that are traveling.

I did not photograph him or his radio, but it appeared to be a large Motorola handheld with an approximately 3 foot whip on it – maybe a 1/2 wave for that band? For any Arizona folks out there, I would encourage reading the Arizona Department of Forestry and Fire Management’s Wildland Fire Radio Communications Guide. It contains lots of good information on the radio systems and common/mutual aid frequencies used by wild land firefighters throughout the state. The ADFFM does a daily VHF broadcast of current fire conditions in the state – super useful for camping and offloading during the fire season.

I was monitoring the 2m band at this time as well on the Kenwood TM-281A in my truck. I heard lots of activity on 146.52 MHz as usual for the Phoenix area, and it was easy to hear all the local simplex traffic at this elevation. 147.52 MHz is a popular 4×4/offroad frequency for hams he in AZ, but I did not hear any traffic or make any contacts this day. I suspect there were not a whole lot of people out on the trails just yet, we headed out just hours after the USFS announced fire restrictions had been lifted. I was also able to hit the Arizona Repeater Association’s Mt Ord repeater on 146.36 MHz.

I was also monitoring the GMRS band and had my main camping HT, a Btech GMRS-V1:

From my location near the top of the peaks, I had a direct line of sight of about 75 miles to the White Tanks mountains on the other side of the Phoenix metro area. The Arizona GMRS Repeater Club has a 50W GMRS repeater at a commercial site atop these mountains at about 4000′:

As soon as I turned on the radio I heard another club member loud and clear and gave him a quick hello. I received a good signal report back, and I also made contact with another club member. Reception was a little bit spotty, but moving around along the western face of the Four Peaks from about 5000′ and above allowed me to have decently clear RX and TX to the AGRC repeater. I camp and do some off roading in this area regularly, and I’m glad to know that I can have reliable 2m and GMRS radio contact for emergencies once I get above the smaller hills. The majority of the stretch of dirt road leading to the peaks does not have cell phone coverage from my provider, Verizon.

After the gate was opened for the public, we continued to drive over the saddle and across the Maricopa/Gila county border, reaching an elevation of about 6000′ feet.

Continuing a about a mile or so down Forest Road 143, I came across this communications tower, just 20 or so feet off the road:

A quick hike up a trail nearby shows a better view:

The sign at the site indicated it was owned by American Tower Corporation, however it stated that an FCC registration number was not required. A site number and telephone contact numbers were provided:

From a layman’s point of view this site appeared to be not in use, especially considering its location along a publicly accessible road. The building looked like it was not being maintained, I think no antennas were actually on the towers, and there was junk scattered around the site. The attached building which looked like a diesel generator also appeared to be somewhat in disrepair. I’m currently doing a but more research to see if any more information about this location is available.

Here is a map showing the entire length of Forest Road 143/Four Peaks Rd, going up and over the peaks to connect AZ Hwy 87 to AZ Hwy 188 and Roosevelt Lake:

The radios in my truck:

And of course some truck pics too!

After this, we headed down the eastern face of the four peaks and out of range of the PHX 500 repeater. The day ended with a swim in Apache Lake as we drove back down to the desert along the Apache trail and into the 100 degree temps! Another successful trip in to the Arizona wilderness, and like always, I definitely never leave without a radio.

K7MFC mobile shack: 2013 F-150 Lariat 4×4

I’ve been piecing together my mobile shack since purchasing my current truck about a year ago. I have everything finally done (j/k – I know it’s never “done”), so here’s a quick post to share my temporarily complete install. This post is especially for the Ford guys out there wondering about installing roof antenna mounts on their truck equipped with a sun roof. Antenna placement will be somewhat limited with a sunroof, but it does not present any real complications during the install process nor does it prevent installing multiple antennas on the roof. Hopefully this post can answer some of the questions I had regarding radio installs in an F-150.

First – the truck: 2013 Ford F-150 Lariat 4×4, 3.5 EcoBoost. I purchased this truck about a year ago, and it’s running strong with over 100k miles on the clock. This truck is my daily driver to the office job, but it does truck stuff too!

Next – the radios, from top to bottom:

Uniden BCD996P2 – I’m usually listening to Arizona DPS, local PDs, Phoenix & Mesa fire dispatch, and lots of other agencies/systems. Local news comms have been of interest lately too – they don’t keep hush hush on the radio about incidents.

Kenwood TK-8180 (UHF – GMRS) – I’m mainly active on GMRS while in my truck, and I’m usually on the Arizona GMRS Repeater Club’s 550 repeater. Daily traffic and weather nets for your commute – check us out!

Kenwood TM-281A (2m) – This radio is primarily for off-roading and back country comms. The 2m band is popular with Jeep/4×4 folks, and there is lots of activity out in the Arizona mountains or desert. Plenty of 2m repeaters on high peaks throughout the state with lots of people listening makes this an important communication tool when I’m camping well beyond cell phone service. Around town I’ll usually monitor 146.52 and chat occasionally.

My F-150 is the Lariat trim, and Ford likes to use the center console shifters in these and higher trims. This significantly limits options when considering a radio install, and my only realistic option was to use the center console under the arm rest. This is far from ideal – it places the radios far out of the driver’s normal field of vision, and operating any controls requires taking your eyes way off the road. Ideally, I pull off the road and park to use any radio controls that aren’t just a single button press.

However, this installation configuration does offer one benefit that is important to my install – it keeps the radios out of sight. The theme of my F-150 install is to be a bit “stealth” or low key, and not stick out like a sore thumb or otherwise attract attention to myself as a result of the radios. When the center console arm rest is closed, no radios are visible from outside or inside the truck, and there is nothing to entice any potential thieves.

Let’s start from the beginning! To power the radios, I ran 10ga wire (with a 30A inline fuse) from the battery and chassis ground through the firewall and up through the center console. This gen F-150 has a rubber grommet on the driver’s side firewall with a nipple that can be cut off and wire fed through, making running the power from the battery and coax from the front fender mount antenna very easy. This pic I found on F150forum.com shows it better than the photo I took:

Power is run to a Blue Sea Systems fuse block and each radio has its own fused circuit:

To secure the radios, I made a mounting rack from some 3/4″ plywood and some 1″ pine:

I attached the legs to each radio, then the legs are attached to the base with some bolts and wingnuts. I slide the base into the center console like this:

And then I’m able to drop the radios onto the base, then slide in the bolts and tighten the wingnuts. The radios are secure and the base fits snugly in the center console storage area. Here is the completed install showing the full length center console:

Operating the radios obviously requires keeping the arm rest up, which is another pretty major drawback:

This is something I may address in the future. I would ideally like to have a custom console cover made which would be removable so it can be out of the way completely when I have the radios on.

Next up – the antennas. No install thread would be complete without some antenna pics, so here’s what my roof looks like now:

On the driver’s side is a Laird QWB450-796 1/4 wave UHF antenna for the TK-8180 (GMRS) and on the passenger side is a Laird QWB144 1/4 wave VHF antenna for the TM-281A. The scanner antenna is a Larsen 150/450/800 on the front driver’s side fender. All antennas were purchased from The Antenna Farm:

For the roof antennas, I used two Tram 1251 NMO mounts from The Antenna Farm:

To drill the roof antenna mount holes, I used a Laird X-ACT 3/4″ hole saw I purchased form ProComm in Phoenix, AZ:

As I mentioned above, the sun roof on the truck significantly limits antenna placement. With the sun roof fully open, I was able to place both antennas 12″ from the rear of the roof to clear everything. Not ideal, but there is just about enough ground plane and it should work OK. Holes marked and masked – measure twice, cut once!

I put down a towel as a protective layer above the headliner when it was dropped down in order to catch all the mess from drilling and sanding. I used gorilla tape to keep the coax from flopping around off road, and ran both cables behind the rear passenger side airbag, down the rear pillar and under the door trim up to the center console.

The fender antenna mount is a Larsen NMO L bracket fender mount for Fords, which I also purchased from The Antenna Farm. I sanded, primed, and painted it black to match the truck:

All antennas are black to keep with the low key look. They are nearly invisible at a distance, blending into the background or the black color of the truck itself. Here’s a few more shots of the truck and antennas:

Misc progress shots:

I have a few backup radios in the truck as well. I keep a Midland 75-822 CB radio hidden in the center console. CB is still pretty popular with 4×4 folks and it comes in handy from time to time on the dirt roads. I have it paired with a Wilson Lil Wil mag mount antenna I keep stashed under the rear seat. It’s actually a pretty decent CB setup and I can get out a few miles reliably, which is about as good as one can expect from a cheap CB.

And I also keep a cheapo Baofeng UV-5R in the glove box just in case.  Another important piece of radio tech I consider part of my mobile shack is the factory Ford SYNC/SiriusXM receiver. Satellite radio operates in the 2.3 GHz section of the S band, and in addition to the music, sports, and news channels offered, up to date traffic and weather incident data is also available. SiriusXM also provides weather and navigation data for aircraft and marine subscribers as well.

Here is the first iteration of the install shortly after buying the truck, just a single Motorola CDM1250 for GMRS: