❌

Reading view

There are new articles available, click to refresh the page.

Building a Simple Internet Radio

Broadcast radio isn’t as popular as it once was, its popularity suffering in turn due to technologies like MP3 players and music streaming services. If you don’t fancy either of those, you might like to listen to some internet radio stations, using a rig like the one [CodersCafeTech] built.

It’s a simple desktop radio set, but instead of tuning in to AM or FM broadcast bands, it has an antenna for 2.4 GHz instead. That’s because inside this radio is an ESP32-S3 development board, which is equipped with onboard WiFi hardware that lets it connect to the internet. It’s hooked up to a 1.3-inch OLED display over I2C, which acts as a user interface in concert with a rotary encoder. Sound is handled with a MAX98357 I2S audio amplifier, hooked up to a small 3 W speaker. Once programmed appropriately, all the unit needs is a WiFi SSID and password, and the URL for the internet radio station you’d like to listen to.

We’ve featured a few internet radio builds over the years, as well as a rather fun build that saw a Macintosh SE/30 hooked up to Spotify. If you’re tinkering with something along those lines, don’t hesitate to let us know on the tipsline!

5 GHz Drone Video, With An ESP32

With the ESP32 series of microcontrollers having had hidden software-defined radio (SDR) facility revealed, we’re now moving on from the announcement into projects making use of the finding. [Twotoz] has one using an ESP32-C5, to receive and demodulate analog FM video.

You might think that video is something which has largely gone away in 2026, with TV transmissions having made the switch more than a decade ago, and home entertainment appliances having used HDMI for longer. But it’s still very popular in the world of drones however, where it exists as 5 GHz FM transmission. There’s no digital cliff-edge to lose your picture if you fly into somewhere with bad propagation of radio waves, and perhaps more importantly, it has an extremely low latency. This receiver uses a Seeed Studio Xiao ESP32-C5 board with a simple resistor-ladder DAC to produce the video. It has a simple button channel interface, and a serial link for more in-depth options.

It’s good to see these projects appear, especially as this one’s 5 GHz and shows those chips work too with the hack. We’d be interested to know whether the latency of the SDR affects its usability though. You may be interested to know this isn’t the first time we’ve seen an SDR do video.

Thanks [Ink] for the tip!

2026 Retrocomputing Challenge: Dollhouse Arcade Cabinet Runs Remote DOS Games

Classic DOS games never ran from within stand-up arcade cabinets in dollhouses, but [Juha Lilja] imagines a world in which they did. His Micro DOS arcade cabinet is described as a device that “runs nothing” because the tiny unit is actually streaming the games over Wi-Fi from a nearby PC. That doesn’t mean it’s just a glorified movie player, though — the cabinet is playable, if a bit awkward to do so.

An economical development board and a 3D-printed enclosure is all it takes to put classic DOS games into dollhouse-sized arcade cabinet.

The core of the micro arcade cabinet is a M5Stack AtomS3R running as an embedded remote terminal. One tilts the whole cabinet as if it were a virtual joystick to send up, down, left, and right. Button presses are done by pushing on the physical screen; it supports single, double, and long-clicks. While in theory one could install a micro joystick and buttons instead, [Juha] aimed to keep everything self-contained and use only what was already built into the AtomS3R. In this case, that’s a motion sensor and the single button which is activated by pressing the screen.

The games themselves run on a PC, with screen contents being streamed wirelessly to the little display and inputs being sent back. The firmware on the AtomS3R doesn’t know or care what game is being played; all it does is display what it’s told, and send back input events. The back end does the rest. This makes it pretty flexible, and a tiny arcade cabinet is a handy way to demonstrate the whole system. It’s a pretty slick addition to his daughter’s dollhouse, too.

If streaming DOS games (or whatever else) to economical endpoints is giving you some ideas, the GitHub repository holds code and a fuller explanation of how it works. There’s a deeper discussion on some of the finer technical points, as well. Watch it in action in the video embedded just below the page break.

2026 Hackaday Retrocomputing Contest

So You Want To Make Your SDR Work On Other Frequencies

Perhaps the most exciting news of the past few weeks in the world of hardware hacking has been the unlocking of hidden SDR functionality in the Wi-Fi radios found on Espressif ESP32 microcontrollers. They can be used as both transmit and receive SDRs, and given that it’s early days for this hack we expect that great things are yet to come.

There’s one snag though, despite speculation that they might be dragged down to much lower frequencies, as far as we know they’re only proven to work around the Wi-Fi frequencies. Though the reality may be wider we’ll take that for a 2.4 GHz part as a 100 MHz slice from 2.4 GHz to 2.5 GHz. Plenty of possibilities there, and they might even work down to 1.8 GHz, but there would be so much more to do if it could work elsewhere in the spectrum. So it’s time to look at the converter, a tried and tested old way to make a radio work on a different frequency.

A Lesson From Analogue Receivers

TV tuner front end block diagram. Derived from Chetvorno (Own work) [CC0], via Wikimedia Commons
TV tuner front end block diagram. Derived from Chetvorno (Own work) [CC0], via Wikimedia Commons.
I hope most of you will be familiar with what happens when you mix two frequencies; the resulting spectrum contains both their sum, and their difference. This was the mechanism behind the tuning dial on your analogue radio or TV, the dial moved an oscillator, and a sensitive circuit tuned to a so-called intermediate frequency would filter out the difference frequency between the oscillator and the station you wanted. A few years ago we had a deep dive into the UHF hackers playground of an analogue TV tuner, where we examined this in depth.

