🍞
Breadstick
  • Breadstick Innovations Website
  • Breadsticks
    • đŸĨ–Raspberry Breadstick
      • Code Examples
        • Demo Code
        • POV Wand
        • Pride Flags POV Wand
        • 6-Axis IMU
        • RGB Blink
        • AsyncIO RGB Blink
        • Digital Input
        • Digital Output
        • PWM
        • ADC
        • Servo Motor
    • đŸĨ–Raspberry Breadstick Lite
    • 🍞Support Boards
      • I2C Devices
        • 🚌I2C Bus Rail Adapter
        • đŸŒĻī¸Weather Crouton
        • 😎Brightness Crouton
        • 📏Distance Crouton
        • đŸĢ¨Motion Crouton
      • I2S Devices
        • đŸ“ĸBoombox
      • SPI Devices
      • đŸ•šī¸Buttons/Switches
    • Learning Resources
    • Troubleshooting
  • Nougat
    • Nougat C3
    • Nougat Quad
    • Installing WLED
  • Pico Slices
    • 🔴Slice 1 - LED Mixer
      • Assembly Guide
      • CircuitPython Code
        • 1 - Blink
        • 2 - Analog Read to Plotter
        • 3 - PWM Fade
        • 4 - Pot Controlled PWM
        • 5 - Gamma Correction
    • âąī¸Slice 2 - Stopwatch
      • Assembly Guide
      • Coding Lessons
        • 1 - 7-Segment Display Intro
        • 2 - Cycling Through All Segments
    • âŦœSlice 3 - 8x8 Dot Matrix
      • Assembly Guide
      • MicroPython Code
        • 1 - Moveable Pixel
        • 2 - Snake
    • Circuit Python Setup
    • Reset Bricked Pico
  • Christmas
    • Christmas Tree DIY kit
  • Protoboards
    • â¤ī¸Proto-Heart
    • đŸĨĒProto-Toast
  • SHOP
Powered by GitBook
On this page
  • Required Libraries
  • Code

Was this helpful?

  1. Breadsticks
  2. Raspberry Breadstick
  3. Code Examples

POV Wand

Use your Raspberry Breadstick as a POV (Persistance Of Vision) wand to draw images in the air using the LEDs!

PreviousDemo CodeNextPride Flags POV Wand

Last updated 1 year ago

Was this helpful?

Required Libraries

Code

"""
Raspberry Breadstick POV Display
www.learn.breadstick.ca
Michael Rangen
May 19, 2024

Loads an indexed bitmap impage and generates a
persistance of vision display as the Breadstick is waved
through the air.

To create an image, start in MSPaint, set the image
height to 24 pixels, and as wide as you want. Alternatively,
copy an image, paste it into paint, and scale the image to
24 pixels tall. Fill the background with black, and save as
as 24-bit bmp file. Open the image in GIMP, and in the toolbar
click Image > Mode > Indexed > Convert before returning to the
toolbar and clicking File > Overwrite your_image.bmp.

SK9822 LEDs are not initialized as DotStar objects, instead
data is sent to them by passing prepared bytearrays to a
bitbangio.SPI object clocking at 12MHz.

The bytearrays are prepared by using adafruit_imageload and
the displayio libraries to extract pixel data from an indexed
bitmap file stored in the root directory of the Breadstick.
A buffer of black columns is added to either side of the image.
Pixel data is padded with necessary bites defined by the SK9822
LED datasheet.

The LSM6DS IMU provides gyroscope data over I2C to determine
which direction the Breadstick is being waved and to control the
delay between each column being sent to the LEDs.
"""


"""
User Controls
"""
IMAGE_PATH = "HappyCat.bmp"
LED_BRIGHTNESS = 0.001
PIXEL_DELAY = 250
IMAGE_PADDING = 4


"""
Library Imports
"""
from board import *
import time

# For SK9822 LEDs
from displayio import Bitmap, Palette
import adafruit_imageload
import bitbangio
from microcontroller import delay_us

# For IMU (Gryoscope & Accellerometer)
import busio
from adafruit_lsm6ds.lsm6ds3trc import LSM6DS3TRC as LSM6DS
from adafruit_lsm6ds import Rate, AccelRange, GyroRange

