Hardware components | ||||||
![]() |
| × | 1 | |||
| × | 1 | ||||
Software apps and online services | ||||||
![]() |
|
I spotted one of these 8x32 LED Matrix displays and thought it would make a cool "news ticker." It turns out there is already a great library for driving the MAX7219. Couple this with Particle webhooks and the Blynk library, and it takes less than an hour to make a real-time scrolling ticker controlled by a smartphone app. I configured the ticker to selectively display text messages sent via the Blynk app or real-time weather (METAR).
More on Particle webhooks:
https://docs.particle.io/tutorials/integrations/webhooks/
Blynk: blynk.cc.
Background on the MAX7219 and the existing Particle library:
https://github.com/digitalwizards/SparkCore-LEDMatrix-MAX7219-MAX7221
8x32 LED Matrix
There are many of these 8x32 matrix displays on eBay and Amazon. Make sure you pick one that uses the MAX7219 IC. The matrix module has 5 pin outs: VCC, GND, DN, CS, CLK. Attach VCC and GND to the corresponding pins on your Photon board. Attach CLK to D1, CS to D2, and DN to D3.

Blynk App Setup
The Blynk app is configured with the terminal widget (on V1) and a button (on V2). The terminal widget is used to send text strings for display on the LED matrix. The button switches the LED matrix display between text messages and weather.

Settings for Terminal Widget
The terminal widget is set for V1 "virtual pin." The Photon firmware uses Blynk_Write to capture strings input on V1.

Matrix.ino
C/C++Photon firmware for interfacing with Blynk and Particle webhooks to display real-time information. Makes use of the matrix library and scrolling text example from https://github.com/digitalwizards/SparkCore-LEDMatrix-MAX7219-MAX7221. And the Blynk library (blynk.cc).
// Simple LED Matrix Display with Blynk and Weather Integration
// Uses 4x MAX7219 Dot Matrix Modules to display messages
// Make sure you add these two libraries using the Particle IDE
#include <ledmatrix-max7219-max7221.h>
#include <blynk.h>
char auth[] = "1234"; // Put your blynk token here
LEDMatrix *led;
int bitmapWidth = 8; // 8 is default
int webcount = 60001; // timer to run the weather webhook every 60 seconds
String text = "Hello World"; // default string for display
String text2 = "No Texts"; // default string for Blynk texts
String text3 = "Getting Weather"; // default string for weather
int mode = 0;
int textLength = text.length();
// default position of the text is outside and then scrolls left
int textX = bitmapWidth;
int fontWidth = 5, space = 1;
void drawText(String s, int x)
{
int y = 0;
for(int i = 0; i < s.length(); i++) {
// Adafruit_GFX method
led->drawChar(x + i*(fontWidth+space), y, s[i], true, false, 1);
}
}
void setup() {
Blynk.begin(auth); // setup Blynk
// setup pins and library
// 1 display per row, 1 display per column
// optional pin settings - default: CLK = A0, CS = A1, D_OUT = A2
// (pin settings is independent on HW SPI)
led = new LEDMatrix(4, 1, D1, D2, D3); // my pins vary from the default
// > add every matrix in the order in which they have been connected <
// the first matrix in a row, the first matrix in a column
// vertical orientation (-90°) and no mirroring - last three args optional
// the Wangdd22 Matrix has 4 matrix elements, arranged side-by-side
led->addMatrix(3, 0, 0, false, false);
led->addMatrix(2, 0, 0, false, false);
led->addMatrix(1, 0, 0, false, false);
led->addMatrix(0, 0, 0, false, false);
Particle.subscribe("hook-response/get_weather", gotWeatherData, MY_DEVICES); // see particle.io tutorial on weather webhooks
}
// In the Blynk app, I used the Termianl widget on virtual pin V1 to send text messages for display.
BLYNK_WRITE(V1) {
String cmd = param[0].asStr();
text2 = cmd;
}
// In the Blynk app, I used V2 as a button to toggle mode between weather and texts.
BLYNK_WRITE(V2){
mode = param.asInt();
}
// This collects data from my get_weather webhook, METAR data in my example. See the photon tutorial on webhooks to get other data. https://docs.particle.io/tutorials/integrations/webhooks/
void gotWeatherData(const char *name, const char *data) {
text3 = String(data);
}
void loop() {
Blynk.run();
if (webcount > 60000) { // fetch data via the webhook only once a minute
Particle.publish("get_weather");
webcount = 0;
}
// pick which text string will be displayed
if (mode == 0) {
text = text3;
textLength = text.length();
}
if (mode == 1) {
text = text2;
textLength = text.length();
}
webcount = webcount + 1;
if(led != NULL) {
drawText(text, textX--);
// text animation is ending when the whole text is outside the bitmap
if(textX < textLength*(fontWidth+space)*(-1)) {
// set default text position
textX = bitmapWidth;
// show heart
led->flush();
delay(333); // 1000 is default
// turn all pixels off (takes effect after led->flush())
led->fillScreen(false);
}
// draw text
led->flush();
delay(125); // 250 is default
}
// animations end
else if (led != NULL) {
// shutdown all displays
led->shutdown(true);
// free memory
delete led;
led = NULL;
}
}
Comments