Skip to main content

How to use MatrixPortal M4

What is GroveMatrixPortal Serial Bluetooth v3.0M4

GroveThe -MatrixPortal Serial BluetoothM4 is ana easy-to-usedevelopment moduleboard compatiblecreated by Adafruit designed to control RGB LED matrices. It is equipped with thean existingATSAMD51 Grovemicrocontroller Base(Cortex Shield,M4) and designedhas built-in Wi-Fi support thanks to the ESP32 coprocessor.

Here are some key features of the MatrixPortal M4:

  1. Microcontroller: ATSAMD51, Cortex M4 processor running at 120 MHz.
  2. Coprocessor: ESP32 handles Wi-Fi and network communication.
  3. Memory: 512KB of RAM, 8MB of QSPI flash storage.
  4. Matrix Control: Dedicated connectors for transparentRGB wirelessLED serialmatrices connection(HUB75 setup.interface), allowing direct control without needing additional hardware.
  5. Power: Can be powered via USB-C or through the matrix’s power 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, we will beuse usingCircuitPython twoto Groveprogram Seriala Bluetooth64X32 modulesmatrix andas twoCircuitPython libraries make it easier to display images, animations, text, etc than Arduino to perform a wireless communication.IDE.

You can read more about this component here.

led_matrices_4745-06.jpg

Wiring

(Master

There -is Sendingno data)wiring needed for basic setup, it's literally plug and play. Please refer to this page to see how to set it up.

adafruit_io_mxprtl-3876.jpg

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

InterruptCircuitPython Pinsand forlibraries RX/TXversions
In this tutorial, I am using an UNO which has pin 2 & 3 as the interrupts pins. Check the model youwe 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.

  • Press the reset button on your board twice quickly.
  • The board’s LED will change to a different colour (usually pulsing red or green)
  • A new USB drive will appear on your computer named something like "BOOT".

3. Copy the pinsCircuitPython accordingly.UF2 File

  • Drag and drop the downloaded UF2 file onto the new drive.
  • The board will reboot, and a new drive named CIRCUITPY will appear. This drive is where you'll place your Python code and libraries.

Libraries

  • Download the libraries bundle here, choose the version you need.
  • Copy the libraries you need to the lib folder of the CIRCUITPY drive.

Common libraries you need:

  1. VCC (Red) to 5Vadafruit_matrixportal
  2. GND (Black) to GNDadafruit_debouncer.mpy
  3. RX (White) to pin 3 (Arduino TX)adafruit_portalbase
  4. TX (Yellow) to pin 2 (Arduino RX)adafruit_esp32spi
  5. Button to GNDneopixel.mpy
  6. Buttonadafruit_bus_device
  7. to
  8. adafruit_requests.mpy
  9. pin
  10. adafruit_fakerequests.mpy
  11. 13
  12. adafruit_io
  13. adafruit_bitmap_font
  14. adafruit_display_text
  15. adafruit_lis3dh.mpy
  16. adafruit_minimqtt
  17. adafruit_ticks.py
  18. adafruit_rgb_display
  19. adafruit_imageload
  20. adafruit_display_shapes

GroveBluetoothMasterCircuit.png

Wiring (Slave - Receving data)

  1. VCC (Red) to 5V
  2. GND (Black) to GND
  3. RX (White) to pin 3 (Arduino TX)
  4. TX (Yellow) to pin 2 (Arduino RX)

GroveBluetoothSlaveCircuit.png

Code - MasterScrolling Text

# SPDX-FileCopyrightText: 2020 Jeff Epler for Adafruit Industries
#
# SPDX-License-Identifier: MIT

# This codeexample readsimplements a simple two line scroller using
# Adafruit_CircuitPython_Display_Text. Each line has its own color
# and it is possible to modify the signalexample to use other fonts and non-standard
# characters.

import adafruit_display_text.label
import board
import displayio
import framebufferio
import rgbmatrix
import terminalio
from adafruit_bitmap_font import bitmap_font
from displayio import Bitmap

