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
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