A converter uses exactly this principle. The antenna frequency range is mixed with the output of a fixed oscillator whose frequency is chosen so that their difference represents the frequency band of your radio. THus tuning your radio tunes across the output of your mixer, which is the same as tuning across the antenna frequency range. For a numerical example, if the ESP32 receives from 2.4 GHz to 2.5 GHz, a mixer on its input with a 2 GHz local oscillator would allow the ESP32’s receiver to pick up the 400 MHz to 500 MHz band. In practice the circuit requires filters for both input and output to keep out-of-band stuff from going where it shouldn’t, but it really is that simple. Best of all, with appropriate handling of power and amplification, it works for transmitters too, and such a device is called a transverter.

Towards An Achievable Receive Converter

To make a practical converter then, we need an input filter, a mixer, an output filter, and a local oscillator. The filters are often off-the-shelf parts and needn’t be too expensive, the mixer can be as simple as a fast Schottlky diode, and the local oscillator could even in this case be another ESP32, they’re that cheap. You can add amplifiers if you want and what I am about to describe is a somewhat janky receive converter, but it can be made to work.

The Filter

A very simple Pi network low pass filter
A very simple Pi network low pass filter

In most cases such a converter will be intended to receive signals lower than the ESSP32’s range, so let’s assume you’re looking somewhere from HF through to VHF. The input filter has to reject anything above your maximum input frequency and stop any stray local oscillator leakage to the antenna, which most of you will identify as a low-pass filter. These can be bought off the shelf for a price, but are easy enough to make for yourself.

The most common low pass filter is often referred to as a Pi network because its circuit superficially resembles a Greek letter Pi, and takes the form of an inductor in the signal path with a capacitor to ground either side of it. If you know your maths you can calculate the values for yourself, but if you don’t there are many online Pi network calculators to help you. Constructing a Pi network at these frequencies is straightforward enough.

For the output filter, you need something that rejects the local oscillator frequency as much as possible, and passes the ESP32 receive range. Here you’re in luck, because the Wi-Fi hardware industry needs exactly those filters, so they can be had from Mouser or Digi-Key for cheap. I’m not going to specify a particular part, but I’d like to point you at the TDK Wi-Fi filter range and invite you to pick one with the bandwidth you need.

The Local Oscillator

Your local oscillator for an ESP32 working at much lower frequencies is likely to be around or above 2 GHz. Back in the day you would have used a crystal oscillator and multiplier circuits, if you like you can buy an expensive PLL oscillator module, but your simplest and probably cheapest method is to use another ESP32, now that it can be used as an SDR transmitter. Program it to output a single carrier on your desired frequency, dial down the output level, and there you have it, a 2 GHz local oscillator for a dollar or two.

The Mixer

Yet again you can buy an off the shelf mixer as a module, though one for a 2.4 GHz output will be expensive. Happily there’s a simple circuit which can do the job, and it uses a diode as a non-linear element fed with both antenna and local oscillator signals. At these frequencies you are looking for a very fast small-signal Schottky diode with as low a capacitance as you can find, and happily such parts are available from multiple manufacturers at cent rather than dollar prices. The basic circuit is shown below, and as you can see it’s quite simple.

The circuit of a simple unbalanced diode mixer with a bandpass filter on its output.
The circuit of a simple unbalanced diode mixer with a bandpass filter on its output.

In the circuit above the diode is your Schottky device, the input low pass filter isn’t shown, and the output filter is an off-the-shelf Wi-Fi bandpass filter. The two thick lines represent a stripline coupler, and they are simply two parallel PCB traces side by side over a groundplane. Their size should ideally be calculated to present the right impedance, often 50 ohms which is also the value of R1, but in practice the jankiest solutions can work here. With an ESP32 as a local oscillator I would hazard a guess that laying the trace on the PCB under the module’s antenna with the power turned down would be enough. I may earn the scorn of some of my peers, but I have a long history of RF bodging and I think it might just work.

Making It Transmit

The same technique as above works for shifting the ESP32’s transmit output down to the desired frequency, but there’s a catch. Even the modest output from an ESP32 can be enough to damage or overload parts designed for receivers, so you have two choices. Pick transmit-appropriate parts, or dial back the power to a low level, and amplify it at the lower frequency.

By Now, You Should Be Able To Bodge A Converter

The information above isn’t a ready-to-go design for a receive converter to get your ESP32 listening to lower frequencies, but it should give you all the signposts you need to get there. People have built converters for the RTL-SDR for ages now, so you could pilfer ideas there too. If you build a downconverter, for transmit or receive or both, let us know!

At a superconference about a decade ago there was a talk about RF construction techniques which will save you a lot of pain, and with luck such a simple circuit should be within your grasp. Good luck.

Building An M7 Pan Tilt Head Controller

The Soonpho M7 Pan Tilt Head is a useful photography tool for remotely aiming a decently-sized camera. Only, [Kyle Housley] wanted a little more control than was available out of the box. Hence, he built a custom controller that could deliver just that.

The project is based around an ESP32-S3 paired with an NRF24L01 wireless module. The ESP32-S3 is hooked up to a computer to receive commands over serial on what movements to make. It then transmits over the NRF24L01 to another NRF24L01 module that has been hacked into the original M7’s controller. In doing so, it can command the M7 to move to a given specific pan and tilt position, or to make a smooth motion along a vector. It can also trigger shutter release in the attached camera as needed, to capture whatever is being looked at.

