Skip to main content

Using MatrixPortal M4 for animation

WhatHow isto MatrixPortal M4

Theuse MatrixPortal M4 isfor a development board created by Adafruit designed to control RGB LED matrices. It is equipped with an ATSAMD51 microcontroller (Cortex M4) and has built-in Wi-Fi support thanks to the ESP32 coprocessor.

animation

HereWe arehave someanother keytutorial featuresfor ofsetting up the MatrixPortal M4:

  1. Microcontroller: ATSAMD51, Cortex M4 processor running at 120 MHz.
  2. Coprocessor: ESP32 handles Wi-Fiboard and network communication.
  3. Memory: 512KB of RAM, 8MB of QSPI flash storage.
  4. Matrix Control: Dedicated connectors for RGB LED matrices (HUB75 interface), allowing direct control without needing additional hardware.
  5. Power: Can be powered via USB-C or throughcovering the matrix’sbasics. powerThis supply.
  6. Programming: Supports programming via CircuitPython and Arduino IDE.
  7. Wi-Fi Connectivity: Useful for IoT projects that require network connectivity, such as weather stations, stock tickers, or message boards.

It’s great for building projects that involve large, colourful LED displays, such as scrolling text, interactive dashboards, or internet-connected signs. In this tutorial, wetutorial will usefocus CircuitPythonon tocreating programan a 64X32 matrix as CircuitPython libraries make it easieranimation to display images,on animations,a text,64x32 etc than Arduino IDE.

You can read more about this component here.matrix.

led_matrices_4745-06.jpgIMG_5497.jpg

WiringCreating the Spitesheet

ThereA spritesheet is noa wiringsingle neededimage file that contains a collection of smaller images (called sprites) arranged in a grid or some other layout. These individual sprites can represent various frames of an animation, characters, objects, or other visual elements in a video game or graphic application.

We will need to use a bitmap spitesheet. If you just want to test the code, you can download the test.bmp and skip this part for basicnow.

setup,

1. it'sPiskel

literally

Piskel plugis anda play.free Pleaseonline refereditor for animated sprites & pixel art.

piskel.png

  • Go to this page to see howresize to set itthe up.

    canvas size to 64 x 32 px
  • Draw whatever you want
  • Add new frame and draw
  • until you finish

adafruit_io_mxprtl-3876.jpgScreenshot 2024-10-11 at 12.04.56.png

Using a 64X64 Matrix

led_matrices_matrixportal_pinout_e_jumper.png

Ask a Technician first!
If you are using a MatrixPortal M4 borrowed from us, please do not do this step yourself, ask a technician for help instead.

This jumper is used for use with 64x64 matrices. You can close the jumper by using your soldering iron to melt a blob of solder on the bottom solder jumper so the middle pad is 'shorted' to 8 as below.

IMG_5496.jpg

You can read more about Address E Line Jumper here.

Install CircuitPython

CircuitPython and libraries versions
In this tutorial, we are using CircuitPython 9.0.5 (11/10/2024), and all libraries used are compatible with this version. Please double-check the latest version of CircuitPython you have installed and use updated and compatible libraries.

CircuitPython is an open-source programming language designed for microcontrollers. It's a beginner-friendly version of Python developed by Adafruit, optimized for hardware projects like controlling sensors, displays, and other electronics.

1. Download CircuitPython

Download the latest version for MatrixPortal UF2 file for your board here.

2. Put the Board into Bootloader Mode

To install CircuitPython, you need to place the board into bootloader mode.

  • PressGo theto resetEXPORT button on your board twice quickly.
  • TheSelect board’sPNG LED
  • will
  • Change changeColumns to a different colour (usually pulsing red or green)1
  • A newDownload USB
  • drive
  • You willnow appearhave ona yourvery computerlong namedPNG something like "BOOT".file

3.2. CopyPhotoshop

the CircuitPython UF2 File

