Introduction: Best USB WiFi Adapter and Setup for Raspberry Pi

Get the most bandwidth from your wifi adapter. I wrote this instructable because I bought an RT5370 USB WiFi Adapter that was advertised as conforming to 802.11n, but struggled to run at 1Mbps.

Image: iperf3 results with a microwave running (red) and two LTE mobile phones making a call (blue).

Introduction

Using iperf3, an RT5370 and a Raspberry Pi 2 Model B, I measured a peak bandwidth of 1.69Mbps. However, the usual maximum bandwidth was 768Kbps, and bandwidth often dipped into sub-kilobit speeds. This was very frustrating.

I gathered about 100 web ideas on how to improve WiFi bandwidth. I combined duplicate ideas and was left with about 30 unique improvements, and then over a four week span ran multiple measurements on each.

Almost all of the ideas have no statistically significant effect on WiFi bandwidth. The ones that matter are (in order of most important):

  • Good Raspberry Pi power adapter
  • Have AP on clear channel
  • Proper settings on Wireless Access Point
  • Don't run the microwave
  • Good USB WiFi Adapter
  • all others are in wpa_supplicant.conf or /etc/network/interfaces

The goals of this instructable are:

  • measure, measure, measure
  • select best adapter based on measurements
  • provide best performing setup for selected adapter

I expect this to be a "living" instructable in that more adapters will be added and measured.

Step 1: Gather Parts

For this instructable, I am using:

  • Raspberry Pi 2 Model B running Raspbian
  • Smart Phone with WiFi Analyzer App
  • U-verse 2-Wire Gateway
  • Linksys WAP300N Wireless Access Point

Notes:

  • Text enclosed in spades, such as, ♣replace-this♣, should be replaced with an actual value. Of course, remove the spades.
  • Measurements are included throughout and in an Appendix.

Step 2: Setup Wireless Access Point

Image: a screen shot of the app WiFi Analyzer running on a smart phone.

WiFi Analyzer

Ensure your wireless access point (AP) has minimal interference from your neighbors.

  • Load Wi-Fi analyzer app on a smart phone.
  • Ensure your Wi-Fi channel is not the same as your neighbor’s.
  • By default, most ISPs set up their users on channel 1.
  • If possible put your AP on a channel different from your neighbors'.
  • Use an odd numbered channel.

Setup Wireless Access Point

