For a recent project, I needed to add cellular connectivity to a Raspberry Pi (actually, an entire cluster... but that's a story for a future time!).
I figured I'd document the process in this blog post so people who follow in my footsteps don't need to spend quite as much time researching. This post is the culmination of 40+ hours of reading, testing, and head-scratching.
There doesn't seem to be any good central resource for "4G LTE and Linux" out there, just a thousand posts about the ABC's of getting an Internet connection working through a 4G modem—but with precious little explanation about why or how it works. (Or why someone should care about random terms like PPP, ECM, QMI, or MBIM, or why someone would choose qmi_wwan
over cdc_ether
, or ... I could go on).
Hopefully you can learn something from my notes. Or point out places where I'm glaringly wrong :)
Hardware
The hardware requirements are not too bad, and remarkably affordable. You'll need:
- A Raspberry Pi (almost any will do, though I used a Raspberry Pi 4 (with a USB adapter) and a Compute Module 4 (with a carrier board with a mini PCIe slot).
- A mini PCI Express 4G LTE modem. I used a Quectel EC25-A, but there are some from Sierra Wireless I've heard recommended too.
- (If not using a CM4 + LTE carrier board) A USB to mini PCIe adapter with built-in SIM tray. I used this one from Timack but any should do—just make sure it has a SIM try built-in! There are even Pi HATs like this one that place the modem hardware directly atop the Pi.
- A SIM card with a 4G data plan. I bought a SixFab SIM and used their monthly pay-as-you-go service for testing. You could pull out the SIM from your mobile phone (on most carriers at least) but that is a bit inconvenient as your phone won't get service until you put the SIM back in. You could also get a plan and SIM from any major carrier (e.g. AT&T, T-Mobile, Verizon in the USA)—though you have to make sure the carrier you use works with the LTE modem you have!
- An antenna—most modems have plugs for LTE main, LTE diversity, and GPS/GNSS. I typically use this Pulse Electronics U.FL antenna in a pinch, but there are many options for different needs (e.g. outdoor antennas, antennas with longer cables and SMA to U.FL adapters)—you have to figure out exactly what you need depending on your environment.
- (Depending on the SIM) If you want to use the SIM from your phone—which might be a nano SIM—you should also have on hand a cheap SIM Adapter set like the one I use.
To save on cost, I bought most of the things I used on eBay, where the price was 30-50% less than buying new on Amazon or SixFab's store. Since there are a lot of enterprise deployments using this type of gear, there's a lot of stock on the used market. Just know that some of it is pretty beat up—so buy only from reputable vendors!
Note: All the instructions in this post assume you're in the US. If you're in another country, some things need changing—for example, the Quectel modem comes in different varieties for different geographical regions, like the EC25-E for Europe, Africa, and parts of Asia.
Once you have everything together, insert the SIM in the SIM tray on your USB adapter or CM4 carrier board, install the LTE modem in the Mini PCIe slot. If you have a USB adapter, plug that USB adapter into one of the Pi's USB ports—which port doesn't really matter since all these devices operate over USB 2.0 (480 Mbps).
Data Plans
Before getting to the setup process, I thought I'd jot down a few notes about data plans, since at least in my part of the USA, it's kinda hard to find generous data packages with features like static IP addresses for a reasonable price.
Just as a point of estimation, it cost me about $30 for 10 GB of data (if pre-purchased), and I can find a few plans that offer 30-50 GB/month for $60-90/month.
I used to have an unlimited plan from AT&T, but they severely throttled data once you went past a certain cap (down to like 100 Kbps, which is excruciating), so I switched to a 30 GB/month shared plan a couple years ago.
I also investigated getting a static public IPv4 address, but that was prohibitively expensive with the carriers I checked on. Instead, you may be able to get a routable IPv6 address—some carriers support this, and some network configurations will work with it. But YMMV, and you should be prepared to deal with CG-NAT.
WARNING: If you set a Pi up as a webserver or some other type of server that's constantly using data, be careful—you could end up racking up huge overage charges if you're not careful.
Pi Setup
These modems are widely supported in Linux, and even in Raspberry Pi OS (which is based on Debian).
Since I used a SixFab SIM, I had to log into my SixFab account and set the SIM to be 'active' before it was able to connect to AT&T's network.
With the Raspberry Pi booted up, in a Terminal window, enter in lsusb
and you should see something like:
pi@lte:~ $ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 2c7c:0125 Quectel Wireless Solutions Co., Ltd. EC25 LTE modem
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
pi@lte:~ $ lsusb -t
...
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M
|__ Port 2: Dev 3, If 4, Class=Vendor Specific Class, Driver=qmi_wwan, 480M
If you don't see the modem listed in the output, you might not have plugged it in all the way, or your USB adapter or CM4 carrier board hasn't routed the USB signal properly (I've encountered a few broken implementations, so it's not out of the question).
If you check the kernel logs with dmesg
, you may also see some messages from qmi_wwan
, like:
pi@lte:~ $ dmesg | grep qmi
[ 5.701450] qmi_wwan 1-1.2:1.4: cdc-wdm0: USB WDM device
[ 5.703022] qmi_wwan 1-1.2:1.4 wwan0: register 'qmi_wwan' at usb-0000:01:00.0-1.2, WWAN/QMI device, 02:5c:84:4e:14:51
[ 5.703245] usbcore: registered new interface driver qmi_wwan
And a device is listed as cdc-wdm0
:
pi@lte:~ $ ls /dev/cdc*
/dev/cdc-wdm0
What may not be obvious—since these 4G modems are physically in a mini PCIe card form factor—is that they don't show up as PCI Express devices (even on a Compute Module 4 board). They show up as USB devices.
Anyways, the card should automatically show up on as a wwan
network interface, usually wwan0
:
pi@lte:~ $ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
...
3: wwan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
link/ether 02:5c:84:4e:14:51 brd ff:ff:ff:ff:ff:ff
inet 169.254.231.106/16 brd 169.254.255.255 scope global noprefixroute wwan0
valid_lft forever preferred_lft forever
inet6 fe80::8284:d6cd:67d2:ca3a/64 scope link
valid_lft forever preferred_lft forever
You can try using this interface already using ping
, but since it's not configured yet, it most likely won't work:
pi@lte:~ $ ping -I wwan0 www.google.com -c 5
PING www.google.com (142.251.32.4) from 169.254.231.106 wwan0: 56(84) bytes of data.
--- www.google.com ping statistics ---
5 packets transmitted, 0 received, 100% packet loss, time 4085ms
At this point, you'll need to make a decision—do you want to use the device
QMI Mode setup (as wwan0
)
There's a longer history about the relationship of QMI, MBIM, and PPP modes for these modems, which I don't know if I have time to get into here. But in general, you should use a modem like the Quectel I'm using in either QMI or ECM mode.
All the modems I've purchased seem to be in PPP/QMI mode by default (usbmode
returns 0
—more on that later). This seems to automatically make the device use the qmi_wwan
driver and expose a wwan0
interface.
SixFab has an excellent guide for getting started with this mode: Setting up a data connection over QMI interface using libqmi.
You need to install a few utilities to interact with the modem via QMI:
pi@lte:~ $ sudo apt update && sudo apt install libqmi-utils udhcpc
Then check the current operating mode for the modem:
pi@lte:~ $ sudo qmicli -d /dev/cdc-wdm0 --dms-get-operating-mode
[/dev/cdc-wdm0] Operating mode retrieved:
Mode: 'online'
HW restricted: 'no'
Note: If this returns a
Resource temporarily unavailable
error after a bit, you might need to first stop ModemManager (if it's installed and running) withsudo systemctl stop ModemManager
, then try again.
If it doesn't return online
, run sudo qmicli -d /dev/cdc-wdm0 --dms-set-operating-mode='online'
to set it online.
Then set the interface into raw_ip
mode:
pi@lte:~ $ sudo ip link set wwan0 down
pi@lte:~ $ echo 'Y' | sudo tee /sys/class/net/wwan0/qmi/raw_ip
Y
pi@lte:~ $ sudo ip link set wwan0 up
Confirm it's in the raw-ip
mode with the following command:
pi@lte:~ $ sudo qmicli -d /dev/cdc-wdm0 --wda-get-data-format
[/dev/cdc-wdm0] Successfully got data format
QoS flow header: no
Link layer protocol: 'raw-ip'
...
Now it's finally time to connect to the network your SIM card is affiliated with! You need to know the APN for the network—in my case I'm using super
for the SixFab card, but a common one for AT&T SIMs like the one I use in my iPhone is nxtgenphone
. Cradlepoint maintains a list of common APNs by carrier, but to know what it should be, the easiest thing is to ask your provider.
Run the following command to connect:
pi@lte:~ $ sudo qmicli -p -d /dev/cdc-wdm0 --device-open-net='net-raw-ip|net-no-qos-header' --wds-start-network="apn='YOUR_APN',ip-type=4" --client-no-release-cid
[/dev/cdc-wdm0] Network started
Packet data handle: '2267587312'
[/dev/cdc-wdm0] Client ID not released:
Service: 'wds'
CID: '19'
Note: If you have a username and password, you can add those in after the apn, e.g.
apn='YOUR_APN',username='YOUR_USERNAME',password='YOUR_PASSWORD',ip-type=4
.
Now, configure udhcpc
to assign a default IP address and route:
pi@lte:~ $ sudo udhcpc -q -f -i wwan0
udhcpc: started, v1.30.1
No resolv.conf for interface wwan0.udhcpc
udhcpc: sending discover
udhcpc: sending select for 10.228.89.96
udhcpc: lease of 10.228.89.96 obtained, lease time 7200
At this point, if you use ip a
, you should see the new settings for the modem:
pi@lte:~ $ ip a
...
3: wwan0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
link/none
inet 10.228.89.96/26 scope global wwan0
valid_lft forever preferred_lft forever
And, if everything worked correctly, you should see some successful pings:
pi@lte:~ $ ping -I wwan0 www.google.com -c 5
PING www.google.com (142.250.190.68) from 10.228.89.96 wwan0: 56(84) bytes of data.
64 bytes from ord37s34-in-f4.1e100.net (142.250.190.68): icmp_seq=1 ttl=116 time=50.2 ms
64 bytes from ord37s34-in-f4.1e100.net (142.250.190.68): icmp_seq=2 ttl=116 time=48.1 ms
64 bytes from ord37s34-in-f4.1e100.net (142.250.190.68): icmp_seq=3 ttl=116 time=46.3 ms
64 bytes from ord37s34-in-f4.1e100.net (142.250.190.68): icmp_seq=4 ttl=116 time=50.8 ms
64 bytes from ord37s34-in-f4.1e100.net (142.250.190.68): icmp_seq=5 ttl=116 time=74.4 ms
--- www.google.com ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4005ms
rtt min/avg/max/mdev = 46.260/53.975/74.403/10.342 ms
Yay! But once you restart the Pi, the network connection is lost.
After a reboot, you have to re-run the following commands to connect again:
pi@lte:~ $ sudo ip link set wwan0 down
pi@lte:~ $ echo 'Y' | sudo tee /sys/class/net/wwan0/qmi/raw_ip
pi@lte:~ $ sudo ip link set wwan0 up
pi@lte:~ $ sudo qmicli -p -d /dev/cdc-wdm0 --device-open-net='net-raw-ip|net-no-qos-header' --wds-start-network="apn='YOUR_APN',ip-type=4" --client-no-release-cid
pi@lte:~ $ sudo udhcpc -q -f -i wwan0
Even though sudo qmicli -d /dev/cdc-wdm0 --wda-get-data-format
shows it's in raw-ip
mode, it seems you still have to stop the interface, force raw_ip
, and start the interface, then you can connect and set up the IP and routing with udhcpc
.
Automatic re-connection
The simplest way to set up automatic re-connection is to add the following contents in a new file for the wwan0
interface:
# Create the file.
pi@lte:~ $ sudo nano /etc/network/interfaces.d/wwan0
# Paste in the following contents (replacing with your own APN).
iface wwan0 inet manual
pre-up ifconfig wwan0 down
pre-up echo Y > /sys/class/net/wwan0/qmi/raw_ip
pre-up for _ in $(seq 1 10); do /usr/bin/test -c /dev/cdc-wdm0 && break; /bin/sleep 1; done
pre-up for _ in $(seq 1 10); do /usr/bin/qmicli -d /dev/cdc-wdm0 --nas-get-signal-strength && break; /bin/sleep 1; done
pre-up sudo qmicli -p -d /dev/cdc-wdm0 --device-open-net='net-raw-ip|net-no-qos-header' --wds-start-network="apn='nxtgenphone',ip-type=4" --client-no-release-cid
pre-up udhcpc -i wwan0
post-down /usr/bin/qmi-network /dev/cdc-wdm0 stop
Note: Be sure to include username and password as stated earlier, if your SIM plan requires it.
Reboot (sudo reboot
) and once rebooted, run the following to manage the connection:
# Bring up the connection.
pi@lte:~ $ sudo ifup wwan0
# Bring down the connection.
pi@lte:~ $ sudo ifdown wwan0
And check if there's a route to the internet via wwan0
with route -n
(or try a ping through the interface).
If you want the interface to come up at system boot, add the line auto wwan0
above the iface
line in the /etc/network/interfaces.d/wwan0
file:
auto wwan0
iface wwan0 inet manual
Now after a reboot, the interface should come up automatically, instead of requiring a manual sudo ifup wwan0
.
Other helpful QMI modem commands
sudo qmicli -d /dev/cdc-wdm0 --nas-get-signal-info
sudo qmicli -d /dev/cdc-wdm0 --nas-get-signal-strength
sudo qmicli -d /dev/cdc-wdm0 --nas-get-home-network
sudo qmicli -d /dev/cdc-wdm0 --nas-get-serving-system
sudo qmi-network /dev/cdc-wdm0 status
sudo qmicli -d /dev/cdc-wdm0 --wds-get-packet-service-status
ECM mode setup (usb0
)
SixFab has a great guide for setting the modem into ECM mode, which exposes a usb0
network interface instead of a wwan0
interface.
Assuming you did all the QMI mode setup, first make sure the interface is down with sudo ifdown wwan0
. Also comment out all the lines in /etc/network/interfaces.d/wwan0
(or delete that file).
To switch to ECM mode, you need to use minicom
to communicate with the modem over it's serial port:
pi@lte:~ $ sudo apt install minicom -y
pi@lte:~ $ minicom -D /dev/ttyUSB2 -b 115200
This should open a serial connection. Type in AT
and press 'Enter', and you should see OK
. We're gonna talk old school AT commands to the modem, the first one being the command to check the current usbmode
:
AT+QCFG="usbnet"
That will likely return +QCFG: "usbnet",0
, but we need that to be set to 1
(ECM mode), so enter the following command:
AT+QCFG="usbnet",1
The modem may reboot itself automatically, but if not, enter the following command to force a reboot:
AT+CFUN=1,1
See, it's fun!
After 5 seconds or so, you'll see a warning pop up in minicom like Cannot open /dev/ttyUSB2!
. It will go away, and you'll start seeing some more information go by as the modem completes its boot process.
Once you can type AT
again and get OK
, it's time to make sure the APN is correct. Enter the following command (but make sure you put in the correct APN for your SIM...):
AT+CGDCONT=1,"IP","YOUR_APN"
And finally, restart the modem again:
AT+CFUN=1,1
Wait for the modem to reboot, then exit minicom: press Ctrl-A, then press Z, and minicom's help comes up. Press X to leave minicom and confirm you want to leave it by hitting Enter.
Now reboot the Raspberry Pi (sudo reboot
), then check if you got an IP address on the usb0
interface:
pi@lte:~ $ ifconfig usb0
usb0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.225.24 netmask 255.255.255.0 broadcast 192.168.225.255
inet6 fe80::1f80:5523:108c:a9eb prefixlen 64 scopeid 0x20<link>
ether a6:51:1c:3f:79:1c txqueuelen 1000 (Ethernet)
RX packets 24 bytes 2153 (2.1 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 33 bytes 4162 (4.0 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
And confirm the modem is using the cdc_ether
driver instead of qmi_wwan
:
pi@lte:~ $ lsusb
...
Bus 001 Device 003: ID 2c7c:0125 Quectel Wireless Solutions Co., Ltd. EC25 LTE modem
pi@lte:~ $ lsusb -t
...
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M
|__ Port 2: Dev 3, If 4, Class=Communications, Driver=cdc_ether, 480M
|__ Port 2: Dev 3, If 5, Class=CDC Data, Driver=cdc_ether, 480M
Test if you can reach the Internet through the usb0
interface:
pi@lte:~ $ ping -I usb0 www.google.com -c 5
PING www.google.com (142.250.190.68) from 192.168.225.24 usb0: 56(84) bytes of data.
64 bytes from ord37s34-in-f4.1e100.net (142.250.190.68): icmp_seq=1 ttl=115 time=33.9 ms
64 bytes from ord37s34-in-f4.1e100.net (142.250.190.68): icmp_seq=2 ttl=115 time=36.8 ms
64 bytes from ord37s34-in-f4.1e100.net (142.250.190.68): icmp_seq=3 ttl=115 time=41.8 ms
64 bytes from ord37s34-in-f4.1e100.net (142.250.190.68): icmp_seq=4 ttl=115 time=59.9 ms
64 bytes from ord37s34-in-f4.1e100.net (142.250.190.68): icmp_seq=5 ttl=115 time=39.1 ms
--- www.google.com ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4005ms
rtt min/avg/max/mdev = 33.934/42.293/59.880/9.168 ms
Hooray! The best thing about this setup is it seems to come up automatically after a reboot on its own—no need for any network interface or qmicli
shenanigans.
You can still disable the usb0
interface with:
pi@lte:~ $ sudo ip link set usb0 down
Other Useful AT commands
# Signal strength: https://m2msupport.net/m2msupport/atcsq-signal-quality/
AT+CSQ
+CSQ: 20,99
# Network information: https://m2msupport.net/m2msupport/network-information-automaticmanual-selection/
AT+COPS?
+COPS: 0,0,"AT&T Twilio",7
# Get clock: https://m2msupport.net/m2msupport/m2m-module-diagnostics/
AT+CCLK?
+CCLK: "22/01/20,19:28:12-24"
Built-in AP configuration
It seems another side effect of using the usb0
interface is the modem itself is where all the management happens, and at least on my Quectel modem, if you open up the gateway IP address in a router (e.g. https://192.168.225.1/
), bypassing certificate warnings, you end up with a little 'Qualcomm MobileAP' login page like:
Note: Since I was operating the Pi headless, and browsing pages via
curl
is all but impossible, I accessed the site from my Mac using an SSH tunnel (ssh -D 8080 [email protected]
), then I configured my network to use a SOCKS5 proxy with addresslocalhost
and port8080
). Then I could access the IP address of the modem in my Mac's browser (Chrome, in this case).
The UI looks ancient (and like many ancient designs, is likely vulnerable to many kinds of attacks), but it did seem to have a number of settings like a built-in firewall, some DHCP options, and basic WWAN settings:
It's not a very intuitive UI, though—and I also didn't see any easy way to do a 'factory reset' or to upgrade the modem from within the MobileAP interface. Seeing the copyright of 2014 didn't inspire a whole lot of confidence there :P
Updating Firmware
But speaking of the modem's firmware, there has to be a way it can be updated, right? Well... there is, with a tool called QFlash, which I found in the 'Tools' section of the EC25 page on SixFab's website.
But it references firmware files that are seemingly conjured up out of thin air, as if by magic.
The only firmware files I could find available for download were through random Google Drive links on forum postings or expired WeTransfer links. Yeah, like I'm gonna do that!
And if you search Quectel's forums, you'll find threads like this one, which seemingly never get resolved:
Quectel Rep: If you need the latest firmware, you can send email to [email protected] to get it, you can provide the firmware you used now, then we will arrange local FAE to support you, they will help to provide the latest firmware package, the upgrade tool and guide you how to upgrade it. Thanks!
Customer: I tried again to request firmware from support earlier this week. Any idea what sort of time I should expect for a typical firmware request?
Quectel Rep: Please provide your email and company name, your country to us, we will arrange local FAE to support you as soon as possible.
Customer: [after doing this loop a few times] ... 😑
So yeah... not sure why it's not possible for Quectel to just provide a firmware download page. And it looks like this isn't the first time someone's hit a brick wall communicating with Quectel; I found Harald Welte's OSMOCOM presentation suggesting it was difficult getting Quectel to provide the sources for their on-chip Linux build.
Choosing QMI or ECM
When I started out on my journey towards understanding 4G LTE on a Pi, I was quickly confused by the fact that almost every tutorial and setup guide had completely different instructions—and some where basically copy-and-paste of someone else's guide.
But nobody seemed to ever talk about the different connection methods: why do multiple methods exist? Why do modems (at least the Quectel) come with QMI and wwan0
set up by default? Is one method faster and/or better supported than another?
Don't know.
So I did a bit of testing in this GitHub issue, and found (informally, at least) that I could get consistently better latency and upload speeds with the ECM driver (cdc_ether
).
What's more, that driver (which sets up the usb0
interface) seems to work out of the box with everything in Linux, doesn't require me to set up a custom interface file with a bunch of extra commands, and is set up automatically just like any other network interface.
Am I missing something? Is there any upside to using the default QMI / qmi_wwan
/ wwan0
?
I asked about it on Twitter and will update this post if I find anything conclusive.
Selecting the default interface for Internet access
With an active 4G LTE interface (whether wwan0
or usb0
), there could be a new problem: what if you have two interfaces providing Internet connectivity? For example, what if your Pi also has a WiFi or Ethernet connection that has more stable or faster Internet, and you just want to use the LTE connection as a backup?
I won't get too deep in the weeds, but you can see how Linux will prioritize routing of the Internet connection by running route
:
pi@lte:~ $ route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default mobileap.qualco 0.0.0.0 UG 204 0 0 usb0
default 10.0.100.1 0.0.0.0 UG 303 0 0 wlan0
10.0.100.0 0.0.0.0 255.255.255.0 U 303 0 0 wlan0
192.168.225.0 0.0.0.0 255.255.255.0 U 204 0 0 usb0
I actually wrote up an entire blog post on how to change the metric
, so Linux will route through a different interface. Check out that post for all the details: Network interface routing priority on a Raspberry Pi.
But for the tl;dr: Linux will route packets through whichever interface has the lowest Metric
(which in the case above is usb0
) and matches the Gateway
IP range (0.0.0.0
means 'any IP address', basically).
So check out the linked blog post if you need to manage the Metric priority for different devices.
One case where that solution isn't so helpful is with the modem in QMI mode (wwan0
). Since that's using udhcpc
instead of the system's built-in dhcpcd
, setting the metric is not as straightforward as I hoped.
Based on the udhcpc documentation, I thought I could just add a file /etc/udhcpc/udhcpc.conf
and put IF_METRIC=400
inside, and that would be picked up as the routing metric... but that didn't seem to work. More investigation is needed.
Conclusion
I naïvely thought, coming into this project, that 4G LTE connectivity would be rather simple. But it's not. And it seems like there are basically two layers of documentation:
- Datasheets and code comments that expect expert-level understanding already.
- Beginner-level guides like "how to get your Pi connected to the Internet"
Hopefully some of what I wrote here can bridge the gap between those two levels—but I gotta be honest, I typically don't like writing a blog post when I only have a partial understanding of the subject... and that's what I have here. So take what I say about 4G LTE with a grain of salt ;)
Comments
It was suggested in this comment on HN that using ModemManager (with
mmcli
headless) might be the best option, and having the card in QMI mode. Here's the majority of that comment:Hey Jeff, thanks a ton for your very informative post. I know exactly what you mean with "there are only 2 types of instructions out there". I have been gone through that pain as well the last few days. There is so much useful information in your blog post, thanks again!
Was going to ask the same “why not use modemmanager on the pi?” as it pretty much covers all the variations in the hardware and does the setup with less configuration. Currently using it on an OpenWRT setup and its awesome. It also has support for sending sms, placing phone calls and such.
bini_man i'd like to get in touch with you for that setup!
Two bits of advice
For an LTE modem, there's tons of Dell DW5811e cards out on the used market. They are actually Sierra EM7455.
For a cheap IoT SIM, go to Amazon and search for ASIN B07JCTZ3BF. This IoTDataWorks plan is rate limited to 64kbps, but has no data limit. On an annualized basis it's a pretty good deal.
Just a heads up if you go with a Dell DW5811e card and you are following Jeff's notes you most likely need a M.2 NGFF Key B to Mini PCI-E Adapter such as
https://www.amazon.com/gp/product/B017R6FJKK/ and also this card has MHF4 RF Pigtail ports, not U.FL IPX IPEX ports like the pigtails that Jeff linked above. These should work https://www.amazon.com/gp/product/B098QDLQ75/
I would like to see you use the Pi to send and receive phone calls and text messages.
Look at the AT command list. You can send and receive. The catch to receiving is to look at the memory location for the incoming message which requires a different AT command to decode.
Just had to say thanks for putting this one together. Went through a similar process about a year ago trying to figure out QMI for some IoT gear and was just coming back around to finishing right as you released this post. Saved me so much heartache. I was dreading figuring it out all over again.
Ha! Yeah there are some projects I approach with a little too much trepidation, as I know my rusty knowledge is bound to end up making me go in circles. Most of the reason I spent a lot of time documenting things in this post is because I know I'll forget half of it by next month and would not like to have to spend all the time figuring it out again!
Excellent article Jeff (you're a star). As you said, there is very little useful information out there on how to set up these boards/HATs. Even the sample code from the manufactures do not Explain the underlying details.
My own UseCase is simple (and not at all unique) : I want to build a Raspberry Pi standalone IoT sensor, that will be installed many miles from a WiFi network, so I've bought a few HATs and (expensive!!) SIM cards :-(
Thanks to your article, I now have one (Waveshare SIM7000) connected to the outside world (can use your ping successfully). I can't currently see web pages hosted on the PI via LTE (but can locally when I have my WiFi turned on).... I'll crack on and get it working, but it's all harder than it should be :-).
Keep up the good work.
Thanks for the tutorial, coming from Reddit. I got it working!
I just re-read this.
I use a TOFU board which has the .m2 interface on the rear of the CM4 board and a sim slot.
This is really a nice way to go.
FYI,
There are quite big differences with bullseye, and the setup is far from bugfree, ie. can often disconnect or do all kinds of bad stuff.
Setting up modemmanager as a service, so that it boots up from scratch has to be the way to go.
Being as the CM4 chips are pretty much unobtanium, (esp the ones with wifi and lots of RAM), it's quite a struggle to implement any strategy reliably right now, so for the present I use a standalone modem board with router OS, a highly minaturised credit sized board made in Russia (er yes!), instead of the less well designed microtik offerings originated in Latvia.
The biggest hic on any router/Sim/4g-LTE system is roaming, which we in Europe simply have to have if any routing system is installed in anything mobile like a vehicle. (ask me about that!).
That's another whole can of worms.
Hi, thanks for the write up! I went through this process using the SixFab website, successfully got my pi4 up and running on QMI with Telit modem.
I'm running into the issue now though where my wlan0 doesn't connect at all to any saved network. I can see them, but can't connect. Wired networking works fine. My goal is to do what you were saying in last part, prioritize routing through better connection.
Any ideas why my wireless isn't connecting? Haven't found much on this, seems that most want internet through the sixfab modem and thats where they stop.....
Hi, thanks for the write up! I went through this process using the SixFab website, successfully got my pi4 up and running on QMI with Telit modem.
I'm running into the issue now though where my wlan0 doesn't connect at all to any saved network. I can see them, but can't connect. Wired networking works fine. My goal is to do what you were saying in last part, prioritize routing through better connection.
Any ideas why my wireless isn't connecting? Haven't found much on this, seems that most want internet through the sixfab modem and thats where they stop.....
Hi Jeff,
I have really enjoyed this tutorial. I have a twist to it though.
I have a requirement for a dual-WAN portable router, using 2 SIM cards, with the ability to configure WAN failover, load balance, or bonding. For now, I am looking at the failover. Suppose I connect 2 4G USB dongles to the Pi4, there should be a way to achieve this scenario, I believe.
Could you add a description for setting up an mbim 4g modem?
Great article. I am wondering how you could access the GNSS data?
That's something I haven't tested yet, sorry!
AT Commands
Just ran through this guide and all went well except for one item. I changed the wwan0 interfaces file to start wwan0 on reboot but it doesn't seem to be working. Here is my config file:
auto wwan0
iface wwan0 inet manual
pre-up ifconfig wwan0 down
pre-up echo Y > /sys/class/net/wwan0/qmi/raw_ip
pre-up for _ in $(seq 1 10); do /usr/bin/test -c /dev/cdc-wdm0 && break; /bin/sleep 1; done
pre-up for _ in $(seq 1 10); do /usr/bin/qmicli -d /dev/cdc-wdm0 --nas-get-signal-strength && break; /bin/sleep 1; done
pre-up sudo qmicli -p -d /dev/cdc-wdm0 --device-open-net='net-raw-ip|net-no-qos-header' --wds-start-network="apn='Broadband',ip-type=4" --client-no-release-cid
pre-up udhcpc -i wwan0
post-down /usr/bin/qmi-network /dev/cdc-wdm0 stop
Any help or troubleshooting tips would be much apporeciated
Thank you Jeff for great contents, I could establish LTE & RPI system with your tutorial.
I am also having same problem as Chris.
sudo ifup wwan0 is working really well,
but it seems like auto wwan0 is not working.
Great tutorial but the same issue here, automatic reconnect after reboot doesnt work and it shows this error:
Aug 03 18:19:35 raspberrypi systemd[1]: Starting Raise network interfaces...
Aug 03 18:19:37 raspberrypi ifup[391]: wwan0: ERROR while getting interface flags: No such device
Aug 03 18:19:37 raspberrypi ifup[298]: ifup: failed to bring up wwan0
Aug 03 18:19:37 raspberrypi systemd[1]: networking.service: Main process exited, code=exited, status=1/FAILURE
Aug 03 18:19:37 raspberrypi systemd[1]: networking.service: Failed with result 'exit-code'.
Aug 03 18:19:37 raspberrypi systemd[1]: Failed to start Raise network interfaces.
Thanks for the excellent writeup. Based on this I decided that adding wireless connectivity to a project I was working on might not be out of reach. I spent a bunch of time looking into the routing metric issue, and it seems to be working by adding the ifmetric command as the last pre-up command in the interfaces file. This is using the Waveshare SIM7600G-H 4G HAT (B) It didn't seem to offer ECM mode by the AT command interface.
This worked for me. Thanks!
you don't need to shutdown ModemManager to issue commands - simply use -p as you are with other qmi commands
Hi jeff, Im using a raspberry pi zero and a SIM7600 connected via UART. My problem is the lsusb-t doesnt show "usbcore: registered new interface driver qmi_wwan", I added enable_uart=1 in the config.txt. Also Im using both SPI and they work fine. Thanks and sorry for my english.
Can you or anyone explain me, how I get this working with ipv6?
I get an ipv6 connection but don't know how set the address and routing on the wwan0 interface, and DNS. udhcpc does not work with ipv6.
FYI, dhcpcd fixed the issue with raw-ip sometime between versions 8.1.2 and 9.4.1, that makes it not necessary to use udhcpd.
I had all parts working according to this blog's instructions except when running sudo udhcpc -q -f -i wwan0
It correctly returned...
udhcpc: started, v1.30.1
No resolv.conf for interface wwan0.udhcpc
udhcpc: sending discover
Then failed with...
"udhcpc: no lease, failing"
The solution was do add the line "denyinterfaces wwan0" to the bottom of /etc/dhcpcd.conf and restart dhcpc before continuing. Then it got an IP address and worked. I found the solution at the following link.
https://community.sixfab.com/t/solution-to-failed-to-get-dhcp-lease/600
Do you use any enclosure/case for the modem?
I have generally followed your guide, except for using a USB to NGFF M.2 Key B Adapter as I had an extra Sierra Wireless EM7455. All seems to be working okay, but for long term use, I don't want to leave everything exposed, especially travelling.
Thank you for the guide; it was very helpful.
Would esim be a possibility?
I haven't tried working with eSIMs on any of these cellular modems yet. I'm sure there are ways to do it, it's just not something I've really had to test.
Thanks Jeff this was helpful. This is the setup I've landed on:
I'm using a QUECTEL Mobile Broadband Module which shows up on
/dev/cdc-wdm0
, and a NetworkManager configuration.The latest version of Pi OS can install NetworkManager through
raspi-config
. I believe this will lose the WiFi settings so it probably shouldn't be done over WiFi. The options are "6 Advanced Options", "AA Network Config", "2 NetworkManager".Afterwards, the NetworkManager setup.
To set the APN:
sudo nmcli connection add type gsm ifname '*' con-name '1-gsm' apn '<APN>' connection.autoconnect yes
. If everything is working it should connect after this.To see the state of the NetworkManager devices:
nmcli
To scan WiFi:
sudo nmcli device wifi
To reconnect to WiFi:
sudo nmcli device wifi connect <SSID> password <PASSWORD>
Etc. etc.
With this setup, ModemManager can be used to get modem and SIM information.
List modems:
mmcli --list-modems
Modem information:
mmcli --modem=<path from previous>
SIM information
mmcli --sim=<SIM path from modem command>
(imsi, iccid, ...)The NetworkManager connections can also be supplied as a
*.nmconnection
file in/etc/NetworkManager/system-connections/
which could be copied there andchmod 600
to clone the setup from another system instead of using the CLI commands.(Oops, I used angle brackets in some of my examples so the commands are not totally correct.)
Hey, I was wondering about signal strength. I think one cool application would be to use this in more remote areas for quick phone calls. So, setup the Pi over cellular, set the Pi up as a hotspot for your phone to connect to via wifi, then use the data to make VOIP calls or rather just using it as a hotspot for other devices to connect to. For hunting in remote places, I wonder if this would be feasible. I'm assuming the antenna would play a big part in it as well. Are there "beefy" ones available to help with this?
Hi Jeff, appreciate all the hard work you do and have found your content excellent. Can you provide any insights on using RPI Bookworm NetworkManager with Waveshare SIM7600 boards on Pi4/5? I'm currently running several of these boards on 8GB Pi4s with 64 bit Bullseye with no issues using QMI following your excellent instructions. Well one issue: In the USA I have to activate Verizon circuits on non-waveshare 4G hardware first and then move the SIMs to the Waveshare boards because VzW won't activate on Waveshare IMEIs (but they run fine once activated). Any expected cellular or interface issues if I migrate my Pi4 8GB units to Bookworm?
Using your guide I've now been able to stream video from my Pi CM4 over the mobile internet using a Quectel EC21. Thanks for detailing all the steps involved. The final part of the equation for me was to set up a point-to-point VPN connection as described at: https://openvpn.net/community-resources/static-key-mini-howto.
How did you manage to do that? AT commands
Thanks a lot! You did a wonderful job! However, after rebooting the RPi ifup (sudo ifup wwan0) command gives me an error: "ifup: failed to bring up wwan0"
which is basically due to the `ModemManager`. We need to stop the `ModemManager` to bring the wwan0 interface in it's action (
sudo systemctl stop ModemManager)
After that, we can do the ifup command (sudo ifup wwan0).
Can i use this same commands to make it work with SIM8200EA 5G M2 Hat on top of Rasberry pi 5?
I just went through this using the ECM mode, all went well on the modem side connecting and getting an IP address, but nothing on the Pi side (just an unassigned ipv6 address):
usb0: flags=4163 mtu 1500
inet6 fe80::e212:b510:b050:6858 prefixlen 64 scopeid 0x20
Turned out I needed to:
sudo udhcpc -i usb0
to get an IP address:
usb0: flags=4163 mtu 1500
inet 192.168.225.22 netmask 255.255.255.0 broadcast 192.168.225.255
inet6 fe80::e212:b510:b050:6858 prefixlen 64 scopeid 0x20
after which everything worked fine. Thanks
This was an incredibly helpful blog post. Thank you for providing a practical guide!