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.

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
        print('%s - sent %s' % (message, counter))
        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_right = digitalio.DigitalInOut(board.GP21)
button_go = digitalio.DigitalInOut(board.GP13)

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

# 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
            listen = True
            led.value = True

    # base ui
    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)

    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

Diablo RPG Style Inventory System in Unity

This weekend felt like a good time to tackle something new.

After successfully prototyping a 3D Disc Golf Game, and then a Game of Life-Simulation, I wanted to explore more of the user interface side.

I decided to build an Inventory management system, also decided it best to create a new project, this way I can build the Inventory as a re-usable module for more than one project.

It didn’t take much time for me to decide on a Diablo-style inventory where each item needs to fix within like a puzzle piece.

I bounced a couple of ideas of my son, and we both agreed on a mathematical solution using a single 2d-array would be the best solution (you can see this 2d-array representation in the debugger below).

With the code functionality solid I set out of re-skinning the components using some art assets I had from a past Humble Bundle.

Each of these Unity ScriptableObjects had names and descriptions, so next I tackled the Mouse hover display popover using another Unity Canvas.

Lastly I need a 3D world representation of the Item. I also needed a way to Pickup from the world, and Drop from the Inventory to the world.

A Game of Life in Unity

Took a little break from my Disc Golf Game to do a bit of AI programming in Unity.

What I ended up with was a simple Game of Life with rabbits trying to survive. Each rabbit has a growing hunger and thirst which if not addressed will result in death. The population is also broken into male and female rabbits which can reproduce.

Check out a couple minutes of the simulation running at realtime speed:

Wireless Chat using NRF24L01+ 2.4GHz RF Transceiver on Arduino & Raspberry Pi Ubuntu Linux

After a bit of success implementing an Arduino 2.4GHz Transceiver, I was encouraged to explore a more familiar environment, something with Python and Linux in the mix.

After a short period of research I landed on the circuitpython-nrf24l01 pypi project page, and quickly began digging through their examples.

It wasn’t long after I had a working prototype that mirrored my Arduino code quite closely:


import sys
import select

from circuitpython_nrf24l01 import RF24
import board
import digitalio as dio

# addresses needs to be in a buffer protocol object (bytearray)
address = b'Nessy'

# change these (digital output) pins accordingly
ce = dio.DigitalInOut(board.D4)
csn = dio.DigitalInOut(board.D5)

# using board.SPI() automatically selects the MCU's
# available SPI pins, board.SCK, board.MOSI, board.MISO
spi = board.SPI()  # init spi bus object

# initialize the nRF24L01 on the spi bus object
nrf = RF24(spi, csn, ce, ask_no_ack=False, data_rate=250)
nrf.dynamic_payloads = False # this is the default in the TMRh20 arduino library
nrf.payload_length = 32

# get username
username = input('Enter Username: ')

# set address of RX node into a TX pipe

# set address of TX node into a RX pipe
nrf.open_rx_pipe(1, address)

nrf.listen = True

print('Welcome %s' % username)
while True:

    # handle write
    if select.select([sys.stdin,],[],[],0.0)[0]:
        nrf.listen = False
        for line in sys.stdin:
            msg = b'[%b] %b' % (username.encode(), line.rstrip().encode())

    # handle recieve
    if not nrf.listen:
        nrf.listen = True

    if nrf.any():
        # retreive the received packet's payload
        buffer = nrf.recv()
        data = buffer.decode().replace('\x00', '')