Ensure your AP is setup correctly. My ISP provider's gateway has a built-in 802.11b/g AP and I pay for an 18Mbps connection. I disabled the gateway's AP, and added an 802.11n AP to my network. The 802.11n AP has the following setup:

  • 2.4 GHz (5GHz disabled)
  • Network Mode = Mixed
  • Network Name (SSID) = :
  • Channel width = Auto (20MHz or 40MHz)
  • Channel = 1
  • SSID Broadcast = enabled
  • Security Mode = WPA2 (don't use WEP - it is less secure)

2.4GHz works best with Raspberry Pi.

Step 3: It's All About the Power

Image:power adapter and Raspberry Pi pins

Power Adapter

A high quality power adapter is fundamental to a properly functioning RPi.

I have 5 power adapters, which were included in Raspberry Pi starter kits. 2 of the 5 adapters provide consistent 5V. The others do not.

Any device added to the Raspberry Pi uses power. So, a USB device, or an HDMI monitor can push the Raspberry Pi into sub-optimal performance.

According to http://nordicgroup.us/rpi/power/:

“Raspberry Pi starts operating erratically below 4.75V”

[You must have a power supply that outputs] “2.4A at 5.2V (12 watts). The extra 0.2V mitigates the effect of the voltage drops in the cable and on the Raspberry Pi board.”

According to http://elinux.org/RPi_Hardware, to measure voltage:

  • Using a multimeter set to 20 volts DC (or 20v =)
  • Measure voltage from Pin# 02 DC Power 5V to Pin# 06 Ground
  • Voltage should be between 4.75 and 5.25 volts.

Recommended power adapter and cable:

  • 5.2V 2.1A USB Power Adapter from Amazon $5.99
  • Micro USB to USB cable 3ft from Amazon $4.69

Measurements:

  • Transfer Bandwidth for adapter providing correct voltage
    • 12.2 Mbps
  • Transfer Bandwidth for adapter providing 4.75V or less:
    • 7.66 Mbps

Step 4: Choose Adapter

Image: iperf3 for 1000 intervals on each of the adapters. The x-axis is Mbps and the y-axis is the count of the measurements in that bandwidth.

Choose Adapter

A device can be advertised as 802.11n, but not be able to achieve 11n bandwidth rates on the Raspberry Pi. Listing the transmit rate of the device is misleading. Instead measure actual bandwidth.

There are multiple aspects of a Wi-Fi chipset that negatively impact bandwidth.

Realtek pioneered soft modems; driving the cost of Ethernet down, while offloading processing from the Ethernet chipset to the host processor. On a PC or MacBook, where the CPU often sits idle, this is a great feature and saves money. However, on a Raspberry Pi, offloading processing to the ARM negatively impacts WiFi bandwidth and application performance.

Most of my applications don't require high WiFi bandwidth. Some applications that do require high WiFi bandwidth are Media Server, NAS, and Raspberry Pi-based PC.

Some general rules:

  • The adapter must be natively supported in current version of Raspbian.
  • Check if anyone has gotten the adapter to work, or if it is known to have issues.
  • The adapter must be supported by Raspberry Pi model being used (Raspberry Pi 2 Model B)
  • Measure performance

I will measure more adapters as I acquire them. In order of best performance (best bandwidth is on top):

  • Panda 300Mbps Wireless N USB Adapter
  • Edimax EW-7811Un 150Mbps 11n Wi-Fi USB Adapter
  • Wi-Pi Raspberry Pi 802.11n Wireless Adapter
  • TP-LINK TL-WN725N Wireless N Nano USB Adapter 150Mbps
  • RT5370

The Panda device is the size of a thumb drive and probably does not offload as much processing to the CPU as the smaller dongles do.

Step 5: Minimum Setup

Image: results of running iperf3 for 100 intervals with minimum setup (blue), and then again with the recommended setup (red). The x-axis is Mbps and the y-axis is the count of the measurements in that bandwidth.

The difference between a minimum setup and my recommended setup is not significant. I choose to have a setup, which is a bit more complex than the minimum, but the measurements don't support this choice (see image).

As long as you don't have power issues, your gateway supports dhcp, your adapter has driver support in raspbian, then this is the minimum setup to get wifi to work:

/etc/network/interfaces

If you have a wpa_supplicant.conf file rename it.

Run the command:

$ sudo nano /etc/network/interfaces

and edit to contain only :

auto wlan0
allow-hotplug wlan0
iface wlan0 inet dhcp
wpa-ssid "♣your-ssid♣"
wpa-psk "♣your-pass-phrase<♣"

CTRL-o to write file

ENTER to confirm write

CTRL-x to exit nano editor

Step 6: /etc/network/interfaces

Image: results of running iperf3 for 100 intervals with "iface eth0 inet dhcp" (blue), and then again with "# iface eth0 inet dhcp" (red). The x-axis is Mbps and the y-axis is the count of the measurements in that bandwidth.


/etc/network/interfaces

Each parameter in the /etc/network/interfaces file was measured.

This file must be correct or wifi won't work.

login into raspberry pi and run the command:

$ sudo nano /etc/network/interfaces

Edit the file to be:

# interfaces(5) file used by ifup(8) and ifdown(8)
# Please note that this file is written to be used with dhcpd
# For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'

# Include files from /etc/network/interfaces.d:
# source-directory /etc/network/interfaces.d

# Commented parameters were used in measurements
#   All comments can be removed
# Replace spades (♣) and text enclosed in ♣replace-this♣ with actual value
# loopback interface
#   loopback is used for tools to talk to themselves on the RPi
auto lo
iface lo inet loopback 

# ethernet interface
#   leave ethernet interface - may be needed for cable connection in the future
iface eth0 inet dhcp

# Wireless adapter
#   Use only one group of settings at a time - either RT5370 or WiPi
#   RT5370 settings:
auto wlan0
allow-hotplug wlan0
iface wlan0 inet dhcp
	# Use wpa-ssid and wpa-psk OR wpa_supplicant, but not both
	#   wpa-ssid "♣your-ssid♣"
	#   wpa-psk "♣your-pass-phrase♣"
	# Use wpa-conf instead of wpa-roam
	#   Using wpa-roam without correct wpa_roam.conf causes issues
	#   For example, on reboot wpa-roam can default to IPv6 and wifi stops 
	wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
	#
	# Turning power management off reduces dropped packets
	wireless-power off

#   WiPi settings:
# auto wlan0
# iface wlan0 inet dhcp
# wpa-ssid "♣your-ssid♣"
# wpa-psk "♣your-pass-phrase♣"
# default interface
# iface default inet dhcp

CTRL-o to write file

ENTER to confirm write

CTRL-x to exit nano editor

Step 7: /etc/wpa_supplicant/wpa_supplicant.conf

Image: results of running iperf3 for 100 intervals with a pre-generated key and instead using a pass phrase. The x-axis is Mbps and the y-axis is the count of the measurements in that bandwidth.

Pre-generated Key

Create a pre-generated PSK key. Login to Raspberry Pi and run the command:

$ wpa_passphrase ♣your-ssid♣ ♣your-pass-phrase♣

output:


network={
	ssid="♣your-ssid♣"
	psk=♣your-pre-generated-key♣
}


/etc/wpa_supplicant/wpa_supplicant.conf

Each parameter in the /etc/network/interfaces file was measured.

The wpa_supplicant.conf file must be correct or wifi won't work.

Login into raspberry pi and run the command:

$ sudo nano /etc/wpa_supplicant/wpa_supplicant.conf

Edit the file to look like this:

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
	ssid="♣your-ssid♣"
	# use a pre-generated key
	psk=♣your-pre-generated-key♣
	# if creating a standard image for many projects, then use pass phrase 
	# instead of generated key
	# a generated key depends on the Raspberry Pi's MAC
	# psk="♣your-pass-phrase♣"
	# specify for clarity
	key_mgmt=wpa_psk
	proto=rsn
	# CCMP is the correct encryption to use for WPA-PSK
	# The Wi-Fi Alliance requires 802.11n transmissions use WPA2 and CCMP
	pairwise=CCMP
	group=CCMP
}

