<!--order=7-->


<h1>Flashing Meshtastic Firmware on the Raspberry Pi Pico</h1>
<p>The Raspberry Pi Pico (RP2040) is a supported Meshtastic platform. Combined with a Waveshare SX1262 LoRa module, it becomes a capable Meshtastic node — cheaper than purpose-built options like the T-Beam, and hackable in ways that dedicated Meshtastic hardware isn't. This covers getting the firmware onto the Pico and configuring it for your network.</p>

<h2>What You Need</h2>

<table>
  <thead><tr><th>Item</th><th>Notes</th></tr></thead>
  <tbody>
    <tr><td>Raspberry Pi Pico / Pico W</td><td>RP2040 generation. The W adds WiFi/Bluetooth, but either board can use USB serial with the Pi.</td></tr>
    <tr><td>Raspberry Pi Pico 2 / Pico 2 W</td><td>RP2350 generation. Use them only with a Meshtastic release that explicitly supports the RP2350 target and the attached radio.</td></tr>
    <tr><td>Waveshare Pico-LoRa-SX1262</td><td>915MHz for North America; plugs onto the Pico header</td></tr>
    <tr><td>Antenna</td><td>915MHz antenna — included with Waveshare module; external omni improves range</td></tr>
    <tr><td>USB cable</td><td>Micro-USB for the Pico</td></tr>
    <tr><td>Linux/Mac/Windows host</td><td>For flashing and initial configuration</td></tr>
  </tbody>
</table>

<h2>Know Which Pico You Have</h2>
<table>
  <thead><tr><th>Board marking</th><th>MCU family</th><th>Wireless</th><th>Firmware question</th></tr></thead>
  <tbody>
    <tr><td>Pico</td><td>RP2040</td><td>None</td><td>Look for an RP2040 Waveshare/Pico SX1262 target</td></tr>
    <tr><td>Pico W</td><td>RP2040</td><td>WiFi/Bluetooth</td><td>Confirm the release target includes the W features you need</td></tr>
    <tr><td>Pico 2</td><td>RP2350</td><td>None</td><td>Do not use an RP2040 UF2; find an explicit RP2350 target</td></tr>
    <tr><td>Pico 2 W</td><td>RP2350</td><td>WiFi/Bluetooth</td><td>Find an explicit RP2350/W target if wireless is required</td></tr>
  </tbody>
</table>
<p>The <code>W</code> suffix describes connectivity, not the LoRa radio. The <code>2</code> describes the newer microcontroller generation. Read the board silkscreen and the firmware release target before flashing.</p>

<h2>Downloading the Firmware</h2>
<pre>
Meshtastic firmware for RP2040 is on the Meshtastic firmware releases page:
https://github.com/meshtastic/firmware/releases

Look for the file named:
  firmware-rp2040-waveshare-pico-lora-sx1262-x.x.x.uf2

The filename encodes the target hardware:
  rp2040          = RP2040 microcontroller (Pico)
  waveshare-pico  = the Waveshare form factor
  lora-sx1262     = SX1262 radio chip (915/868MHz)

If you have the SX1268 variant (433/470MHz), look for:
  firmware-rp2040-waveshare-pico-lora-sx1268-x.x.x.uf2

Download the latest stable release (not a pre-release) for field use.
</pre>
<p>Those RP2040 filenames are examples for the original Pico generation. Pico 2 and Pico 2 W need an RP2350-targeted release asset when one is provided. Firmware filenames and supported board targets change over time, so match the release asset to the MCU, wireless variant, radio chip, and exact Waveshare board—not just the word “Pico.” Before a field update, save the current version and export the configuration from a known-good node.</p>

<h2>Pre-Flash Checklist</h2>
<ul>
  <li>Confirm the target is an RP2040 board and identify the SX1262 or SX1268 radio variant.</li>
  <li>Connect the correct regional antenna before the new firmware is allowed to transmit.</li>
  <li>Use a data-capable USB cable; many charge-only cables cause unnecessary flashing trouble.</li>
  <li>Keep a copy of the firmware file and its release notes with the deployment record.</li>
  <li>Export the old configuration when updating an existing node.</li>