[Kyle] has used this rig to create a motion tracking system for aircraft photography. With a Yolo vision model running on a laptop, the pan-tilt head can be commanded to track aircraft passing by and photograph them when they’re in frame. It’s a pretty slick setup; we’d love to see similar done with the aid of ADS-B data, too—perhaps even with automatic image tagging and upload. 

Pager Converted to Meshtastic Node

Text messaging has been around on cellular networks en masse for around three decades now. It’s so common that it’s difficult to remember a time without it. Its two-way quick messaging is incredibly useful, but for even simpler communications there’s a one-way system that predates it. Pagers are able to receive simple messages, but outside of hospitals are rarely used nowadays. Eventually some added in two-way communications like this Motorola T900, but they’re still mostly obsolete. That’s why [zindustries87] converted it to operate on the Meshtastic network instead.

To get this pager working, a lot of reverse engineering was needed. There is essentially no documentation on the chips in these devices, so the screen and keyboard both were reverse-engineered to work with other hardware. In this case, [zindustries87] found space for a Heltec V4 with an ESP32-S3, a popular Meshtastic node with a small form factor. Some programming was needed to get everything communicating together, but from the looks of things it seems to have basic functionality.

[zindustries87] points out that this is a prototype, and didn’t know going in if the keyboard and screen could be brought back to life, or if the other hardware would fit in the case. But with it working on this level, they plan to add a number of other features in and possibly build a drop-in PCB replacement for these devices. They were once fairly popular so there are plenty around, and they’re a good form factor for a dedicated Meshtastic device that doesn’t need a smartphone to work. The only other ways of bringing pagers back to life involve bootstrapping an entire pager network, and Meshtastic is a bit more useful than that now.

AI Controls iPhone Via ESP32

Do you want to get an AI agent to do something to an iPhone? You could try and jailbreak the device and do some heavy software hacking, or… you could grab a microcontroller off the shelf and have it do the hard work. [Henry Yuan] explains how to achieve this with an ESP32.

The first step is getting an AI agent access to the current state of the phone screen—which [Henry] achieves with AirPlay screen mirroring and UxPlay. A Gstreamer pipeline is then used to feed the screen as a JPEG stream to the AI agent of your choice. Then comes control, which is achieved by an ESP32-S3 acting as a USB-HID device, emulating both USB mouse and keyboard. With iOS AssistiveTouch enabled, this gives the agent control over inputs to the device. From there, it’s up to the AI agent to figure out the actions to make to achieve the desired behavior, which is obviously very use-case specific.

It might sound a little convoluted, but this approach has benefits. There’s no requirement to have an Apple Developer Account, or XCode, or a Macintosh at all. You can just get your agent tinkering away on the phone without any of that fussy overhead. We’ve featured some other great iPhone hacks of late, as well. Video after the break.

ESP-SDR Can Now Transmit

Well, that was fast! Last week, we reported on two apparently simultaneous hacks using the 2.4 GHz radio inside many ESP32 variants that enabled raw access to the radio samples, turning it into a listen-only software defined radio (SDR) platform. Listen only? That’s only half of the SDR story.

Last weekend, [marble] got started fixing that, and released an early early version of ESP32 firmware that can also transmit, and got it working with gqrx. The demo communicates between an S3 and a C6 using a Hellschreiber mode, something that’s certainly out of the WiFi spec. And it didn’t stop there, either. [marble] is working on 802.15.4 modulation at the moment, which means that maybe soon your ESP32 will speak ZigBee.

This is all in the roughly 2.4 GHz band, but [marble] suggests that it might be good down to 1.8 GHz. (Editor’s note: previously, we said 100 MHz, but that was incorrect.) So there is still some uncharted terrain, and it’s clear that the boundaries on the ESP-SDR are just starting to get pushed.

If the early hacks on the RTL-SDR set off a wave of hacker SDR radio experimentation, and we can only hope that this is the beginning of the ESP-SDR era. Thanks then to [marble]– and the original hacks coming from the Espargos team for kicking this all off!

ESP32 As Your Raspberry Pi’s Linux Wireless Co-processor

A laptop with no wireless connectivity feels like a rarity – but when you shop for powerful Linux single-board computers (SBCs), it is pretty common to see one skimp on WiFi. At the same time, current wireless cards can leave much to be desired. A mess of proprietary firmware, ephemeral or even binary blob drivers, weird glitches never resolved, and sometimes entirely source-less blobs with an expiration date. Maybe the SBC doesn’t have a free USB port for a plug-and-play WiFi chip, or you don’t want to design for an obscure hard-to-source castellated module.

What if I told you there’s a unique solution to the problem, as long as the SBC has an SDIO or SPI to spare? There’s a wireless card we can all try to get behind, and it’s certainly not flawless but gives us way more room to grow – it’s got somewhat open-source firmware, it comes from a respectable company, and it’s nigh-guaranteed to be easy to source. I am, of course, talking about esp-hosted – using ESP32 modules as your WiFi/BT card, over SDIO or SPI.

I’ve recently added an ESP32-C6 into my project, and setting up esp-hosted wasn’t ultra straightforward – so here’s a guide, and a discussion on what makes esp-hosted so cool and so incredibly promising. Spoilers: it works with privacy switches that cut out power, it could be hacked into a coprocessor for mesh protocols, and it could potentially help us build a fully open-source SDIO WiFi card.

Two Halves, Most Chips Supported

