OpenWRT on Pi – Light OS with Network Features

OpenWRT is an open source firmware that can be loaded on many commercially available routers. The firmware offers an upgrade path for older or obsolete hardware and customization/advanced features for newer equipment.

With OpenWRT’s small footprint (176MB vs. 1.7GB Raspbian image), it’s ideal for older Raspberry hardware where speed and memory usage is an issue.

For small home and office projects OpenWRT will offer some interesting networking solutions, such as making the Pi into an access point or using it as a wireless LAN bridge. However it’s important to note that the Raspberry Pi WiFi hardware will not offer the same performance as you’ll find on dedicated routers.

In this blog I documented my notes on getting an old Raspberry Pi Model B up and running with OpenWRT. I also tried to explain how to install many of the common Pi functions (loading software, GPIO, I2C…)

Pro’s and Con’s

Before jumping into a Pi OpenWRT project it’s useful to know where it stands versus the default Raspberry Pi OS.

Some of the OpenWRT advantages (over Raspbian/Raspberry PI OS) include:

  • It’s fast. It was designed to run on lower end CPU’s with limited memory
  • Network focused
  • Fast bootup
  • Smaller OS footprint so even older 4 GB SD card be used (2GB is possible but may not be able to load many software packages).

Some OpenWRT limitations:

  • No X-window desktop.
  • System setup isn’t streamlined like the default Raspberry PI OS (there’s no raspi-config)
  • Default installation is quite bare, so you need to manually load packages (even Bash and Nano)
  • Some packages could be a challenge to install (for example Node-Red)

Getting Started

Despite the fact that OpenWRT is designed to run on routers, in many ways its easier to play with on a Raspberry Pi. Some of the benefits of using a PI are:

  • you can’t ‘brick’ the Raspi. (I’ve come close many times playing with home routers)
  • SD/microSD card have considerably more space than most home routers. (This was in issue for me with older routers).
  • Pi has an HDMI connection so you can work directly on the PI (good for getting started)

For the OpenWRT Raspberry Pi Images see: https://openwrt.org/toh/raspberry_pi_foundation/raspberry_pi

You can use the standard Raspi imager to install OpenWRT on an SD card. For Linux systems the imager can be installed by:

sudo apt update && sudo apt install rpi-imager

After an SD card has been loaded up there are several way to get an OpenWRT system up and running. Below are the steps that I used.

1. Connect a monitor and keyboard to the Pi

Let it boot up and then go to the command prompt, and setup an static LAN address:

# Enter your own static IP. Note: change the gateway/DNS for your setup
uci set network.lan.proto="static"
uci set network.lan.ipaddr="192.168.0.140"
uci set network.lan.netmask="255.255.255.0"
uci set network.lan.gateway="192.168.0.1"
uci set network.lan.dns="192.168.0.1"
uci commit network

If you able to see IP addresses on your LAN you can simple do:

# Set Pi for DHCP and then check its address
uci set network.lan.proto="dhcp"
uci commit network

2. Hardwire Pi to Your LAN

Connect the 100BaseT port of the Pi to your LAN and then reboot the module.

From a laptop you now can use OpenWRT’s Web Interface or you can use the secure shell (ssh) command line interface.

I like the ssh option to get started because I can paste in groups of commands. To get started with ssh (with my static IP) :

$ ssh root@192.168.0.140


BusyBox v1.35.0 (2023-01-03 00:24:21 UTC) built-in shell (ash)

  _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M
 -----------------------------------------------------
 OpenWrt 22.03.3, r20028-43d71ad93e
 -----------------------------------------------------
=== WARNING! =====================================
There is no root password defined on this device!
Use the "passwd" command to set up a new password
in order to prevent unauthorized SSH logins.
--------------------------------------------------
root@OpenWrt:~# 

3. Install Your Required Software

The default OpenWRT installation is extremely bare, so will probably need a number of basic packages.

OpenWRT uses opkg to install software. (Note: apt and apt-get are not supported in OpenWRT).

As a bare minimum I like to load:

# Install some software, but update list first
opkg update
# Install Bash, nano editor
opkg install bash nano 
# For Python projects install the base Python3 and pip
opkg install python3 python3-pip
# For Pi GPIO projects 
opkg install  gpioctl-sysfs gpiod-tools 

If you are planned to do some projects on your Raspberry Pi adding Bash, Python, and GPIO hardware support will be useful.

LuCI – OpenWRT Web Interface

After the system was up and running, the LuCI web interface can be used to setup other features such as networking interfaces and custom software. Many of the software packages also include additions to a LuCI web add-on.

From the LuCI interface you are easily see how much memory and disk space is available. It is important to check this screen if you’re planning on loading a large number of software packages.

Setup a USB WiFi Adapter

For Raspberry Pi models 3 and 4 OpenWRT will identify their built-in WiFi hardware, however for earlier models or projects where you want to use a USB WiFi adapter you’ll need to do this step.

On OpenWRT the configuring of USB devices has to be added manually. The first step is to install the USB utilities package:

# Update the package list
opkg update
# Add USB Utils (has lsusb)
opkg install usbutils