CTRL-o to write file

ENTER to confirm write

CTRL-x to exit nano editor

Step 8: Testwifi.sh

Image: shows drop in transfer rate when a microwave oven runs.

testwifi.sh

On my first Raspberry Pi project, the pi would intermittently lose connectivity and not recover. At the time, I was unaware of the importance of the power adapter. I wrote this script to restore wifi, if anything goes wrong.

Login to the Raspberry Pi and run the following command:

$ sudo nano /usr/local/bin/testwifi.sh

Edit the file to look like this:

!/bin/bash

# Router IP address
TESTIP=♣u-verse-gateway-ip-address♣
counter=0
while true; do
	# ping the router
	ping -c1 ${TESTIP} > /dev/null
	if [ $? != 0 ]
	then
		# try a couple of times before restarting, pings can get lost
		if [ "$counter -lt 3 ]
		then
			counter=$((counter+1))
			logger "testwifi.sh: WiFi seems down, sleeping"
			sleep 2
		else
			logger "testwifi.sh: WiFi seems down, restarting"
			sudo /sbin/ifdown --force wlan0
			sleep 10
			sudo /sbin/ifup wlan0
			exit 0
		fi
	else
		logger "testwifi.sh: WiFi seems fine" 
		exit 0
	fi
done
exit 0

CTRL-o to write file

ENTER to confirm write

CTRL-x to exit nano editor

Make the file executable:

$ sudo chmod ug+x /usr/local/bin/testwifi.sh

or

$ sudo chmod 0755 /usr/local/bin/testwifi.sh

Create a crontab entry to periodically run the script:

$ sudo crontab –e<br>

and make it look like:

# run every 2 minutes:
*/2 * * * * /usr/local/bin/testwifi.sh >> /var/log/syslog

CTRL- to write file

ENTER to confirm write

CTRL-x to exit nano editor

Your Done !

Step 9: Appendix Measurements

Image: shows with and without wpa_supplicant.conf

Measurements

The basic measurement approach is:

  • repeat and refine until the measurements are accurate and easily reported
    • reflash the micro SD card to NOOBS
    • apply setup changes to get Raspberry Pi to a known good state
    • run iperf3 as a server on a laptop
    • repeat the following steps for each measurement:
      • reboot the (Raspberry Pi) RPi
      • with no change run iperf3 as a client on the RPi
      • make one change and reboot the RPi
      • run iperf3 as a client on the RPi
      • remove the change
      • copy and paste the iperf3 results into Excel
      • graph the results w/ and w/o the change in Excel

During the measurements, I reflashed the microSD card five times.

Most measurements have 100 intervals. Some measurements have 1000. A larger number of intervals is required when more accurate data is required. For example, when comparing Adapters.

Analysis includes calculating average, min, max and standard deviation, plus significance using a 2 sigma test. All iperf3 results are converted to Mbps (M bits / second)

Measurement results are rounded to fit in 1Mbps bins and counted. Rounding removes some accuracy, but makes graphing the results easier to interpret.

Both results (with and without change) are graphed: y-axis = count and x-axis = Mbps.

Step 10: Appendix Iperf3

Image: shows bandwidth between two MacBook Pros running iperf3 through a wireless access point.

iperf3

iperf3 is a command line speed test tool for measuring bandwidth.

Measure bandwidth between two laptops (PCs or MacBooks). This measurement establishes a baseline for highest achievable bandwidth on your network. Using an iperf3 server external to your network can introduce differences in measurements, which are outside of your control.

All other measurements are made between a laptop and a Raspberry Pi. This approach isolates changes on the Raspberry Pi showing impact on bandwidth.

Expect bandwidth between a Raspberry Pi and a PC to be less than between two PCs.

Install iperf3:

Open a terminal window.

Download and install iperf3 on two laptop/desktop. (I use a MacBook Pro, but it works on PCs as well)

http://macappstore.org/iperf3/

Find the MacBook's IP address, which will act as iperf3 server

$ ifconfig | grep "inet 192.168" 
inet 192.168.1.76

    ssh and login into the Raspberry Pi

    $ ssh pi@♣raspberry-pi-ip-address♣

    Install iperf3 on Raspberry Pi

    $ sudo apt-get install iperf3

    Using perf3 for measurements:

    To make a measurement run iperf3 from Raspberry Pi to MacBook

    Open a terminal window and start an iperf3 server running:

    $ iperf3 -s

    Open a second terminal window, login into the Raspberry Pi and run:

    $ iperf3 -c 192.168.1.76 -R -b 0 -i1 -t 100

    Options explained ($ man iperf3):

    -R runs perf in reverse mode

    -b n=0 sets the bandwidth to unlimited, otherwise n=bandwidth - not required

    -i1 pause n seconds between bandwidth reports - not required

    -t 100 sets the number of intervals to 100

    Step 11: Appendix CCMP

    Image: with and without CCMP

    CCMP is the standard encryption protocol used with WPA2 standard, which is more secure than the WEP protocol and TKIP protocol of WPA. There isn’t really a choice here. Use CCMP.

    $ sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
    network={
    	ssid=♣your-ssid♣
    	psk=♣your-pre-generated-key♣
    	# only have one of measurement 1, 2 or 3
    	# measurement 1
    	# pairwise=CCMP
    	# group=CCMP
    	# measurement 2
    	# pairwise=CCMP 
    	# group=CCMP
    	# measurement 3
    	pairwise=CCMP TKIP
    	group=CCMP TKIP
    }

    Step 12: Appendix Key_mgmt and Proto

    Image: with and and without key_mgmt and proto

    Measure with and without key_mgmt and proto.

    $ sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
    
    network={
    	wpa-ssid="♣your-ssid♣"
    	wpa-psk="♣your-generated-psk♣"
    	# Only include measurement 1 or 2, but no both
    	# Measurement 1
    	# key_mgmt=WPA-PSK
    	# proto=RSN
    	# Measurement 2
    	key_mgmt=WPA-PSK
    	proto=RSN
    
    	pairwise=CCMP
    	group=CCMP
    }

    Step 13: Appendix Loopback Interface

    Image: with and without loopback interface

    Measure with and without loopback interface.

    Loopback is used by various applications on the Raspberry Pi to talk to itself. So, I won’t make this change.

    	$ sudo nano /etc/network/interfaces
    	# Measurement 1
    	auto lo
    	iface lo inet loopback
    	# Measurement 2
    	# auto lo
    	# iface lo inet loopback
    

    Step 14: Appendix Default Interface

    Image: with and without default interface

    Measure with and without default interface.

    $ sudo nano /etc/network/interfaces
    # Measurement 1
    iface default inet dhcp
    # Measurement 2
    # iface default inet dhcp

    Step 15: Appendix With and Without GUI

    Image: with and without GUI

    Measure with and without GUI. Removing the GUI frees about 2GB on the micro SD card.

    To remove the GUI:

    $ sudo apt-get --purge remove 'x11-*'
    $ sudo apt-get --purge auto remove
    $ sudo reboot
    $ sudo raspi-config

    Advanced Options

    memory_split:

    Raspberry Pi’s RAM is limited. RAM is shared between a central processing unit (CPU) and a graphics processing unit (GPU). Raspbian Wheezy gives 64MB of RAM to the GPU. Removing the GUI frees this RAM up for applications running on the CPU. Running raspi-config afterwards should show 0MB allocated to the GPU.

    Once set in raspi-config, this command will show memory allocated to GPU:

    $ cat /boot/config.txt
    gpu_mem=0