A quick clarification is warranted, as there are two projects under the esp-hosted roof. There’s the esp-hosted-mcu (previously known as esp-hosted-fg, “First Generation”), which runs the ESP32 as more of an MCU connected to WiFi and provides a relatively limited but self-sufficient interface on the Linux side; your connection aspects are mostly managed by the ESP32 module, so it will connect to your defined WiFi networks no matter if your host is rebooting or even fully off. As such, esp-hosted-mcu works best on microcontrollers, or in cases where you want your ESP32 to be a fully conscious separate entity, so to say. Want to make your ESP32 into an EC for your board, complete with WiFi connectivity? Then go with the -mcu version.

esp-hosted-linux (previously known as esp-hosted-ng, “New Generation”) leaves the wireless stack on the Linux side, with the ESP32 being a relatively thin proxy for the Linux wireless stack. I’ll talk about esp-hosted-linux here because it behaves in the most “native” way that regular WiFi cards do under Linux, but a lot of this article will apply to esp-hosted-mcu too.

esp-hosted requires two to tango: a Linux computer with an SDIO or SPI port to spare, and an ESP32 chip/module out of supported ones, I opted for ESP32-C6. The generic ESP32-WROOM modules are more than enough, but most of the shiny new chips are supported as well. Specifically, ESP32-S2, -S3, -C2, -C3, -C5, and -C6/C61 can all work with the esp-hosted-linux, and if you’re playing with something like the -S31, check the issue tracker of the parent project. I run the C6 because I thought it was the chip with the largest amount of supported features, and it’s marginally more expensive than any of the other ones, so why wouldn’t I? However! That was a mistake, and if I were to design a new board, I’d go with the ESP32-C5. Turns out, despite the C number being lower, ESP32-C5 is straight up better than the ESP32-C6, sporting 5GHz support in particular.

From there, you’ll want to wire it up over SDIO or SPI – I recommend SDIO if available, because it’s way speedier. One thing – make sure that your SBC’s SDIO interface is supported by the OS, and not in the limbo state of “the hardware is ready, someone just needs to make the driver work”, unless you can be that somebody. If you already have a devboard, you can bodge in an SD card onto your supposedly-SDIO pins to verify that your SDIO interface actually functions!

SDIO is essentially a full-duplex parallel bus with one control signal (CMD), one clock (CLK), and four data lines (D0-D3) – or just one data line, D0, if you feeling ascetic. These lines wiggle fast, and they’re not diffpairs, so you’ll want to lay them out with respect as single-ended wires. I’ll be writing up a larger SDIO article, but until then, do refer to one of the numerous SDIO layout tutorials online. Here’s a reference schematic:

A short SDIO layout recommendation: make sure there’s a continuous ground return path underneath, length-match between signals to the best of your ability (within 1 mm?), and overall keep the SDIO link as short as you possibly can. When wiring up SDIO coming from the 40-pin header on a Pi Zero or a full-sized Pi, some signals will need a lot of length-matching and some will need none at all – that’s normal, such is the Raspberry Pi GPIO pinout, just remember to match them. Include both series resistors and pullup resistors, as asked by the ESP-Hosted documentation.

Apart from the SDIO signals, you’ll want control over EN, so the driver can reset the ESP32 into a known-good state before starting communications. For that matter, you can also wire up EN to a classic RC circuit used for OLED displays, if you’re short on GPIOs and don’t mind – the driver wants EN supplied, but it doesn’t require-require it, you can just provide resetpin=-1 to the driver init script if you take care of EN switching on your own.

Example of single-sided layout of both pullup and series resistors at once

You don’t need to worry about the BOOT pin. You do need to make sure there’s sufficient 3.3 V power available, though: 300 mA to 400mA. The 3.3 V power rail on Raspberry Pi boards will generally be more than enough for powering your ESP32, but on other SBCs, you might end up adding an extra 3.3 V regulator to satiate the ESP32’s 3.3 V appetite. Last but not least, expose the ESP32 USB port somehow, because you’ll need it for flashing the firmware. Thankfully, the firmware flashing only needs to be done once. Personally, I put it on a 4-pin JST-SH with a QWIIC-like pinout, as you can see on the schematic above.

Build Firmware, Or Don’t

There are three things you need to do. Make sure your SBC’s SDIO (or SPI) interface is freed up, compile and flash your ESP32 firmware, then compile and load the driver. Not necessarily in this order, of course, but you need all three.

Freeing up the SDIO interface is relatively easy on Raspberry Pi: it’s a quick config.txt job. You only need to remap the SDIO pins, and if there’s an existing WiFi card, also disable its Bluetooth. The “Bluetooth disable” part is likely required because the onboard WiFi card’s firmware is uploaded over SDIO, so the Bluetooth part of the card wouldn’t function, anyway. It also frees up the UART console port on the Pi, which can be incredibly helpful if you need to debug your WiFi interface bringup! By the way, I have my doubts that the poll_once=off SDIO overlay parameter is required, and it does seem to spam up dmesg. If you ever need to get rid of that spam, removing that poll option might be a good start.

On other SBCs, you might struggle with SDIO, but as long as it is not too obscure, it shouldn’t be too big of a problem. If you’re rolling your own SBC, and if you have a devboard, feel free to wire up a microSD socket to the SDIO pins, add pullups as required, and debug your SDIO interface bringup using a spare microSD card. If a microSD card works, then in all likelihood, the ESP32 will work too.