Once usbutils in added, the lsusb command will show information about the connected USB devices (Note: drivers still need to be loaded). For my Raspberry Pi B setup with an old Realtek WiFi adapter my output was:

root@OpenWrt_Pi1:~# lsusb
Bus 001 Device 004: ID 0bda:8189 Manufacturer_Realtek RTL8187B_WLAN_Adapter
Bus 001 Device 003: ID 0424:ec00  
Bus 001 Device 002: ID 0424:9512  
Bus 001 Device 001: ID 1d6b:0002 Linux 5.10.176 dwc_otg_hcd DWC OTG Controller

From this listing I can see that I need to search for a RTL8187B_WLAN_Adapter. The Luci Web Interface can be used to find and install the required network driver.

Once the USB WiFi adaptor is enabled, there are several different wireless arrangements that can be used, some of the more common setups would be:

  • Wireless application node, (like a typically Raspberry Pi setup)
  • Access point node, to setup your own custom network
  • Wireless bridge, to extend an existing wireless network

For a simple wireless application node, go into the LuCI web interface Network->Wireless menu option, and then select your radio and scan for a wireless network. After a SSID (a wireless connection) is configured, select Edit to add the network information.

Ensure that you select both lan and wwan, by doing this you will be able to remotely access the Pi node via both wireless and wired connections.

Using SFTP and FileZilla

Remotely working a OpenWRT can be a little challenging if you are only using the SSH and Luci web interface. A Secure File Transfer Protocol (SFTP) server package can be used to greatly improve editing and saving of configuration and coding files.

The OpenSSH-FTP server package is installed by:

# For remote work add an SFTP server
opkg update
opkg install openssh-sftp-server

After this software has been loaded a graphical SFTP client package like FileZilla can be used on a laptop.

FileZilla allows for an easy visual interface for remote coding and maintenance. Below is an example of FileZilla connecting into an OpenWRT Raspberry Pi node. A file association on FileZilla has been setup to link py files to the basic Python Idle editor.

A Raspi 3 Example

I wanted to do a more complete Pi functions test. For this project I used Pi 3 because I wanted to test controlling the USB power. (Note: USB power control is only available on Pi 3 and 4).

My goal was to play with GPIO, I2C and USB power. In the final project I used OpenWRT’s built-in uhttpd web server to show the results.

Below are some of the individual steps that I did to get things running.

GPIO Setup

The base GPIO packages need to loaded:

 # update list of available packages
opkg update
opkg install  gpioctl-sysfs gpiod-tools 

After the basic GPIO software is installed Raspberry Pi pin can be read to and written to in Bash (or ash which is the default OpenWRT shell).

Before a GPIO pin can be used it needs to defined. The tee command can be used to create a gpio definition with all the required files, for example:

# Create a gpio4 definition
echo 4 | tee /sys/class/gpio/export

# Show the file structure
ls /sys/class/gpio/gpio4
active_low  direction   power       uevent
device      edge        subsystem   value

A example to create a GPIO definition, then to write to the pin and read the value back is:

# Define the pin as an output
echo "out" > /sys/class/gpio/gpio4/direction
# Set the pin on (1)
echo 1 > /sys/class/gpio/gpio4/value
 # Read the pin value
cat /sys/class/gpio/gpio4/value
1

If you are doing some playing around and you want to remove a gpio definition then write to the unexport file:

# Remove GPIO4
echo 4 | tee /sys/class/gpio/unexport

I2C Setup

To get the I2C setup working the Raspberry Pi I2C chipset driver and the I2C tools need to be loaded:

# Update the opk list. This needs to be done once after a power up
opkg update
opkg install kmod-i2c-bcm2835 i2c-tools

The next step is to edit the file: /boot/config.txt

nano /boot/config.txt

At the bottom on the file add three dtparam lines:

################################################################################
# Bootloader configuration - config.txt
################################################################################

################################################################################
# For overclocking and various other settings, see:
# https://www.raspberrypi.org/documentation/configuration/config-txt/README.md
################################################################################

# OpenWrt config
include distroconfig.txt

[all]
# Place your custom settings here.
dtparam=i2c1=on
dtparam=spi=on
dtparam=i2s=on

Once the file is edited the system needs to be rebooted. After this I2C devices can be connected up. To check that the I2C addresses for wired devices use the i2cdetect command:

i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- 28 -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- 77     

(Note: for this i2cdetect example, addresses 28 and 48 were on from the Pimoroni Explorer HAT, and address 77 was a BME280 sensor).

Typically the next step is to install Python with pip and then any required I2C device library. For this project I was using a BME280 temperature/humidity sensor.

BME280 Sensor Setup

Each sensor will have its own particular library, however you’ll probably need the python3-smbus support.

For my sensor I needed to:

opkg update
opkg install python3 python3-pip
opkg install python3-smbus
# Install Python BME280 temperature/humidity sensor library
pip install bme280

The Python bme280 library also has a Bash interface, so to get the data from I2C address 77:

# Get the BME280 sensor data from address 0x77 
read_bme280  --i2c-address 0x77