</ul>

<h2>Flashing the Pico</h2>
<pre>
1. Hold the BOOTSEL button on the Pico
2. While holding BOOTSEL, plug in the USB cable
3. The Pico appears as a mass storage device (RPI-RP2)
4. Release BOOTSEL

$ ls /media/$USER/RPI-RP2/   # should show the drive

5. Copy the .uf2 file to the drive:
$ cp firmware-rp2040-waveshare-pico-lora-sx1262-2.5.x.uf2 /media/$USER/RPI-RP2/

The Pico reboots automatically and Meshtastic starts running.
The drive disappears — that's normal.

# On macOS:
$ cp firmware-*.uf2 /Volumes/RPI-RP2/

# Verify it's running — the Pico should appear as a serial device:
$ ls /dev/tty.usbmodem*   # macOS
$ ls /dev/ttyACM*          # Linux
</pre>

<h2>Initial Configuration via Python CLI</h2>
<pre>
# On a Debian or Raspberry Pi host, keep the CLI in a virtual environment
$ python3 -m venv ~/meshtastic-cli
$ . ~/meshtastic-cli/bin/activate
$ python -m pip install --upgrade pip meshtastic

# Connect and check the node
$ meshtastic --port /dev/ttyACM0 --info

# If the port isn't found, try:
$ meshtastic --info    # auto-detect (works via USB or Bluetooth)

# Expected output — something like:
# Nodes in mesh:
# {'num': 1234567890, 'user': {'id': '!abcd1234', 'longName': 'Meshtastic abcd', ...}}
</pre>
<p>Wireless support does not remove the need for USB during first setup. A plain Pico uses USB serial, while a W board may additionally offer Bluetooth or WiFi if the installed firmware exposes those features. For a Pi gateway, USB is usually the simplest and most predictable management path.</p>
<p>If the serial device is not accessible, add the user to the appropriate serial-access group, then sign out and back in. Do not solve a permission problem by running every Meshtastic command as root.</p>

<h2>Essential Configuration</h2>
<pre>
# Set a useful node name
$ meshtastic --port /dev/ttyACM0 \
    --set-owner "Field Node 1" \
    --set-owner-short "FN1"

# Set the region (REQUIRED for legal operation)
$ meshtastic --port /dev/ttyACM0 --set lora.region CA_915
# Region codes: CA_915 (Canada), US (USA), EU_868 (Europe), AU_915 (Australia)
# Without setting a region, the node won't transmit.

# Set the modem preset
$ meshtastic --port /dev/ttyACM0 --set lora.modem_preset LONG_FAST
# Options: LONG_FAST, LONG_SLOW, LONG_MODERATE, MEDIUM_SLOW, SHORT_SLOW, SHORT_FAST

# Verify configuration
$ meshtastic --port /dev/ttyACM0 --info
</pre>
<p>CLI option names can change between Meshtastic releases. Treat the commands as a workflow rather than a copy-and-paste contract: use <code>meshtastic --help</code> and export the resulting configuration to verify each setting on the installed version.</p>

<h2>Channel Configuration</h2>
<pre>
# View current channels
$ meshtastic --port /dev/ttyACM0 --info

# Set a private channel with custom key (all nodes must use the same key)
$ meshtastic --port /dev/ttyACM0 --ch-set name "FieldNet" --ch-index 0
$ meshtastic --port /dev/ttyACM0 --ch-set psk random --ch-index 0
# Save the output key — you'll need it for every node on the network

# Or set a specific key (must be base64-encoded, 16 or 32 bytes):
$ meshtastic --port /dev/ttyACM0 --ch-set psk "BASE64KEYHERE==" --ch-index 0

# Export the full channel config to share with other nodes:
$ meshtastic --port /dev/ttyACM0 --qr     # generates a QR code URL
# Share the URL — other nodes scan with the phone app to join your channel
</pre>