bmp format.png

  • DragOpen the image with Photoshop
  • Save a copy in BMP format
  • Choose Windows (doesn't matter what computer you use) and drop16 theBit downloaded UF2 file onto the new drive.
  • TheYou boardnow will reboot, andhave a newready-to-go drivespitesheet namedBMP CIRCUITPY will appear. This drive is where you'll place your Python code and libraries.file

Libraries

  • DownloadImporting the librariesImage bundle here, choose the version you need.
    1. CopyCreate the libraries you need to the liba folder ofcalled bmp in the CIRCUITPY drive.
  • Copy

    Commonthe librariesbitmap file you need:

    have
      created
    1. adafruit_matrixportal
    2. into
    3. adafruit_debouncer.mpy
    4. the
    5. adafruit_portalbase
    6. adafruit_esp32spi
    7. neopixel.mpy
    8. adafruit_bus_device
    9. adafruit_requests.mpy
    10. adafruit_fakerequests.mpy
    11. adafruit_io
    12. adafruit_bitmap_font
    13. adafruit_display_text
    14. adafruit_lis3dh.mpy
    15. adafruit_minimqtt
    16. adafruit_ticks.py
    17. adafruit_rgb_display
    18. adafruit_imageload
    19. adafruit_display_shapesfolder.

    Code - Scrolling Text

    # SPDX-FileCopyrightText: 2020 JeffJohn EplerPark for Adafruit Industries
    #
    # SPDX-License-Identifier: MIT
    
    #import This example implements a simple two line scroller using
    # Adafruit_CircuitPython_Display_Text. Each line has its own color
    # and it is possible to modify the example to use other fonts and non-standard
    # characters.time
    import adafruit_display_text.labelos
    import board
    import displayio
    importfrom framebufferiodigitalio import rgbmatrixDigitalInOut, Pull
    from adafruit_matrixportal.matrix import terminalioMatrix
    from adafruit_bitmap_fontadafruit_debouncer import bitmap_fontDebouncer
    
    fromSPRITESHEET_FOLDER displayio= import"/bmp"
    BitmapDEFAULT_FRAME_DURATION = 0.1  # If100ms
    
    thereFRAME_DURATION_OVERRIDES was= a{
        display"KIRBY.bmp": before0.05,
    (protomatter, LCD, or E-paper), release it so}
    
    # we--- canDisplay createsetup ours
    displayio.release_displays()---
    matrix = rgbmatrix.RGBMatrix(
        Matrix(width=64, height=64, bit_depth=6,6)
    rgb_pins=[
            board.MTX_R1,
            board.MTX_G1,
            board.MTX_B1,
            board.MTX_R2,
            board.MTX_G2,
            board.MTX_B2
        ],
        addr_pins=[
            board.MTX_ADDRA,
            board.MTX_ADDRB,
            board.MTX_ADDRC,
            board.MTX_ADDRD
        ],
        clock_pin=board.MTX_CLK,
        latch_pin=board.MTX_LAT,
        output_enable_pin=board.MTX_OE
    )
    display = framebufferio.FramebufferDisplay(matrix, auto_refresh=False)
    keycolour = 0X7BFF4A
    # Create two lines of text to scroll. Besides changing the text, you can also
    # customize the color and font (using Adafruit_CircuitPython_Bitmap_Font).
    # To keep this demo simple, we just used the built-in font.
    # The Y coordinates of the two lines were chosen so that they looked good
    # but if you change the font you might find that other values work better.
    line1 = adafruit_display_text.label.Label(
        terminalio.FONT,
        color=keycolour, #white
        text="This is Creative Technology Hub")
    line1.x = display.width
    line1.y = 5
    
    line2 = adafruit_display_text.label.Label(
        terminalio.FONT,
        color=0x000000,
        background_color=keycolour,
        background_tight = True,
        text="Hello Hello Hello Hello Hello Helloooooooooo")
    line2.x = display.width
    line2.y = 15
    
    line3 = adafruit_display_text.label.Label(
        terminalio.FONT,
        color=keycolour,
        
        text="Stop peeking come in")
    line3.x = display.width
    line3.y = 26
    
    # Put each line of text into a Group, then show that group.
    gsprite_group = displayio.Group()
    g.append(line1)
    g.append(line2)
    g.append(line3)
    matrix.display.root_group = gsprite_group
    
    
    file_list = sorted(
        [
            f
            for f in os.listdir(SPRITESHEET_FOLDER)
            if (f.endswith(".bmp") and not f.startswith("."))
        ]
    )
    
    if len(file_list) == 0:
        raise RuntimeError("No images found")
    
    current_image = None
    current_frame = 0
    current_loop = 0
    frame_count = 0
    frame_duration = DEFAULT_FRAME_DURATION
    direction = 1 #1 for forward, -1 for backward
    
    def load_image():
        """
        Load an image as a sprite
        """
        # Thispylint: functiondisable=global-statement
        willglobal scootcurrent_frame, onecurrent_loop, labelframe_count, aframe_duration
        pixelwhile sprite_group:
            sprite_group.pop()
    
        filename = SPRITESHEET_FOLDER + "/" + file_list[current_image]
    
    
        # # CircuitPython 7+ compatible
        bitmap = displayio.OnDiskBitmap(filename)
        sprite = displayio.TileGrid(
             bitmap,
             pixel_shader=bitmap.pixel_shader,
             tile_width=bitmap.width,
             tile_height=matrix.display.height,
         )
    
        sprite_group.append(sprite)
    
        current_frame = 0
        current_loop = 0
        frame_count = int(bitmap.height / matrix.display.height)
        frame_duration = DEFAULT_FRAME_DURATION
        if file_list[current_image] in FRAME_DURATION_OVERRIDES:
            frame_duration = FRAME_DURATION_OVERRIDES[file_list[current_image]]
        direction = 1
    
    def advance_image():
        """
        Advance to the leftnext image in the list and send itloop back toat the end
        """
        # thepylint: fardisable=global-statement
        rightglobal current_image
        if it'scurrent_image goneis allnot None:
            current_image += 1
        if current_image is None or current_image >= len(file_list):
            current_image = 0
        load_image()
    
    
    def advance_frame():
        """
        Advance to the waynext offframe screen.and Thisloop goesback inat athe functionend
        """
        # becausepylint: we'lldisable=global-statement
        doglobal exactlycurrent_frame, thecurrent_loop, samedirection
        thingcurrent_frame with+= line1direction
        andif line2current_frame below.>= defframe_count:
            scroll(line):
        line.xcurrent_frame = line.xframe_count - 1
            line_width = line.bounding_box[2]
        if line.x < -line_width:
            line.x = display.width
    
    # This function scrolls lines backwards.  Try switching which function is
    # called for line2 below!
    def reverse_scroll(line):
        line.x = line.x + 1
        line_width = line.bounding_box[2]
        if line.x >= display.width:
            line.xdirection = -line_width1  # YouReverse candirection
        addelif morecurrent_frame effects< in0:
            thiscurrent_frame loop.= For0
            instance,direction maybe= you want to set the1  # colorForward ofdirection
        eachsprite_group[0][0] label= tocurrent_frame
    
    
    
    a different value.advance_image()
    
    while True:
        scroll(line1)advance_frame()
        #scroll(line2)
        scroll(line3)
        reverse_scroll(line2)
        display.refresh(minimum_frames_per_second=1)time.sleep(frame_duration)