1005.19 hPa
  38.38 %
  19.25 C

Control USB Power

Controlling the USB power is not something that is done very often. Some use cases might be: USB fans and lights or resetting an Arduino controller that a Pi is powering/connected to.

For this feature you’ll need to run:

opkg install usbutils uhubctl

The lsusb command will show which smart USB devices are connected, it will not show simple hardware like USB fans and lights.

lsusb --tree
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=dwc_otg/1p, 480M
    |__ Port 1: Dev 2, If 0, Class=, Driver=hub/5p, 480M
        |__ Port 1: Dev 3, If 0, Class=, Driver=smsc95xx, 480M

For the Raspberry Pi 3 and 4 the power on all USB ports is ganged together through port 2, so unfortunately it is not possible to power up/down an individual USB port. As mentioned earlier, the chip set on the Pi 1 and 2 do not support USB power control.

The Pi 4 has two internal USB hubs. Hub 1-1 connects to all the USB port on the USB 2.10 standard. Hub 2 controls to all the ports on the USB 3.00 standard and the Ethernet jack.

The commands to turn on/off/toggle the USB ports and keep the Ethernet jack powered are:

uhubctl -l 1-1 -p 2 -a on
uhubctl -l 1-1 -p 2 -a off
uhubctl -l 1-1 -p 2 -a toggle

OpenWRT uhttpd Web Server

OpenWRT has the lightweight uhttp web server pre-installed. This server is used for the LuCI Web Interface but it can also be used for custom applications.

For custom web projects add your files to: /www/cgi-bin

This directory allows any CGI program (Bash, Python, Lua, etc.) to run. Remember to set execute permissions on your CGI script files:

chmod +x mycgifile

A Pi3 CGI Web Example

The hardware setup on this project used a Pimoroni Explorer HAT Pro. This Pi Top had four built-in coloured LEDs (on pins 4, 17,27 and 5). Before toggling a GPIO pin, the device needs to be defined and a direction needs to be set:

#!/bin/bash
#
# setgpio - setup GPIO 
#
for pin in 4 17 27 5
do
  gpiodev=/sys/class/gpio/
  gpiodev+=$pin

  echo $pin | tee /sys/class/gpio/export  
  echo "out" > /sys/class/gpio/gpio$pin/direction
done
ls /sys/class/gpio

For my Web Page, some buttons were used to pass a query string variable that is read at the top of the script before outputting the HTML. The BME280 sensor data is shown as a simple Bash variable.

#!/bin/bash
#
# toggle - Bash CGI to show some standard functions
#           -  toggle GPIO LEDs and USB power
#           - show some I2C sensor results
#      Note: GPIO pins need to be setup as outputs
set -e
# Toggle a pin if it's passed in the queue string
if  [[ "$QUERY_STRING" =~ "gpio" ]]; then
  pin=$QUERY_STRING
 
  # Read the GPIO pin value and then toggle it
  if [ "$(cat /sys/class/gpio/$pin/value)" == 1 ]; then
    echo 0 > /sys/class/gpio/$pin/value
  else
    echo 1 > /sys/class/gpio/$pin/value
  fi
fi

# Toggle USB power, ensure to add '&' for CGI use
if [[ "$QUERY_STRING" =~ "usb" ]]; then
  uhubctl -l 1-1 -p 2 -a toggle &> /dev/null
fi

# Get BME280 sensor data
data=$(read_bme280 --i2c-address 0x77)


echo "Content-type: text/html"
echo ""

echo "
<html>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<title>OpenWRT PI Toogle</title>
</head>
<body>
<h1>OpenWRT PI CGI </h1>
<h3>Toggle Hardware</h3>
<hr>
<button style='background-color:skyblue;'
   onclick='location.href=\"?gpio4\"'>Toggle GPIO4  LED1
</button><br>
<button style='background-color:yellow;'
   onclick='location.href=\"?gpio17\"'>Toggle GPIO17 LED2
</button><br>
<button style='background-color:red;'
   onclick='location.href=\"?gpio27\"'>Toggle GPIO27 LED3
</button><br>
<button style='background-color:green;'
   onclick='location.href=\"?gpio5\"'>Toggle GPIO5 LED4
</button><br><br>
<button style='background-color:white;'
   onclick='location.href=\"?usb\"'>Toggle USB Power
</button><br>
<hr><h3>BME280 Sensor Data</h3>
<b>$data</b>
</body>
</html>"

exit 0

The web pages is called by: http://pi_OpenWRT_ip/cgi-bin/toggle

Below is a picture of the web page and the Pi setup.

Summary

OpenWRT can breath a lot of life into old Raspberry Pi hardware. I’ve noticed a nice performance improvement on the old Pi hardware that makes the system quite usable.

Long term Raspberry Pi users may find OpenWRT’s lack of a pre-installed applications, drivers and no desktop a little frustrating at first.

It’s important to note that certain packages like Node-Red will take some work to get installed.

This blog only really looked at Raspberry Pi functionality under OpenWRT. I never documented some of the OS’s real strengths on the networking side.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s