IOT: Adventures in 5G
NOTE: The Oldest Draft Ever
I apologize for the huge delay in getting this draft out. I don’t get on the blog a lot.
One of the ways I avoid the burnout at work is to go on a related side quest. Today’s side quest is assembling a standalone network probe which can be used to keep an eye on a 5G/LTE APN that we are using at work.
The introduction of the APN itself was quite the announcement at work. The principal intent was to leverage 5G technology to provide an improved connectivity experience for the physician population. While I have a lot of opinions about the project, the new reality is somewhere around 2,000 5G handsets are in the hands of clinical staff.
From a network architecture and operation perspective, it became readily apparent that we did not have a way to independently collect and validate any sort of metric data. Why not build a 5G probe to do the things that we need?
The Hardware
Feature Requirements
A couple of things that we needed for the probe were:
- Relatively inexpensive hardware.
- Linux operating system.
- Generally supportable (ideally) by folks other than myself.
- PoE capable, because wall warts are not good for this purpose.
As development platforms for smaller IOT devices go, there isn’t much that can really compete with the Raspberry Pi platform. Conveniently, the Pi 5 came out and brought a very welcome iteration to the Pi line that was going to be suitable for this task. I ended up getting this Pi5 Kit from MicroCenter since I drive by there on my way home.
When it came to adding a 5G hat, the one which was recommended to us was the SixFab 5G Modem kit for the Pi5. This is based on the RM502U modem from Quectel. The modem comes with the hat, a pin header, and its own USB-C power supply. Our IT wholesaler was able to turn around a PO on these pretty quickly.
The final feature to satisfy was PoE power. I picked up this PoE+ hat from PiShop.us to cover that ground. At a minimum, this would save me one wall wart.
The Hat Stack
The hat stack is a pretty impressive collection of parts once it’s all bolted together:

My primary complaint is that the collection of standoffs I had from the modem and the PoE hat aren’t exact fits to each other. Most of the standoffs aren’t particularly made to be stacked upon each other either.
The case will need to be a custom 3D print, once the device is functionally completed. Just so I can run out the drab filament, the case will likely be printed in what my children and I call “Mental Health Grey”.
Powering the Modem
As far as thought outside the box went, I figured it was worth a shot to see if the USB-C port on the Pi would be capable of powering up the modem. To my surprise, this worked. I suspect that this is not the intent. I’ve got a couple of stupid short jumpers coming via Amazon to keep the loops tidy.
My suggestion to SixFab and others would be to have a means to draw power from the GPIO header. I understand not wanting to do this in the normal case, but it would be very handy for folks who use PoE+ hats in their stack and have the wattage to spare.
The Software
There are a couple of options when it comes to Linux distributions. Raspbian is probably one of the most common installations done on the Pi. Pretty much everything that is required is built in.
Ubuntu 24 LTS
My Linux preference has been Ubuntu for quite a long time, so I more or less settled on Ubuntu 24.04 server. I flashed this onto a microSD card using the official Raspberry Pi imager. The added bonus of this, being that I could enable SSH and set my username and password as an option making for a headless boot.
We have a couple packages to add:
- gpiod
- minicom
- net-tools
- traceroute
- udhcpc
Also, we need to remove the modemmanager package. We need this removed so we can access the control port on the modem manually. Otherwise, this is being treated like a serial modem from the old times.
sudo apt remove modemmanager
Modem Configuration
For convenience, the modem can be configured with minicom. For this particular module, the TTY port we’ll be using us /dev/ttyUSB2.
minicom -w -c on -D /dev/ttyUSB2 -b 115200
Once we are on the modem, we’ll want to issue a factory reset of some variables. It’s useful to have character echo enabled so we can see what we’re typing. We want to be sure we receive an “OK” response when we type in AT:
at
OK
Modem Mode
We need to be in QMI mode. We can query this by looking at the status of “usbnet”
AT+QCFG="usbnet"
+QCFG: "usbnet",0
OK
If our mode is not zero, we need to set it as such followed by resetting the modem:
AT+QCFG="usbnet",0
OK
Also of importance, we want to be sure the modem is enabled, and restart. Minicom will report the tty is unavailable while the modem resets itself. The modem comes back online and will be in the RDY state:
AT+CFUN=1,1
OK
RDY
We want to be sure the qmi_wwan driver is the one we are seeing via lsusb:
$ lsusb -t | grep wwan
|__ Port 001: Dev 003, If 4, Class=Vendor Specific Class, Driver=qmi_wwan, 5000M
APN Configuration
We can also configure our APN from the AT session as well:
AT+CGDCONT=1,"IPV4V6","YOUR_APN"
OK
Registration
We can verify the ability to register to the APN on the modem itself with some AT commands. There is a router mode for this particular module which requires the AT command set before anything comes online.
We can now check our registration status. We do this by typing in “AT+CREG?”. In this response, we see it is 0,1.
AT+CREG?
+CREG: 0,1
OK
Next up is to set the registration to automatic:
AT+CREG=2
OK
If we give it a moment, we will see the registration show as active.
AT+CREG?
+CREG: 2,1,"55F5","0BBD802",13
OK
Finally, we can query the modem to find out what IP address we were given. Since this is a private APN, the RFC-1918 address is expected.
AT+CGPADDR=1
+CGPADDR: 1,"10.22.150.205"
OK
Interface wwan0
Next up, we will configure the wireless wide area network, WWAN0 interface.
First up, we check on our current operating mode. We want this to be “online”
$ sudo qmicli -d /dev/cdc-wdm0 --dms-get-operating-mode
[/dev/cdc-wdm0] Operating mode retrieved:
Mode: 'online'
HW restricted: 'no'
We want to be in raw IP operational mode. Before we can do that, we need to verify wwan0 is down. Then we reconfigure the interface as raw IP, and bring it back up:
sudo ip link set wwan0 down
echo 'Y' | sudo tee /sys/class/net/wwan0/qmi/raw_ip
sudo ip link set wwan0 up
We can verify that we are using raw_ip:
$ 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'
Uplink data aggregation protocol: 'disabled'
Downlink data aggregation protocol: 'disabled'
NDP signature: '0'
Downlink data aggregation max datagrams: '0'
Downlink data aggregation max size: '0'
Also, we can see in an “ip link” that our interface is now configured as a point-to-point;
$ ip link | grep wwan0
5: wwan0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 1000
Next, we’ll open up the network connection. I am using a private APN, so I do not have any username or password specified in this command line:
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
When this is successful, it lets us know the network is started:
[/dev/cdc-wdm0] Network started
Packet data handle: '4015756704'
[/dev/cdc-wdm0] Client ID not released:
Service: 'wds'
CID: '17'
Finally, the last item is to use udhcpc to pull down the IP info from the modem:
sudo udhcpc -q -f -i wwan0
This gives us the IP we want. For this case, the address is correct because it is connecting to a private APN:
udhcpc: started, v1.36.1
Dropped protocol specifier '.udhcpc' from 'wwan0.udhcpc'. Using 'wwan0' (ifindex=3).
udhcpc: broadcasting discover
udhcpc: broadcasting select for 10.22.150.205, server 10.22.150.206
udhcpc: lease of 10.22.150.205 obtained from 10.22.150.206, lease time 7200
Dropped protocol specifier '.udhcpc' from 'wwan0.udhcpc'. Using 'wwan0' (ifindex=3).
We can also see the DNS information we received as well with resolvectl:
$ resolvectl status wwan0
Link 3 (wwan0)
Current Scopes: DNS
Protocols: +DefaultRoute -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 1xx.1xx.12.1
DNS Servers: 1xx.1xx.12.1 1xx.1xx.12.2
$
We can verify that we’ve got outbound traffic:
$ ping 4.2.2.1 -c 5
PING 4.2.2.1 (4.2.2.1) 56(84) bytes of data.
64 bytes from 4.2.2.1: icmp_seq=1 ttl=49 time=257 ms
64 bytes from 4.2.2.1: icmp_seq=2 ttl=49 time=99.1 ms
64 bytes from 4.2.2.1: icmp_seq=3 ttl=49 time=98.1 ms
64 bytes from 4.2.2.1: icmp_seq=4 ttl=49 time=97.1 ms
64 bytes from 4.2.2.1: icmp_seq=5 ttl=49 time=88.0 ms
--- 4.2.2.1 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4004ms
rtt min/avg/max/mdev = 88.021/127.916/257.268/64.796 ms
$
At this point, the system is now online via the APN and is directly accessible.
Persistent Configuration
The last step for what I need to do with the module at this stage is to make sure it boots up on its own and can manage to connect to the APN without much difficulty.
Other Fun Modem Commands
Here are a few other commands that you can use when connected to the modem side:
Signal Quality
We can check our signal quality at our location:
AT+CSQ
+CSQ: 31,99
OK
RF Band Information
We can look at our current RF band:
AT+QNWINFO
+QNWINFO: "FDD LTE","310260","LTE BAND 66",66736
Service Cell Tower
We can look at the specific tower that we are connected to:
AT+QENG="servingcell"
+QENG: "servingcell","NOCONN","LTE","FDD",310,260,BBD802,424,66736,66,5,5,55F5,-87,-18,-48,10,0,-,37
OK
Neighbor Cell Towers
As well as see the neighboring towers:
AT+QENG="neighbourcell"
+QENG: "neighbourcell intra","LTE",66736,424,-14,-87,-52,-,36,7,8,0,46
+QENG: "neighbourcell intra","LTE",66736,188,-15,-88,-64,-,35,7,8,0,46
+QENG: "neighbourcell inter","LTE",875,-,-,-,-,-,36,6,0,8
OK
Resources
- Quectel: Quectel_RG50xQ&RM5xxQ_Series_AT_Commands_Manual_V1.2 | Quectel
- SixFab: 5G LTE Cellular Connectivity (sixfab.com)
- SixFab: Setting up a data connection over QMI interface using libqmi (sixfab.com)
Filed under: 5G,Networking Adventures,Observability - @ 2024-09-27 5:42 pm
Tags: 5G