-
-
Notifications
You must be signed in to change notification settings - Fork 22
quick_start
The following is a brief reference on how to install and use DMD_STM32 library.
There are two ways to install the library:
- Download ZIP-archive directly from Releases section, open your Arduino IDE, click on
Sketch > Include Library > Add . ZIP Library
. Choose the zip file you just downloaded. - Using Library Manager (since Arduino IDE 1.6.2): navigate to
Sketch > Include Library > Manage Libraries
inside your Arduino IDE and search for the library, then clickInstall
.
-
Adafruit_GFX library
DMD_STM32a project requires Adafruit GFX library
-
STM32
The only Roger Clarks's repo https://github.com/rogerclarkmelbourne/Arduino_STM32 is supported for STM32 based boards on Arduino IDE.
Please note that Clark's repo versions prior d05a128 (28 Apr 2024) is incompatible with recent Adafruit GFX library. Use Adafruit GFX version prior to 1.8.0 (v1.7.0 is OK) https://github.com/adafruit/Adafruit-GFX-Library/releases/tag/1.7.0
-
Raspberry Pi Pico
This code requires Earle Philhower core https://github.com/earlephilhower/arduino-pico
- Monochrome panels: The library primarily intended to work on P10 32x16 Monochrome panels with HUB12 interface. Other types of Monochrome panels are quite rare and not tested with the library.
-
RGB panels: The code works with most RGB HUB75 panels with line scanning drivers. Panels of almost any size, scanning and multiplexing type can be used. All these are configured by "matrix pattern" - a strings of digits, represents a key characteristics of given panel. More information about matrix patterns you can found in wiki.The library does provide to users a rich set of predefined matrix patterns. Full list of implemented patterns see in
DMD_Panel_Templates.h
file. If you haven't found a suitable pattern for your matrix, please feel free to open an issue using template.
Using panels with a drivers with internal memory (S-PWM, EPWM types) is a difficult case; although the classes for some such drivers are implemented (FM6126a, FM6353, FM6363) in the library, as a general rule S-PWM drivers are not supported. You can found a table of known supported and unsupported drivers in the wiki/Led drivers section.
When using the library for the first time, I recommend connect the pins and use the settings, specified in the examples.
To include Monochrome panel support part of DMD_STM32 library add the following line at the top of your sketch:
#include <DMD_MonoChrome_SPI.h>
or
#include <DMD_Monochrome_Parallel.h>
To learn the difference between SPI and Parallel Monochrome modes see the "Connections" wiki.
Many library modes require specific MCU pins, depending on used controller. Let's assume you have a simple setup as follows: the STM32F103 "Bluepill" board with 4 P10 32x16 Monochrome panels, chained in 2x2 screen. Create constants for the pins that controls the panel:
#define DMD_PIN_A PA1
#define DMD_PIN_B PA3
#define DMD_PIN_nOE PB1
Loading data into the panel is similar to working with a shift register; the clock, data and latch pins are also used here. The way they are set depends on the selected mode:
-
Monochrome Parallel mode
In this mode we connect each row of panels to separate DATA pin, using common clock and latch pins for all rows. Clock and data pins defined as a list:
#define DMD_PIN_SCLK PA15 // latch uint8_t pins[] = { PA5, PA7, PA6 }; // CLK , row1, row2
Note that on many panels latch pin could be labeled as SCLK
-
Monochrome SPI mode
The mode uses hardware SPI bus as a transport interface. We use SPI_CLK and SPI_MOSI as CLK and DATA pins; it has the predefined values depends on used SPI channel. The only LAT(SCLK) pin must be defined:
#define DMD_PIN_SCLK PA15 // latch SPIClass dmd_spi(1);
Recommended pin combinations for other cases are shown in the examples. If you want to change the default pins, see the Connections section in the Wiki.
Setup the screen:
//Number of panels in x and y axis
#define DISPLAYS_ACROSS 2
#define DISPLAYS_DOWN 2
switch on DUAL BUFFER if needed:
#define ENABLE_DUAL_BUFFER true
and create the library object:
- Monochrome Parallel mode
DMD_Monochrome_Parallel dmd(DMD_PIN_A, DMD_PIN_B, DMD_PIN_nOE, DMD_PIN_SCLK, pins, DISPLAYS_ACROSS, DISPLAYS_DOWN,ENABLE_DUAL_BUFFER);
- Monochrome SPI mode
DMD_MonoChrome_SPI dmd(DMD_PIN_A, DMD_PIN_B, DMD_PIN_nOE, DMD_PIN_SCLK, DISPLAYS_ACROSS, DISPLAYS_DOWN, dmd_spi, ENABLE_DUAL_BUFFER);
After creating an instance of the DMD class, the last thing you need to do before you start working with panels is to initialize the library. Place the line
dmd.init()
somewhere in setup()
.
Congratulations! Setup is complete. See the "Use cases" section and example directory to view how to work with DMD Led panels in your code.
In order to start using library with RGB panels add the following line at the top of your sketch:
#include <DMD_RGB.h>
In some cases to work with panels equipped with non-standard drivers you may need to include a different headers to work:
DMD_RGB_FM6126a.h
orDMD_RGB_FM6353.h
. See examples for detail.
Many library modes require specific MCU pins, depending on used controller. Let's assume you have a simple setup as follows: the STM32F401 "Blackpill" board with 4 64x32 s16 RGB panels, chained in 2x2 screen. Create constants for the pins that controls the panel:
#define DMD_PIN_A PB6
#define DMD_PIN_B PB5
#define DMD_PIN_C PB4
#define DMD_PIN_D PB3
#define DMD_PIN_E PB8
// put all mux pins at list
uint8_t mux_list[] = { DMD_PIN_A , DMD_PIN_B , DMD_PIN_C , DMD_PIN_D , DMD_PIN_E };
// pin OE must be one of PB0 PB1 PA6 PA7
#define DMD_PIN_nOE PB0 // OE
#define DMD_PIN_SCLK PB7 // LAT
The RGB panels has a six data pins - a two for each color Red, Green, Blue. All these pins as well a CLK pin must be connected to the same controller port:
// All this pins must be selected on the same mcu port!
uint8_t custom_rgbpins[] = {PA6, PA0,PA1,PA2,PA3,PA4,PA5 }; // CLK, R0, G0, B0, R1, G1, B1
Recommended pin combinations for other cases are shown in the examples. If you want to change the default pins, see the Connections section in the Wiki.
Setup the screen:
//Number of panels in x and y axis
#define DISPLAYS_ACROSS 2
#define DISPLAYS_DOWN 2
switch on DUAL BUFFER if needed:
#define ENABLE_DUAL_BUFFER true
and create the library object:
DMD_RGB <RGB64x32plainS16, COLOR_4BITS> dmd(mux_list, DMD_PIN_nOE, DMD_PIN_SCLK, custom_rgbpins, DISPLAYS_ACROSS, DISPLAYS_DOWN, ENABLE_DUAL_BUFFER);
Working with panel that used a shift_register type (aka 595 type) multiplexer chip, just replace the
DMD_RGB
class toDMD_RGB_SHIFTREG_ABC
class. Similar to it, when use a panel with a specific drivers FM6126, FM6353 or FM6363 - replace theDMD_RGB
toDMD_RGB_FM6126
,DMD_RGB_FM6353
orDMD_RGB_FM6363
respectively.
After creating an instance of the DMD class, the last thing you need to do before you start working with panels is to initialize the library. Place the line
dmd.init()
somewhere in setup()
.
Congratulations! Setup is complete. See the "Use cases" section and example directory to view how to work with DMD Led panels in your code.
All examples in this section are not a stand-alone sketches, but only a code snippets. Let's assume you already defined the pins and setup the matrix, as described in section How to start.
In order to output the text on the panel you need to attach a font to the sketch. Select one from the library's font folder and add to your code somewhere before setup()
:
#include "gfx_fonts/GlametrixLight12pt7b.h"
DMD_GFX_Font GlametrixL((uint8_t*)&GlametrixLight12pt7b, 13);
Than set the text, choose the color and draw the string on display:
void setup() {
// initialize DMD objects
dmd.init();
// set the brightness
dmd.setBrightness(100);
// create the colors
uint16_t bg = 0; // background - black
uint16_t fg = dmd.Color888(255, 0, 0); // foreground - red
//define the text
char str[] = "Hello DMD_STM32!";
// select the font and draw the string at pos (x,y) 0,0 with color fg
dmd.selectFont(&GlametrixL);
dmd.drawString(0, 0, str, strlen(str),fg);
}
The only difference from the previous example is a method of the setting the colors. Instead of selecting a single color we setup a color list.
// attach the font
#include "gfx_fonts/GlametrixLight12pt7b.h"
DMD_GFX_Font GlametrixL((uint8_t*)&GlametrixLight12pt7b, 13);
void setup() {
// initialize DMD objects
dmd.init();
// set the brightness
dmd.setBrightness(100);
// create color array
uint16_t col[] = {
0, // background = black
dmd.Color888(255,0, 0), // red
dmd.Color888(0, 255, 0), // green
dmd.Color888(0, 0, 255) // blue
};
// create colorlist
DMD_Colorlist multicolor(4, col ); // list length, pointer to color array
//define the text
char str[] = "Hello DMD_STM32!";
// select the font and draw the string at pos (x,y) with colors from the list
dmd.selectFont(&GlametrixL);
dmd.drawStringX(0, 15, str, &multicolor);
}
To run the scrolling string you need to perform the same steps as for displaying text. Working with scrolling is performed by two functions - the drawMarquee()
function prepares and displays the string on the matrix, and the stepMarquee()
function controls its movement.
Scrolling text is a dynamic process, so we need a cycle that calls the stepMarquee()
with a given interval. The condition for completing or restarting scrolling may be that the text leaves the screen completely.
Take note, that as a default you can use only one marquee on the time. To see the workaround, read the next examples.
// attach the font
#include "gfx_fonts/GlametrixLight12pt7b.h"
DMD_GFX_Font GlametrixL((uint8_t*)&GlametrixLight12pt7b, 13);
void setup() {
// initialize DMD objects
dmd.init();
// set the brightness
dmd.setBrightness(100);
// create the colors
uint16_t bg = 0; // background - black
uint16_t fg = dmd.Color888(255, 0, 0); // foreground - red
// we need set text colors when using it with Marquee functions
dmd.setTextColor(fg, bg);
// select the font
dmd.selectFont(&GlametrixL);
}
//define the text
const char str[] = "Hello DMD_STM32!";
bool first_start = true;
void loop() {
// initial marquee setup. We need to do it once so we use the marquee_start flag
if (first_start) {
dmd.drawMarqueeX(str, -1 * (dmd.stringWidth(str)), 0); // start the scroll from the left border of the screen
first_start = false;
}
// scrolling step interval
const uint32_t interval = 30; // milliseconds
static uint32_t prev_step = millis();
if ((millis() - prev_step) > interval) {
prev_step = millis();
if (dmd.stepMarquee(1, 0) & MARQUEE_OUT_OF_SCREEN ) { // if text is reached screen bounds
// clear the screen and restart marquee
dmd.clearScreen(true);
dmd.drawMarqueeX(str, -1 * (dmd.stringWidth(str)), 0);
}
}
}
See also dmd_rgb.ino
in library examples.
As a default the stepMarquee()
shifts the entire screen, so you can't have a static elements on display when you use a scrolling. To solve the issue we have to use a DUAL_BUFFER_MODE
and redraw the static text every time as we moved the marquee. Add this BEFORE creating the dmd object:
// Enable of output buffering
// if true, changes only outputs to matrix after
// swapBuffers(true) command
// If dual buffer not enabled, all output draw at matrix directly
// and swapBuffers(true) command do nothing
#define ENABLE_DUAL_BUFFER true
Now we can fullfil our usual procedures:
// attach the font
#include "gfx_fonts/GlametrixLight12pt7b.h"
DMD_GFX_Font GlametrixL((uint8_t*)&GlametrixLight12pt7b, 13);
// create the colors
uint16_t bg = 0; // background - black
uint16_t fg = dmd.Color888(255, 0, 0); // marquee foreground - red
uint16_t fg2 = dmd.Color888(0, 255, 0); // static text foreground - green
void setup() {
// initialize DMD objects
dmd.init();
// set the brightness
dmd.setBrightness(100);
// we need set text colors when using it with Marquee functions
dmd.setTextColor(fg, bg);
// select the font
dmd.selectFont(&GlametrixL);
// disable moving the marquee by shifting the screen
dmd.disableFastTextShift(true);
}
//define the text
const char str[] = "Hello DMD_STM32!";
bool first_start = true;
void loop() {
// initial marquee setup. We need to do it once so we use the marquee_start flag
if (first_start) {
dmd.drawMarqueeX(str, -1 * (dmd.stringWidth(str)), 0); // start the scroll from the left border of the screen
first_start = false;
}
// scrolling step interval
const uint32_t interval = 30; // milliseconds
static uint32_t prev_step = millis();
if ((millis() - prev_step) > interval) {
prev_step = millis();
if (dmd.stepMarquee(1, 0) & MARQUEE_OUT_OF_SCREEN ) { // if text is reached screen bounds
// clear the screen and restart marquee
dmd.clearScreen(true);
dmd.drawMarqueeX(str, -1 * (dmd.stringWidth(str)), 0);
}
// renew fixed text
dmd.drawFilledBox(0, 0, 15, dmd.height() - 1, bg);
dmd.drawStringX(0, 0, "23", fg2);
// output mem buffer to matrix
dmd.swapBuffers(true);
}
}
Another example of using this technique see at the dmd_rgb_dual_buf.ino
code.
The principle the same as for scrolling with a static text - you have to move a marquee and redraw the second string. But instead of redrawing it in a fixed position - we will increment the x coordinate by one pixel every time, moving the second string in opposite direction to the marquee.
#define ENABLE_DUAL_BUFFER true // add this BEFORE the creating a DMD instance
// ...create a DMD...
// attach the font
#include "gfx_fonts/GlametrixLight12pt7b.h"
DMD_GFX_Font GlametrixL((uint8_t*)&GlametrixLight12pt7b, 13);
// create the colors
uint16_t bg = 0; // background - black
uint16_t fg = dmd.Color888(255, 0, 0); // marquee foreground - red
uint16_t fg2 = dmd.Color888(0, 255, 0); // second text foreground - green
void setup() {
// initialize DMD objects
dmd.init();
// set the brightness
dmd.setBrightness(100);
// we need set text colors when using it with Marquee functions
dmd.setTextColor(fg, bg);
// select the font
dmd.selectFont(&GlametrixL);
// disable moving the marquee by shifting the screen
dmd.disableFastTextShift(true);
}
//define the texts
const char str[] = "Hello DMD_STM32!";
const char fixed_str[] = "FIXED TEXT";
bool first_start = true;
void loop() {
// initial marquee setup. We need to do it once so we use the marquee_start flag
if (first_start) {
dmd.drawMarqueeX(str, dmd.width() -2 , 16); // start the scroll from the right border of the screen
first_start = false;
}
// scrolling step interval
const uint32_t interval = 30; // milliseconds
static uint32_t prev_step = millis();
static int16_t i = 0;
if ((millis() - prev_step) > interval) {
prev_step = millis();
if (dmd.stepMarquee(-1, 0) & MARQUEE_OUT_OF_SCREEN ) { // move text left and checks if text is reached screen bounds
// clear the screen and restart marquee
dmd.clearScreen(true);
dmd.drawMarqueeX(str, dmd.width() -2 , 16);
}
// renew a second text
dmd.drawStringX(i, 0, fixed_str, fg2);
i++; // increment the X coordinate
if (i >= (dmd.width() +2) ) i = -1 * (dmd.stringWidth(fixed_str)); // if text is out the right screen border - restart from the left
// output mem buffer to matrix
dmd.swapBuffers(true);
}
}
Additional info about library's classes and methods see in Library API Reference.