<h2>Configuring Telemetry</h2>
<pre>
# Set how often telemetry is broadcast (seconds)
$ meshtastic --port /dev/ttyACM0 \
    --set telemetry.device_update_interval 300    # every 5 minutes

# Enable environment telemetry (for connected sensors like BME280)
$ meshtastic --port /dev/ttyACM0 \
    --set telemetry.environment_measurement_enabled true \
    --set telemetry.environment_update_interval 600   # every 10 minutes

# Set position broadcast interval
$ meshtastic --port /dev/ttyACM0 \
    --set position.position_broadcast_secs 600    # 10 minutes
</pre>

<h2>Checking Node Status</h2>
<pre>
# List all nodes the mesh knows about
$ meshtastic --port /dev/ttyACM0 --nodes

# Send a test message (appears on all nodes in the channel)
$ meshtastic --port /dev/ttyACM0 --sendtext "Node 1 online"

# Monitor incoming messages
$ meshtastic --port /dev/ttyACM0 --listen

# Export full config (useful for backing up before changes)
$ meshtastic --port /dev/ttyACM0 --export-config > node1-config.yaml
</pre>
<p>Run the test from both ends of the link. A message that leaves the USB-connected node proves very little unless a second node receives it with the intended channel, preset, and antenna.</p>

<h2>Pico W — WiFi and MQTT</h2>
<pre>
# If using the Pico W (not the plain Pico), you can configure WiFi
# and MQTT for internet bridging:

$ meshtastic --port /dev/ttyACM0 \
    --set network.wifi_ssid "YourSSID" \
    --set network.wifi_psk "yourpassword" \
    --set network.wifi_enabled true

$ meshtastic --port /dev/ttyACM0 \
    --set mqtt.address "broker.hivemq.com" \
    --set mqtt.enabled true \
    --set mqtt.json_enabled true   # outputs JSON — easier to parse

# After rebooting, the node bridges mesh traffic to MQTT
# and can be managed via the Meshtastic web UI on its IP address.
</pre>

<h2>Troubleshooting</h2>

<table>
  <thead><tr><th>Problem</th><th>Likely cause</th><th>Fix</th></tr></thead>
  <tbody>
    <tr><td>Node won't transmit</td><td>Region not set</td><td><code>--set lora.region CA_915</code></td></tr>
    <tr><td>Can't see other nodes</td><td>Mismatched modem preset or channel key</td><td>Verify all nodes use same preset and key</td></tr>
    <tr><td>Port not found</td><td>Driver issue or wrong port</td><td><code>ls /dev/ttyACM*</code> or install CH340 driver</td></tr>
    <tr><td>Python CLI errors</td><td>Old meshtastic version</td><td><code>pip3 install --upgrade meshtastic</code></td></tr>
    <tr><td>Radio not initialising</td><td>Wrong firmware variant</td><td>Confirm you flashed the sx1262 variant (not sx1276 or sx1268)</td></tr>
  </tbody>
</table>

<h2>Configuration Backup and Recovery</h2>
<pre>
# After a clean working setup, save a versioned backup:
$ meshtastic --port /dev/ttyACM0 --export-config \
  > field-node-01-config.yaml

# Keep the backup and a note containing:
# - firmware release
# - board / radio variant
# - regional setting
# - channel configuration method
# - antenna type
</pre>
<p>Keep channel keys out of public repositories and screenshots. A configuration backup is most valuable when it can restore a replacement node without exposing the private network to everyone who reads the article.</p>

<h2>References</h2>
<ul>
  <li><a href="https://meshtastic.org/docs/getting-started/flashing-firmware/" target="_blank" rel="noopener">Meshtastic — Flashing Firmware ↗</a></li>
  <li><a href="https://meshtastic.org/docs/software/python/cli/" target="_blank" rel="noopener">Meshtastic Python CLI Docs ↗</a></li>
  <li><a href="https://github.com/meshtastic/firmware/releases" target="_blank" rel="noopener">Meshtastic Firmware Releases ↗</a></li>
</ul>