ESP32 firmware compilation is also relatively easy. Maybe you don’t want to compile the ESP32 firmware on your SBC, since it might run out of RAM and lock up while executing cmake. On a Pi Zero, the lockup is basically guaranteed. Simply use your desktop computer to compile the firmware and avoid the hassle. Alternatively, you can skip all of that and download a firmware from the Releases tab on Github. Those are currently kept in the legacy repo, but I’m assuming eventually new releases will be put into the esp-hosted-linux repository, so look out.

Make sure that your driver is built from the same esp-hosted git repository version as your ESP32 firmware, using git log or the like to check the last commit. Otherwise, the driver will throw a warning and refuse to load, you can patch out that warning if you think the difference is too minor, but that’s at your own risk.

Drivers Done In Old-Fashioned Way

Now, the driver, you’ll want to compile the driver on the SBC itself, unless you cross-compile. The rpi_init.sh script compiles and loads the driver, and it also contains some notes you might find helpful. If you have an SBC with 512 MB of RAM or less – open the rpi_init.sh in the editor, find the make -j8 command, and replace it with make -j2 (or even -j1). Otherwise, your compilation process will run out of RAM and lock up your SBC.

Do you have everything connected by now? If you have SDIO properly configured and firmware has been flashed, the driver will just load successfully and a wlan interface will appear. Problems with that? Check dmesg to see the debug output of the driver module. I enjoy running dmesg -Hw in a spare terminal window, or just in the background.

Now, the rpi_init.sh script is a great tool for debugging, but it’s a tool you’ll want to shed when running the module longer-term, in large part because it recompiles the module every time it’s run. In the same directory, you’ll find esp_sdio.ko – that’s the Linux module you just compiled. Do this:

sudo cp esp_sdio.ko /lib/modules/uname -r/kernel/drivers>/code>
sudo depmod -a

It may be a hack, but at least now, you can modprobe esp_sdio, instead of insmod from the script directory. You can then also put the module name (esp_sdio) into /etc/modules to have it auto-load on every boot, which is way better than re-running the script and the associated recompile.

Workable And Very Promising

Forgot about pullups and had to improvise

There are some things to be desired, of course. The module should be properly integrated into device tree interfaces, for one, so that it doesn’t need to be added into /etc/modules and can instead be auto-loaded by an overlay. It also should get a dkms integration, in the same way the esp8089 driver was distributed. Currently, you have to recompile it and re-add the module into the kernel modules directory after every kernel upgrade, and dkms would cut that right out. Throughput is alright, you can get 40 Mbps to 50 Mbps at default SDIO frequency. If you think your hardware is good enough and can push SDIO limits further, there’s some dials and knobs you can tweak!

Cool Trick, But Why?

So why talk about this? There are four reasons that I find important. First, this is the only WiFi card I know that can pass Bluetooth through over SDIO instead of tying up a UART port, which is especially helpful for Pi Zero form-factor boards. That alone is pretty cool.

Second, while the code is imperfect and there is a heap of pull requests one should take a look at, esp-hosted does handle hardware power switches in my project! There are no kernel module crashes or failures as the ESP32 loses power, it disconnects and reconnects seamlessly, the hardware switch just works, and I find that endearing.

The next two reasons are both about this being an essentially open-firmware WiFi card. The ESP32 firmware isn’t fully open, as the RF bits are traditionally closed-source and get compiled in as blobs, but there have been some mighty projects trying to liberate the proprietary bits of the ESP32 WiFi stack. As more and more people get a stab at it, it’s entirely possible we could turn the omnipresent ESP32 modules into fully open-source firmware Linux WiFi cards, incredibly cheap and abundant anywhere, too. Truly hacker-friendly WiFi cards that last, what’s not to love?

The final reason is the most fun of all, and doesn’t even need the de-proprietarization. After SDIO wireup, the ESP32 is left with many free pins, including ones with high-speed SPI. Who’s to say that we can’t wire up a LoRa modem to it and run Meshtastic/Meshcore/etc.?  Since the firmware is mostly open, in theory, any code could be added within the WiFi/BT gaps, any meaningful data then forwarded to the Linux host. It also doesn’t escape my eye that new ESP32 chips support Zigbee and Thread natively, and exposing that to Linux is only a matter of code, too. To me, that’s the best part, thinking that one day we could turn the ESP32 into a true Swiss army knife communications co-processor for any Linux-running CPU.

Building a Pocket Wi-Fi Threat Detector

Welcome back, aspiring cyberwarriors!

Wireless security monitoring in the 2.4 GHz spectrum often depends on active probing, which can not only make the monitoring infrastructure vulnerable to attackers but also clutter the radio frequency environment. On the other hand, taking a passive approach by listening without transmitting allows security teams to detect malicious wireless activity more discreetly and reliably.

To put this idea into practice, the project Travel WiFi Canary was developed. This system serves as an early-warning mechanism using ESP32 microcontrollers. By operating the Wi-Fi radio in promiscuous mode, the device passively captures raw IEEE 802.11 management frames and traffic patterns. This helps identify potential threats such as deauthentication attacks, beacon spam, rogue access points often referred to as Evil Twins, and unauthorized probe requests. Eventually, it provides comprehensive insights into the wireless environment, enabling you to act proactively rather than reactively.

In this article, we will guide you through configuring, flashing, and running Travel WiFi Canary on the LilyGo T3 V1.6.1 development platform. Let’s get rolling!

What is Travel WiFi Canary?

The Travel WiFi Canary is a project that turns a low-cost ESP32 microcontroller into a passive 2.4 GHz threat-detection device. It operates continuously by alternating between active network enumeration and passive promiscuous packet capturing across specified channels.

