A Raspberry Pi Pico-based FM radio controller using the TEA5767 FM radio module.
The project was developed on Pimoroni Tiny2040 but it is compatible with any RP2040-based board, including:
- Raspberry Pi Pico / Pico W
- Pimoroni Tiny2040
- Adafruit Feather RP2040
- Sparkfun Pro Micro RP2040
- And others
The project is built with the official Raspberry Pi Pico VSCode extension.
- Scanning across the FM band (87.5 – 108.0 MHz), re-scan with a button
- Persistent station storage, selected station in flash (survives power cycles)
- Cycle through found stations with a button
- Change the frequency manually via potentiometer
- I2C communication with TEA5767 module
- Signal strength and stereo detection for reliable station identification
- UART output for debugging and station information
- RP2040-based board
- TEA5767 FM radio module
- Button for next station
- Button for scanning
- Appropriate audio output (speaker/headphones connected to TEA5767)
- (Optional) Potentiometer (connected to ADC pin) for manual tuning
Important considerations when selecting a board:
-
Pin Availability: Ensure your board has the required pins accessible:
- 2 GPIO pins for I2C (SDA/SCL)
- 1 ADC-capable GPIO pin (must be GPIO26-29 on RP2040)
- 2 GPIO pins for buttons
- (Optional) Pins for UART if you want debug output
-
ADC Pin Requirement: The potentiometer must be connected to an ADC-capable pin. On RP2040, only GPIOS 26–29 have ADC functionality (labeled ADC0-ADC3).
-
Flash Size: The project stores station data in the last sector of flash. All RP2040 boards (2MB to 16MB flash) are supported as the code automatically adapts to the available flash size.
-
Form Factor: Smaller boards like the Tiny2040 may be more convenient for compact or portable FM radio builds.
All pin assignments are configurable at build time, making it easy to adapt to your specific board's layout.
For input, USB connection (5V) is recommended for most use cases. You can power the radio module with the 3V3 pin.
Default GPIO assignments (active-low buttons with internal pull-ups):
| Function | GPIO Pin | CMake Variable |
|---|---|---|
| I2C SDA | 4 | PIN_SDA |
| I2C SCL | 5 | PIN_SCL |
| ADC Input (Potentiometer) | 26 (ADC0) | ADC_PIN |
| Next Station Button | 2 | NEXT_STATION_PIN |
| Scan Stations Button | 3 | SCAN_STATIONS_PIN |
All pins can be overridden at build time, see CMakeLists.txt.
Note: When using boards other than the standard Raspberry Pi Pico, verify that your chosen GPIO pins are physically accessible on your board and that your ADC pin is one of GPIO26-29.
Quick Start: A prebuilt binary (pico-fm-radio.uf2) with default pin assignments is included in the repository. You can flash it directly to your board without building if the default pins work for your setup.
- Ensure the Pico SDK is installed and
PICO_SDK_PATHis set - Create a build directory and compile:
mkdir build
cd build
cmake ..
ninja- To use custom pin assignments, pass them as CMake cache variables:
cmake .. -DPIN_SDA=8 -DPIN_SCL=9 -DNEXT_STATION_PIN=10- Flash the
.uf2file to your board:- Use the prebuilt
pico-fm-radio.uf2from the repository root, or - Use your compiled version from
build/pico-fm-radio.uf2 - Hold the BOOTSEL button while connecting USB
- Copy the
.uf2file to the mounted drive
- Use the prebuilt
- On startup the previously saved stations are restored; if none are found it performs a scan
- Found stations (up to 30) and the current station are persisted
- Press the next-station button to cycle through saved stations
- Press the scan button to re-scan the FM band
- (Optional) Turn the potentiometer to manually tune to any frequency
- (Optional) Monitor UART output (115200 baud) for debug prints
Key parameters can be adjusted in the source code:
SCAN_SIGNAL_THRESHOLD: Minimum signal strength for station detection (default: 9)MAX_STATIONS: Maximum number of stations to store (default: 30)FM_BAND_MIN/FM_BAND_MAX: FM band range (default: 87.5 – 108.0 MHz)FM_SNAP_GRID_KHZ: Manual tuning grid resolution (default: 50 kHz)
MIT License
