Raspberry Pi Pico and 433MHz Data Radio

Well its been a minute since I’ve toyed around with electronics, but a $4 Raspberry Pi Pico board arriving in the mail changed that.

This board packs a boat load of utility for $4, just check out the data sheet and check out all them I2C and SPI pins!

I dusted off the last components I tinkered with, along with a handful of wires. After a couple days of tinkering, I ended up with a 433MHz radio packet receiver.

  • micro controller
  • radio module
  • display module
  • Simple push button switches

With this setup I can listen on all them 433MHz radio frequencies; for example, I have another RFM69 broadcasting unencrypted messages at 433.0MHZ using CircuitPython & a Trinket M0 :

import time
import board
import busio
import digitalio
import adafruit_rfm69

FREQ = 433.0

spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)

cs = digitalio.DigitalInOut(board.D1)
reset = digitalio.DigitalInOut(board.D0)

rfm69 = adafruit_rfm69.RFM69(spi, cs, reset, FREQ)

# keep message length 21 characters or lower,
# and stay at 3 lines or under
messages = [
'''Welcome to
nessy radio!
''',
'''The passcode is:
slippery panda
''',
]

counter = 0
while True:
    for message in messages:
        rfm69.frequency_mhz = FREQ
        rfm69.tx_power = 20
        rfm69.send(message)
        print('%s - sent %s' % (message, counter))
        time.sleep(5)
        counter = counter + 1

This code merely broadcast our messages, one at a time every 5 seconds:

# keep message length 21 characters or lower,
# and stay at 3 lines or under
messages = [
'''Welcome to
nessy radio!
''',
'''The passcode is:
slippery panda
''',
]

Using the Raspberry Pi Pico and a USB battery I’m able to pick up the data packets anywhere in my house!

According to Adafruit, the range for the RFM69:

Range of approx. 500 meters, depending on obstructions, frequency, antenna and power output

That means I should my Raspberry Pi Pico setup should be able to receive this message within 1640.42 feet!? Wow, I’ll need to test this.

Any ways, here is the code I ended up demoing on the Pico, happy hacking, and happy Pi day ;)

import time
import board
import busio
import digitalio

import adafruit_ssd1306
import adafruit_rfm69

# basic on board led
led = digitalio.DigitalInOut(board.LED)
led.direction = digitalio.Direction.OUTPUT
led.value = False  # turn off led

# buttons
button_left = digitalio.DigitalInOut(board.GP20)
button_left.switch_to_input(pull=digitalio.Pull.DOWN)
button_right = digitalio.DigitalInOut(board.GP21)
button_right.switch_to_input(pull=digitalio.Pull.DOWN)
button_go = digitalio.DigitalInOut(board.GP13)
button_go.switch_to_input(pull=digitalio.Pull.DOWN)

# i2c oled display
i2c = busio.I2C(scl=board.GP15, sda=board.GP14)
display = adafruit_ssd1306.SSD1306_I2C(128, 64, i2c, addr=0x3d)
display.fill(0)
display.show()

# radio
FREQ = 433.0
spi = busio.SPI(board.GP2, MOSI=board.GP3, MISO=board.GP0)
cs = digitalio.DigitalInOut(board.GP1)
reset = digitalio.DigitalInOut(board.GP4)
rfm69 = adafruit_rfm69.RFM69(spi, cs, reset, FREQ)

# uncomment to enable encryption
# rfm69.encryption_key = (
#     b"\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08"
# )

listen = False
count = 0
msg = ''
while True:

    if not listen:
        if button_left.value:
            FREQ = round(FREQ + 0.1, 1)
            rfm69.frequency_mhz = FREQ

        if button_right.value:
            FREQ = round(FREQ - 0.1, 1)
            rfm69.frequency_mhz = FREQ

    if button_go.value:
        if listen:
            listen = False
            led.value = False
        else:
            listen = True
            led.value = True

    # base ui
    display.fill(0)
    display.text("Radio: %sMhz" % FREQ, 0, 0, 1)
    display.text(msg, 0, 20, 1)
    display.text(str(count), 55 - len(str(count)), 55, 1)
    display.text("<Up>", 0, 55, 1)
    display.text("<Down>", 93, 55, 1)
    display.show()

    if listen:
        packet = rfm69.receive()
        if packet is not None:
            packet_text = str(packet, 'ascii')
            msg = packet_text
            print('Received: {0}'.format(packet_text))
            count = count + 1