At its core, the device’s Wi-Fi chip listens directly to raw radio signals passing through the air rather than connecting to a specific network.

When a wireless signal arrives, a fast automated responder checks the basic structure of the incoming data instantly. It identifies network management signals, such as connection requests, disconnection commands, or nearby network announcements, and separates them from standard web traffic.

To handle intense bursts of wireless activity without getting overwhelmed or missing crucial information, the chip places these flagged security signals into a temporary holding queue. This allows the main system to process and analyze the data safely in the background while keeping the hardware radio free to capture new incoming signals without interruption.

The central intelligence of the project relies on a dynamic confidence-scoring engine rather than rigid binary alerts. As the system processes the ring queues and periodic active scans, it evaluates detected anomalies against a local memory table built during the startup baseline phase.

Active scans check nearby Access Points for structural security violations. If an Access Point using an encrypted baseline protocol like WPA2 or WPA3 is detected operating without encryption, the system identifies an open clone attack. Security downgrades, unexpected vendor prefix mismatches on familiar SSIDs, or sudden disappearances of legitimate Access Points during an active open broadcast instantly contribute points to the global confidence score.

Simultaneously, the passive sniffer thread drains the lock-free queues to detect airborne attacks. Deauthentication frame floods are monitored over rolling time windows, assigning score penalties if threshold limits are breached by single sources or broadcast addresses.

The sniffer also inspects the payload fields inside beacon frames to detect Pwnagotchi signatures, parsing JSON structures hidden in vendor tags to determine if the device is operating in an active attack state.

All calculated points feed into a unified state machine. Aggregate scores between zero and two keep the device in a normal state, scores between three and five push it into a caution state, and scores of six or higher escalate the device into an active alert state.

To prevent temporary radio noise or brief packet anomalies from causing permanent alarm states, a background timer executes a score decay routine every minute. This routine gradually reduces the aggregate threat score over time, allowing the system to automatically transition back to a normal state once threat vectors clear the area. Hardware outputs, such as status LEDs or connected display controllers, continuously mirror the internal state variable to provide real-time visual monitoring.

What is LilyGo T3 V1.6.1?

The Travel WiFi Canary was initially made for the M5Stack Atom Lite development board. However, in this demonstration, I will test it on the LilyGo T3 V1.6.1.

The LilyGo T3 V1.6.1, also called the TTGO T3 LoRa32 V1.6.1, is an open-source development board designed for Internet of Things (IoT) projects and long-range RF communication. It has an ESP32 chip that allows for packet sniffing and Wi-Fi scanning. It gives us all the necessary functionality for wireless threat detection required by the Travel WiFi Canary project.

Getting Started with Travel WiFi Canary

The best way to flash the Travel WiFi Canary is by using Visual Studio Code along with the PlatformIO IDE extension. The installation process is fairly simple, so let’s move on to the next step, which is cloning the repository. I will use the modified version designed for the LilyGo T3 device. Here’s the command to do that:

kali> git clone https://github.com/AirClick-Code/esp32-wifi-canary.git

Next, connect your LilyGo T3 V1.6.1 to your computer using a data-capable Micro-USB cable. In Visual Studio Code, click on the PlatformIO status bar at the bottom and select env:esp32dev. Then, you can either click the checkmark icon in the status bar or press Ctrl+Alt+B to compile the firmware.

Once that is complete, click the right arrow icon in the status bar to start the upload process. PlatformIO will automatically detect the serial port, trigger the ESP32 to enter bootloader mode via auto-reset circuitry using the DTR and RTS lines, erase the necessary flash sectors, and upload the binaries seamlessly.

After the upload is complete, you can monitor the device with the built-in command:

pio device monitor -b 115200

At this point, the state machine and scanning engine are fully operational. During its initial scan, it detected seven nearby access points, recording their SSIDs, BSSIDs, signal strengths, channels, and encryption methods in memory.

Now, let’s simulate an open clone of a known encrypted network. The README file provides the following instructions:

I created a Wi-Fi access point from my phone with the same name as the network to which my system is connected, but without a password. Let’s observe how the WiFi Canary responds.

The script successfully identified the clone and granted 4 points to the score, changing the state to caution. The rogue open clone remained active in the following 20-second scan with a strong RSSI, adding another 4 points, which brought the total score to 8 and changed the state to alert. At the 310-second mark, the decay timer activated, decreasing the score from 8 to 7. However, since the score remained above the SCORE_ALERT threshold of 6 or higher, the system continued to maintain its alert state until the threat was resolved and the score naturally decayed back to zero.

Limitations

Despite the benefits of confidence scoring in reducing unexpected alerts, the possibility of false positives still exists. This is particularly true in enterprise networks, multi-node mesh setups, and crowded public venues, which can display behaviors that resemble attack patterns. On the flip side, false negatives may arise if a skilled attacker impersonates a legitimate BSSID while carefully adjusting their transmission power to fit in with normal signal strength variations, thus evading detection.

The limitations of the physical hardware create additional coverage boundaries. Passive detection of deauthentication relies heavily on the distance from the receiving device, meaning that low-power or far-off transmitters may be beyond the reach of the antenna. Furthermore, monitoring is confined solely to the 2.4 GHz spectrum, leaving the 5 GHz and 6 GHz bands completely unmonitored.

Lastly, the design of the radio architecture leads to a temporary gap in scanning whenever the chip switches between promiscuous packet sniffing and active environment scanning, resulting in a three-second blind spot where airborne deauthentication bursts can go unnoticed.