# If there was a display before (protomatter, LCD, or E-paper), release it so
# we can create ours
displayio.release_displays()
matrix = rgbmatrix.RGBMatrix(
    width=64, bit_depth=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 buttontext, you can also
# customize the color and sendsfont it(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.
g = displayio.Group()
g.append(line1)
g.append(line2)
g.append(line3)
display.root_group = g

# This function will scoot one label a pixel to the Slaveleft Arduino.

and
send /*it *back FM.hto
*# Athe libraryfar right if it's gone all the way off screen. This goes in a function
# because we'll do exactly the same thing with line1 and line2 below.
def scroll(line):
    line.x = line.x - 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 SeeedStudioline2 Grovebelow!
FMdef *
 * Copyright (c) 2012 seeed technology inc.
 * Website    reverse_scroll(line):
    www.seeed.ccline.x *= Authorline.x :+ Steve1
    Changline_width *= Createline.bounding_box[2]
    Time:if JULYline.x 2014>= *display.width:
        Changeline.x Log= :-line_width

Modified# byYou looveecan 2013-10-29add ,more Modifiedeffects by jacob yan 2014-7-29 
 
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * ofin this softwareloop. andFor associatedinstance, documentationmaybe filesyou (the "Software"),want to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include <SoftwareSerial.h>                         // Software Serial Port

#define RxD         2
#define TxD         3

#define PINBUTTON   13                               // pin of button

#define DEBUG_ENABLED  1



SoftwareSerial blueToothSerial(RxD,TxD);

void setup()
{
    Serial.begin(9600);
    pinMode(RxD, INPUT);
    pinMode(TxD, OUTPUT);
    pinMode(PINBUTTON, INPUT_PULLUP);
    
    setupBlueToothConnection();
    //wait 1s and flush the serial buffer
    delay(1000);
    Serial.flush();
    blueToothSerial.flush();
}

void loop()
{
    
    static unsigned char state = 1;             // led off
    //Serial.println(digitalRead(PINBUTTON));
    
    if(digitalRead(PINBUTTON))
    {
        //state = 1-state;
        
        Serial.println("button on");
        
        blueToothSerial.print(state);
        
        delay(10);
        while(digitalRead(PINBUTTON))       // until button release
        {
            delay(10);
        }
        
        Serial.println("button off");
    }
}

/***************************************************************************
 * Function Name: setupBlueToothConnection
 * Description:  initilizing bluetooth connction
 * Parameters: 
 * Return: 
***************************************************************************/
void setupBlueToothConnection()
{

	
    blueToothSerial.begin(9600);  
	
	blueToothSerial.print("AT");
	delay(400); 
	
	blueToothSerial.print("AT+DEFAULT");             // Restore all setup value to factory setup
	delay(2000); 
	
	blueToothSerial.print("AT+NAMESeeedMaster");    // set the 
bluetooth# name as "SeeedMaster" ,the lengthcolor of bluetootheach namelabel mustto lessa thandifferent 12value.
characters.while delay(400);True:
    blueToothSerial.print("AT+ROLEM");scroll(line1)
    //#scroll(line2)
    setscroll(line3)
    thereverse_scroll(line2)
    bluetooth work in slave mode
	delay(400); 
	
	
	blueToothSerial.print("AT+AUTH1");            
    delay(400);    
	
	blueToothSerial.print("AT+CLEAR");             // Clear connected device mac address
    delay(400);   
	
    blueToothSerial.flush();
	
	
}display.refresh(minimum_frames_per_second=1)



Code - Slave

/*
 * FM.h
 * A library for SeeedStudio Grove FM
 *
 * Copyright (c) 2012 seeed technology inc.
 * Website    : www.seeed.cc
 * Author     : Steve Chang
 * Create Time: JULY 2014
 * Change Log : Modified by loovee 2013-10-29  ,   Modified by jacob yan 2014-7-29
 
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */



#include <SoftwareSerial.h>   //Software Serial Port

#define RxD         2
#define TxD         3

#define PINLED      13

#define LEDON()     digitalWrite(PINLED, HIGH)
#define LEDOFF()    digitalWrite(PINLED, LOW)

#define DEBUG_ENABLED  1

SoftwareSerial blueToothSerial(RxD,TxD);

void setup()
{
    Serial.begin(9600);
    pinMode(RxD, INPUT);
    pinMode(TxD, OUTPUT);
    pinMode(PINLED, OUTPUT);
    LEDOFF();
    
    setupBlueToothConnection();
}

void loop()
{
    char recvChar;
    
    while(1)
    {
        if(blueToothSerial.available())
        {//check if there's any data sent from the remote bluetooth shield
            recvChar = blueToothSerial.read();
            Serial.print(recvChar);
            
            if(recvChar == '1')
            {
                LEDON();
            }
            else if(recvChar == '0')
            {
                LEDOFF();
            }
        }
    }
}




/***************************************************************************
 * Function Name: setupBlueToothConnection
 * Description:  initilizing bluetooth connction
 * Parameters: 
 * Return: 
***************************************************************************/
void setupBlueToothConnection()
{	

	
	
	blueToothSerial.begin(9600);  
	
	blueToothSerial.print("AT");
	delay(400); 

	blueToothSerial.print("AT+DEFAULT");             // Restore all setup value to factory setup
	delay(2000); 
	
	blueToothSerial.print("AT+NAMESeeedBTSlave");    // set the bluetooth name as "SeeedBTSlave" ,the length of bluetooth name must less than 12 characters.
	delay(400);
	
    blueToothSerial.print("AT+PIN0000");             // set the pair code to connect 
	delay(400);
	
	blueToothSerial.print("AT+AUTH1");             //
    delay(400);    

    blueToothSerial.flush();

}

Connection

After uploading both codes to both Arduinos, reset them simultaneously. The LEDs on the modules will be flashing and wait until they stay on, then they are connected.

You may need to repeat a couple of times to get them connected, it's all about patience.