# Garbage Collector
import gc

"""
LED Setup
"""
spi = bitbangio.SPI(DOTSTAR_CLOCK, DOTSTAR_DATA)
while not spi.try_lock():
    pass
spi.configure(baudrate=12000000)


"""
IMAGE Setup
"""
my_bitmap, my_palette = adafruit_imageload.load(
    IMAGE_PATH, bitmap=Bitmap, palette=Palette
)

columns = []

start = [0, 0, 0, 0]
end = [255, 255, 255, 255]
bright = 225 + int(LED_BRIGHTNESS * 30)

# Pad the left side of the image with black columns
for x in range(0, IMAGE_PADDING, 1):
    column = []
    column.extend(start)
    for y in range(my_bitmap.height - 1, -1, -1):
        column.append(bright)
        r = 0
        g = 0
        b = 0
        column.append(b)
        column.append(g)
        column.append(r)
    column.extend(end)
    columns.append(bytearray(column))
# Create columns from the indexed bitmap file.
# If you're getting errors about ColorConverter
# then your bitmap likely is in RGB mode.
# Open it in GIMP
# Image > Mode > Indexed > Convert
# File > Overwrite your_image.bmp
for x in range(0, my_bitmap.width, 1):
    column = []
    column.extend(start)
    for y in range(my_bitmap.height - 1, -1, -1):
        column.append(bright)
        pixel = my_palette[my_bitmap[x, y]]
        r = (pixel >> 16) & 0xFF
        g = (pixel >> 8) & 0xFF
        b = pixel & 0xFF

        column.append(b)
        column.append(g)
        column.append(r)
    column.extend(end)
    columns.append(bytearray(column))
# Pad the right side of the image with black columns
for x in range(0, IMAGE_PADDING, 1):
    column = []
    column.extend(start)
    for y in range(my_bitmap.height - 1, -1, -1):
        column.append(bright)
        r = 0
        g = 0
        b = 0
        column.append(b)
        column.append(g)
        column.append(r)
    column.extend(end)
    columns.append(bytearray(column))
"""
IMU Setup
"""
i2c = busio.I2C(IMU_SCL, IMU_SDA)
IMU = LSM6DS(i2c)
IMU.accelerometer_range = AccelRange.RANGE_4G
print("Accelerometer range set to: %d G" % AccelRange.string[IMU.accelerometer_range])
IMU.gyro_range = GyroRange.RANGE_1000_DPS
print("Gyro range set to: %d DPS" % GyroRange.string[IMU.gyro_range])
IMU.accelerometer_data_rate = Rate.RATE_1_66K_HZ
print("Accelerometer rate set to: %d HZ" % Rate.string[IMU.accelerometer_data_rate])
IMU.gyro_data_rate = Rate.RATE_1_66K_HZ
print("Gyro rate set to: %d HZ" % Rate.string[IMU.gyro_data_rate])

"""
Free Up Memory
"""
gc.collect()


"""
Main Program Loop
"""
while True:

    gyro_x, gyro_y, gyro_z = IMU.gyro
    if abs(gyro_z) < 0.001:
        gyro_z = 0.001
    col_delay = abs(int(PIXEL_DELAY / gyro_z))

    if gyro_z < 0:
        for i in range(0, len(columns), 1):
            gyro_x, gyro_y, gyro_z = IMU.gyro
            if abs(gyro_z) < 0.001:
                gyro_z = 0.001
            col_delay = abs(int(PIXEL_DELAY / gyro_z))
            if gyro_z > 0:
                break
            else:
                spi.write(columns[i])
                delay_us(col_delay)
    else:
        for i in range(len(columns) - 1, -1, -1):
            gyro_x, gyro_y, gyro_z = IMU.gyro
            if abs(gyro_z) < 0.001:
                gyro_z = 0.001
            col_delay = abs(int(PIXEL_DELAY / gyro_z))
            if gyro_z < 0:
                break
            else:
                spi.write(columns[i])
                delay_us(col_delay)

đŸĨ–
2KB
HappyCat.bmp
image
The rest of the libraries we import are already included with the Breadstick's CircuitPython distribution.
HappyCat.bmp