Summary

For many travelers and remote workers, understanding whether the Wi-Fi around them is secure is crucial. Private messages and sensitive information can be easily compromised when malicious actors set up fake hotspots or disrupt local connections. A device like the Travel WiFi Canary can continuously monitor the airwaves and alert you the moment a wireless attack is detected.

This device uses active Wi-Fi scanning and passive signal listening to find threats in real time. It constantly checks nearby networks against a trusted standard to spot fake open hotspots, duplicate routers, or security issues. At the same time, it listens for harmful activities like deauthentication attacks or rogue scanning tools. When it detects a threat, it raises a danger level with an internal scoring system and triggers a clear visual alarm. This alerts you immediately, giving you a warning before your devices may face any risk.

If you’re interested in improving your knowledge of wireless security, take a look at our Wi-Fi Hacking training. This course will guide you on how to assess the security of wireless networks and equip you with modern strategies to protect them effectively.

The post Building a Pocket Wi-Fi Threat Detector first appeared on Hackers Arise.

SDR (Signals Intelligence) for Hackers: Tracking People with ESP32-Paxcounter

Welcome back, aspiring cyberwarriors!

Lately, we’ve covered several tools you can use with your laptop to track nearby devices and people. While they’re useful, their effectiveness depends on the strength of your Bluetooth adapter, and, of course, you need to have your laptop with you.

This time, we’re doing things differently. We want to show you a device that can automatically monitor nearby devices for extended periods, anywhere you choose to place it, and as often as you want. It doesn’t rely solely on Bluetooth, as it also uses Wi-Fi, which is far more likely to be enabled, increasing the chances of detecting someone in your area.

What is Paxcounter

Paxcounter is an open-source firmware project that takes a cheap little ESP32 development board and turns it into a sensor that can count people. Almost every smartphone in the world is constantly sending out small Wi-Fi signals, called probe requests, and Bluetooth signals too, even when the phone is not connected to anything. Paxcounter listens for these signals in the air. It counts how many different devices it hears during each scan, and from that, it can tell you a real time estimate of how many people are nearby.

The project started out as a simple way to measure how many passengers or pedestrians pass through a certain spot. But over time, it grew into something much bigger. Now it works as a general purpose IoT platform, built on hardware that usually costs somewhere between $10 and $30. Besides its main job of counting Wi-Fi and Bluetooth devices, a Paxcounter can also read environmental sensors, track its GPS position, keep accurate time, and send all of that data out through LoRaWAN, MQTT, a local serial connection, or straight onto an SD card. 

How the Counting Works

The way Paxcounter counts people is simple, but it was clearly built with privacy in mind from the very start. Every scan cycle, which lasts 60 seconds by default, the device switches its Wi-Fi and Bluetooth radios into scanning mode and listens for probe requests and advertisement packets coming from nearby devices. Each of these packets carries a MAC address. Paxcounter takes just the last two bytes of that address and turns them into a short, temporary ID. This ID is only used to check for duplicates during that one scan cycle. Once the cycle ends, the count of unique IDs gets sent out, and the whole list is wiped from memory. The firmware also does not try to fingerprint any device. It never tries to figure out a phone’s brand, its operating system, or who owns it. All it wants to know is whether that device has already been counted in the current window.

paxcounter

This scan and clear cycle just keeps repeating, either nonstop or on a schedule if deep sleep power saving is turned on. The results, which include the Wi-Fi count, the Bluetooth count, and sometimes live sensor readings too, get packed into a small payload and sent out through whatever channel the device is set up to use. One thing worth knowing is that Wi-Fi and Bluetooth scanning actually share the same 2.4 GHz radio hardware on the ESP32. So running both scans at the same time slightly lowers the accuracy of each one. Because of that, the project’s own advice is to split Wi-Fi only counting and Bluetooth only counting across two separate devices whenever the best possible accuracy is needed for both.

One Firmware, Many Boards

Paxcounter comes with a hardware abstraction layer and its own pin mapping files for dozens of ESP32 and ESP32-S3 boards. These come from well known manufacturers like LILYGO and TTGO, Heltec, Pycom, WeMos, M5Stack, and Adafruit, and there is also a generic template ready for boards that are not officially supported yet. LILYGO even sells a ready-made board called Paxcounter LoRa, built specifically to run this firmware. 

lilygo paxcounter

Depending on which board you pick, your device can end up supporting a LoRaWAN radio for sending data over long distances while using very little power, an OLED status screen, or a single color, RGB, or larger LED matrix light to show status. It can also support a physical button for flipping through display pages or sending an alarm message, battery voltage monitoring, GPS positioning, a real time clock chip along with IF482 or DCF77 time telegram output, and even an SD card slot for logging data locally when there is no network around.

Because the whole system was designed to be truly portable, the documentation goes into real detail about power draw, which usually sits somewhere between 450 and 1000 milliwatts depending on how the device is set up. It also makes good use of the ESP32’s deep sleep mode, so a device can keep running for a long stretch of time on just one 18650 lithium ion battery cell. Members of the community have already shared several 3D printable enclosure designs on Thingiverse for the more popular boards.

3d printed enclosure

Getting the Device Up and Running

Paxcounter is built using PlatformIO instead of the plain Arduino IDE. This choice lets it work smoothly with editors like Visual Studio Code, Atom, or Eclipse, and it gives the project reproducible, script driven builds. In fact, the repository runs an automated PlatformIO build check every single time the code changes, using GitHub Actions, and there is even a CodeFactor badge that keeps an eye on ongoing code quality.

