Wiznet makers

Grace_Koo

Published May 21, 2026 ©

71 UCC

25 WCC

11 VAR

0 Contests

0 Followers

0 Following

Original Link

auto-dj-arduino-switch

Arduino Giga R1 + WIZnet W5500 that automatically logs auto DJ tracks into a college radio station's copyright flowsheet over HTTPS.

COMPONENTS
PROJECT DESCRIPTION

Why a College Radio Station Is Replacing Wi-Fi with W5500 — Auto DJ Arduino Switch

In One Sentence

"An Arduino + W5500 system that automatically logs every track played by the auto DJ into the station's copyright flowsheet — so no one has to do it manually."

WXYC (89.3 FM), the student-run radio station at the University of North Carolina at Chapel Hill, put an Arduino into its live broadcast infrastructure. When no DJ is on air, the auto DJ software plays music automatically — but those tracks weren't being logged. The Arduino detects when the auto DJ is active via a relay contact on the mixing board, polls for the currently playing track, and writes each entry into the station's flowsheet (playback log).

It started on Wi-Fi. Three real-world problems pushed the project toward Arduino Ethernet Shield Rev2 (WIZnet W5500) as the primary transport.


Background

What is a flowsheet? A radio station's playback log. Stations are required to record what was played and when, for copyright reporting and broadcast history. Live DJs log entries manually — but when the auto DJ is running with no one logged in, those tracks go unrecorded. This device fills that gap.

What is AzuraCast? Open-source web radio management software. It runs the auto DJ and exposes currently-playing track data via a REST API and a real-time Centrifugo WebSocket.


The Three Wi-Fi Problems

Problem 1: The campus Wi-Fi password changes every year

UNC rotates its Wi-Fi password (UNC-PSK) annually. When Wi-Fi is the only network transport, a password change takes the device offline — and someone has to physically walk to the studio, connect via USB, and reflash the firmware to restore it.

[Wi-Fi only]
  UNC rotates password → Arduino loses Wi-Fi → no network → physical visit required

[After W5500]
  UNC rotates password → Wi-Fi fallback breaks → Ethernet stays up
                       → push new password over Ethernet → Wi-Fi restored

Problem 2: Wi-Fi reconnection blocks for up to 36 seconds

This is a known firmware bug in the Arduino Giga R1. When the Wi-Fi connection drops, WiFi.begin() blocks execution for up to 36 seconds while attempting to reconnect. During that window, the state machine is completely frozen — any track changes that happen go unlogged.

The README's Known Limitations section states this explicitly:

"WiFi reconnection blocks for ~36 seconds (known Giga R1 firmware limitation). During this time, the state machine is frozen."

The W5500 has a hardwired TCP/IP stack. With an Ethernet cable plugged in, reconnection is near-instant and non-blocking.

Problem 3: A WiFiSSLClient crash bug forces a structurally limiting workaround

Using a global WiFiSSLClient object crashes the Giga R1. The current code works around this by creating a new WiFiSSLClient for every HTTP request and destroying it immediately after.

// Current workaround — create and destroy on every request
case AUTO_DJ_ACTIVE:
    if (...) {
        WiFiSSLClient ssl;  // created here
        inputs.pollNewTrack = azuracast.poll(ssl);
        // ssl destroyed here
    }

This makes persistent WebSocket connections impossible over Wi-Fi. AzuraCast supports real-time push via Centrifugo WebSocket, but the current Wi-Fi transport can't use it — so the device is stuck polling every 20 seconds. With W5500, a persistent WebSocket connection becomes viable and track changes can be detected in real time.


What's Running Today

The W5500 Ethernet code hasn't been implemented yet, but the Wi-Fi-based core logic is fully operational.

Flow:

Mixing board AUX relay closes (D2 LOW)
    ↓
STARTING_SHOW: POST to tubafrenzy to open a new show
    ↓
AUTO_DJ_ACTIVE: poll AzuraCast every 20s (HTTPS GET)
    ↓ new track detected
Add flowsheet entry (HTTPS POST)
    ↓
Relay opens → ENDING_SHOW: close the show

All state transition logic lives in a pure function — tick(Context, Inputs) → TickResult — with no I/O or side effects. This makes the entire decision logic testable on desktop without any hardware. 82 GoogleTest tests run on every push via GitHub Actions CI.

ModuleTests
state_machine (pure transition logic)32
utils (URL encoding, time calculations)19
relay_monitor (debouncing)12
flowsheet_client (HTTP POST)10
azuracast_client (HTTP GET + JSON parsing)9

What Changes After the W5500 Switch

The planned architecture is fully documented in networking-spec.md:

 Current (Wi-Fi)After W5500
Track detectionPoll AzuraCast every 20sReal-time push via Centrifugo WebSocket
Management channelNonePersistent WebSocket (remote monitoring, commands)
Credential rotationPhysical visit requiredPush over Ethernet remotely
Reconnection delayUp to 36s blockingNear-instant
Wi-FiPrimary transportFallback only

Tech Stack

ComponentDetails
MCUArduino Giga R1 WiFi (STM32H747, Cortex-M7 480MHz)
EthernetWIZnet W5500 (Arduino Ethernet Shield Rev2)
FirmwareC++ (Arduino / Mbed OS)
External APIsAzuraCast Now Playing API, tubafrenzy Flowsheet API
Testing82 GoogleTest cases, desktop CI, no hardware required

FAQ

Q. The Ethernet code isn't implemented yet — why was the hardware added first? A. The 3D-printed enclosure was designed with cutouts for the Ethernet Shield Rev2's RJ45 port and SD card slot from the start. Hardware preparation and software implementation are running in parallel.

Q. Why keep Wi-Fi at all instead of dropping it entirely? A. As a fallback for when the Ethernet cable is unplugged or the campus wired port goes down. As long as at least one transport is up, broadcast logging continues. The only scenario that requires physical intervention is both transports failing simultaneously.

Q. Why is the state machine a pure function? A. To make the entire transition logic testable on desktop without hardware. The tick(Context, Inputs) → TickResult structure lets 32 state machine tests run in CI with no Arduino attached. Separating I/O from logic is the core design principle of the project.


Project Links

Documents
Comments Write