The configuration is intentionally spread across a handful of different files instead of being crammed into just one. This keeps board specific settings, behavioral settings, and personal settings nicely separated from each other. The platformio.ini file is where you select which board’s hardware profile you want to compile against. The paxcounter.conf file handles behavioral settings, things like how long a scan cycle lasts, sleep timing, and payload options. The shared lmic_config.h file sets the LoRaWAN region and frequency plan, so it matches the rules where you live. The shared loraconf.h file holds the device’s LoRaWAN join credentials, and the project recommends using OTAA rather than ABP for this. And the shared ota.conf file stores the Wi-Fi credentials the device uses for over the air firmware updates.

You can upload firmware the traditional way, over USB, or once a device has joined a LoRaWAN network, you can push updates over the air instead. A remote command tells the board to connect to Wi-Fi, check a hosted repository called PAX.express for a newer build, and then download and flash it automatically. If anything goes wrong during that process, it will roll back to the previous version on its own. Devices can also be set up to open a small local web based bootstrap menu right when they power on, which lets you upload a firmware file manually, even from a phone in tethering mode, without needing PlatformIO installed on site.

Configuration and Extensibility

Beyond just picking a board, Paxcounter gives you a long list of settings you can tune to fit your needs. It can log environmental data from sensors like the Bosch BMP180, BME280, BMP280, or BME680, read a Nova SDS011 particulate matter sensor to track dust in the air, and keep accurate time using either a DS3231 real time clock or a connected GPS module. 

extensions

Display and LED

On boards that come with an OLED display, Paxcounter shows live status information you can cycle through with a short press of the button. This includes the current pax count, meaning the people count, a histogram of recent activity, GPS status, environmental sensor readings, and the time of day. 

display

A long press of that same button sends an alarm message out over the network instead, which is a simple way to flag a problem from out in the field without needing any other kind of interface. Even on boards that do not have a display at all, a status LED still tells you what the device is doing through its blink pattern. You get a brief flash whenever a new Wi-Fi or Bluetooth device is spotted, a quick blink while the device is joining the LoRaWAN network, a short blink during data transmission, and a slow, long blink if there is a LoRaWAN stack error. Boards that have an RGB LED get a color coded version of these same signals.

led

How You Receive the Data

Once a Paxcounter has counted the people nearby and packed everything into a message, that data has to go somewhere so you can actually see it. How that happens depends on which output the device is using, and the good news is you can turn on more than one at the same time. If you are using LoRaWAN, which is the most common setup, the device does not send the data straight to you. Instead, a nearby LoRaWAN gateway picks up the signal first and forwards it on to a network server, usually The Things Stack. There is a small decoder script included with the project, and its job is to take that raw message and turn it into numbers you can actually read, something like a pax count of 14. From there, The Things Stack can pass the data along to your own app or dashboard using MQTT or a webhook, or you can simply watch it come in live through the built in console.

If a board does not have LoRa hardware built in, it can just skip the gateway completely and send that same kind of data straight to an MQTT service over Wi-Fi instead. You can also connect the device to a computer using a USB cable and read the numbers directly from a serial connection. This is a simple way to test things out without needing to set up a network at all. If SD card logging is turned on, everything also gets saved locally as a CSV file, so you can pull the card out later and open it up in a spreadsheet. This comes in handy in places where there is no network coverage to rely on. 

Where It’s Used

Because a single Paxcounter device is cheap to build and can be left running unattended for a long time, you will find it popping up in a pretty wide range of places. Retailers and shopping centers use it to measure foot traffic without needing to install cameras. Event organizers use it to watch how crowds move around a venue in real time. Pentesters can get a passive read on how many Wi-Fi and Bluetooth devices are active in a building, or to notice unexpected devices showing up where they shouldn’t, all without needing camera access or network credentials.

Legal and Privacy Considerations

Since Paxcounter’s whole job involves listening to wireless traffic, its documentation is unusually upfront about the legal side of things. It points out that sniffing Wi-Fi and Bluetooth MAC addresses may be regulated or restricted depending on where you live, and it links to specific starting references for the US, the UK, the Netherlands and the EU, and Germany. It also makes clear that the legal responsibility for how a device is built and deployed falls on the person doing it, especially for public deployments where the results might get published somewhere. On the technical side of privacy, the project’s own design actually holds up pretty well against that legal backdrop. Identifiers are only ever built from the last two bytes of a scanned MAC address, they are kept in memory just for the length of one scan cycle, and then they are discarded completely. No MAC addresses or identifiers are ever sent out over the network, and the firmware does not do any extra tracking or fingerprinting of the devices it scans.

Summary

What really makes Paxcounter stand out is not any single feature on its own. It is the whole combination working together. One piece of open source firmware supports dozens of cheap boards, runs for a long time on a small battery, counts people without saving anything identifying about them, doubles as a general environmental sensor node, speaks LoRaWAN, MQTT, serial, and SD card all at once, and can be fully reconfigured from a distance once it is out in the field. The full source code, the complete board list, and all the documentation are available on GitHub.

If you enjoy experimenting with frequencies and trying new things, we recommend signing up for our SDR for Hackers training. With Master OTW, you’ll learn how to use your computer and inexpensive SDR hardware to explore and hack a wide range of radio signals.

The post SDR (Signals Intelligence) for Hackers: Tracking People with ESP32-Paxcounter first appeared on Hackers Arise.

❌