Circuit Diagram:
Steps:
const char* ssid = "your SSID"; // edit your wifi SSID here const char* password = "your Password"; // edit your wifi password here
//Link: https://blog.etechpath.com
#include <ESP8266WiFi.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#define PRINT_CALLBACK 0
#define DEBUG 0
#define LED_HEARTBEAT 0
#if DEBUG
#define PRINT(s, v) { Serial.print(F(s)); Serial.print(v); }
#define PRINTS(s) { Serial.print(F(s)); }
#else
#define PRINT(s, v)
#define PRINTS(s)
#endif
#if LED_HEARTBEAT
#define HB_LED D2
#define HB_LED_TIME 500 // in milliseconds
#endif
#define MAX_DEVICES 4
#define CLK_PIN D5 // or SCK
#define DATA_PIN D7 // or MOSI
#define CS_PIN D8 // or SS
// SPI hardware interface
//MD_MAX72XX mx = MD_MAX72XX(CS_PIN, MAX_DEVICES);
#define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW //edit this as per your LED matrix hardware type
MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary pins
//MD_MAX72XX mx = MD_MAX72XX(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
// WiFi login parameters - network name and password
const char* ssid = "your SSID"; // edit your wifi SSID here
const char* password = "your Password"; // edit your wifi password here
// WiFi Server object and parameters
WiFiServer server(80);
// Global message buffers shared by Wifi and Scrolling functions
const uint8_t MESG_SIZE = 255;
const uint8_t CHAR_SPACING = 1;
const uint8_t SCROLL_DELAY = 75;
char curMessage[MESG_SIZE];
char newMessage[MESG_SIZE];
bool newMessageAvailable = false;
char WebResponse[] = "HTTP/1.1 200 OK\nContent-Type: text/html\n\n";
char WebPage[] =
"<!DOCTYPE html>" \
"<html>" \
"<head>" \
"<title>eTechPath MAX7219 ESP8266</title>" \
"<style>" \
"html, body" \
"{" \
"width: 600px;" \
"height: 400px;" \
"margin: 0px;" \
"border: 0px;" \
"padding: 10px;" \
"background-color: white;" \
"}" \
"#container " \
"{" \
"width: 100%;" \
"height: 100%;" \
"margin-left: 200px;" \
"border: solid 2px;" \
"padding: 10px;" \
"background-color: #b3cbf2;" \
"}" \
"</style>"\
"<script>" \
"strLine = \"\";" \
"function SendText()" \
"{" \
" nocache = \"/&nocache=\" + Math.random() * 1000000;" \
" var request = new XMLHttpRequest();" \
" strLine = \"&MSG=\" + document.getElementById(\"txt_form\").Message.value;" \
" request.open(\"GET\", strLine + nocache, false);" \
" request.send(null);" \
"}" \
"</script>" \
"</head>" \
"<body>" \
"<div id=\"container\">"\
"<H1><b>WiFi MAX7219 LED Matrix Display</b></H1>" \
"<form id=\"txt_form\" name=\"frmText\">" \
"<label>Msg:<input type=\"text\" name=\"Message\" maxlength=\"255\"></label><br><br>" \
"</form>" \
"<br>" \
"<input type=\"submit\" value=\"Send Text\" onclick=\"SendText()\">" \
"<p><b>Visit Us at</b></p>" \
"<a href=\"http://www.eTechPath.com\">www.eTechPath.com</a>" \
"</div>" \
"</body>" \
"</html>";
char *err2Str(wl_status_t code)
{
switch (code)
{
case WL_IDLE_STATUS: return("IDLE"); break; // WiFi is in process of changing between statuses
case WL_NO_SSID_AVAIL: return("NO_SSID_AVAIL"); break; // case configured SSID cannot be reached
case WL_CONNECTED: return("CONNECTED"); break; // successful connection is established
case WL_CONNECT_FAILED: return("CONNECT_FAILED"); break; // password is incorrect
case WL_DISCONNECTED: return("CONNECT_FAILED"); break; // module is not configured in station mode
default: return("??");
}
}
uint8_t htoi(char c)
{
c = toupper(c);
if ((c >= '0') && (c <= '9')) return(c - '0');
if ((c >= 'A') && (c <= 'F')) return(c - 'A' + 0xa);
return(0);
}
boolean getText(char *szMesg, char *psz, uint8_t len)
{
boolean isValid = false; // text received flag
char *pStart, *pEnd; // pointer to start and end of text
// get pointer to the beginning of the text
pStart = strstr(szMesg, "/&MSG=");
if (pStart != NULL)
{
pStart += 6; // skip to start of data
pEnd = strstr(pStart, "/&");
if (pEnd != NULL)
{
while (pStart != pEnd)
{
if ((*pStart == '%') && isdigit(*(pStart+1)))
{
// replace %xx hex code with the ASCII character
char c = 0;
pStart++;
c += (htoi(*pStart++) << 4);
c += htoi(*pStart++);
*psz++ = c;
}
else
*psz++ = *pStart++;
}
*psz = '\0'; // terminate the string
isValid = true;
}
}
return(isValid);
}
void handleWiFi(void)
{
static enum { S_IDLE, S_WAIT_CONN, S_READ, S_EXTRACT, S_RESPONSE, S_DISCONN } state = S_IDLE;
static char szBuf[1024];
static uint16_t idxBuf = 0;
static WiFiClient client;
static uint32_t timeStart;
switch (state)
{
case S_IDLE: // initialise
PRINTS("\nS_IDLE");
idxBuf = 0;
state = S_WAIT_CONN;
break;
case S_WAIT_CONN: // waiting for connection
{
client = server.available();
if (!client) break;
if (!client.connected()) break;
#if DEBUG
char szTxt[20];
sprintf(szTxt, "%03d:%03d:%03d:%03d", client.remoteIP()[0], client.remoteIP()[1], client.remoteIP()[2], client.remoteIP()[3]);
PRINT("\nNew client @ ", szTxt);
#endif
timeStart = millis();
state = S_READ;
}
break;
case S_READ: // get the first line of data
PRINTS("\nS_READ");
while (client.available())
{
char c = client.read();
if ((c == '\r') || (c == '\n'))
{
szBuf[idxBuf] = '\0';
client.flush();
PRINT("\nRecv: ", szBuf);
state = S_EXTRACT;
}
else
szBuf[idxBuf++] = (char)c;
}
if (millis() - timeStart > 1000)
{
PRINTS("\nWait timeout");
state = S_DISCONN;
}
break;
case S_EXTRACT: // extract data
PRINTS("\nS_EXTRACT");
// Extract the string from the message if there is one
newMessageAvailable = getText(szBuf, newMessage, MESG_SIZE);
PRINT("\nNew Msg: ", newMessage);
state = S_RESPONSE;
break;
case S_RESPONSE: // send the response to the client
PRINTS("\nS_RESPONSE");
// Return the response to the client (web page)
client.print(WebResponse);
client.print(WebPage);
state = S_DISCONN;
break;
case S_DISCONN: // disconnect client
PRINTS("\nS_DISCONN");
client.flush();
client.stop();
state = S_IDLE;
break;
default: state = S_IDLE;
}
}
void scrollDataSink(uint8_t dev, MD_MAX72XX::transformType_t t, uint8_t col)
// Callback function for data that is being scrolled off the display
{
#if PRINT_CALLBACK
Serial.print("\n cb ");
Serial.print(dev);
Serial.print(' ');
Serial.print(t);
Serial.print(' ');
Serial.println(col);
#endif
}
uint8_t scrollDataSource(uint8_t dev, MD_MAX72XX::transformType_t t)
// Callback function for data that is required for scrolling into the display
{
static enum { S_IDLE, S_NEXT_CHAR, S_SHOW_CHAR, S_SHOW_SPACE } state = S_IDLE;
static char *p;
static uint16_t curLen, showLen;
static uint8_t cBuf[8];
uint8_t colData = 0;
// finite state machine to control what we do on the callback
switch (state)
{
case S_IDLE: // reset the message pointer and check for new message to load
PRINTS("\nS_IDLE");
p = curMessage; // reset the pointer to start of message
if (newMessageAvailable) // there is a new message waiting
{
strcpy(curMessage, newMessage); // copy it in
newMessageAvailable = false;
}
state = S_NEXT_CHAR;
break;
case S_NEXT_CHAR: // Load the next character from the font table
PRINTS("\nS_NEXT_CHAR");
if (*p == '\0')
state = S_IDLE;
else
{
showLen = mx.getChar(*p++, sizeof(cBuf) / sizeof(cBuf[0]), cBuf);
curLen = 0;
state = S_SHOW_CHAR;
}
break;
case S_SHOW_CHAR: // display the next part of the character
PRINTS("\nS_SHOW_CHAR");
colData = cBuf[curLen++];
if (curLen < showLen)
break;
// set up the inter character spacing
showLen = (*p != '\0' ? CHAR_SPACING : (MAX_DEVICES*COL_SIZE)/2);
curLen = 0;
state = S_SHOW_SPACE;
// fall through
case S_SHOW_SPACE: // display inter-character spacing (blank column)
PRINT("\nS_ICSPACE: ", curLen);
PRINT("/", showLen);
curLen++;
if (curLen == showLen)
state = S_NEXT_CHAR;
break;
default:
state = S_IDLE;
}
return(colData);
}
void scrollText(void)
{
static uint32_t prevTime = 0;
// Is it time to scroll the text?
if (millis() - prevTime >= SCROLL_DELAY)
{
mx.transform(MD_MAX72XX::TSL); // scroll along - the callback will load all the data
prevTime = millis(); // starting point for next time
}
}
void setup()
{
#if DEBUG
Serial.begin(115200);
PRINTS("\n[MD_MAX72XX WiFi Message Display]\nType a message for the scrolling display from your internet browser");
#endif
#if LED_HEARTBEAT
pinMode(HB_LED, OUTPUT);
digitalWrite(HB_LED, LOW);
#endif
// Display initialisation
mx.begin();
mx.setShiftDataInCallback(scrollDataSource);
mx.setShiftDataOutCallback(scrollDataSink);
curMessage[0] = newMessage[0] = '\0';
// Connect to and initialise WiFi network
PRINT("\nConnecting to ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
PRINT("\n", err2Str(WiFi.status()));
delay(500);
}
PRINTS("\nWiFi connected");
// Start the server
server.begin();
PRINTS("\nServer started");
// Set up first message as the IP address
sprintf(curMessage, "%03d:%03d:%03d:%03d", WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3]);
PRINT("\nAssigned IP ", curMessage);
}
void loop()
{
#if LED_HEARTBEAT
static uint32_t timeLast = 0;
if (millis() - timeLast >= HB_LED_TIME)
{
digitalWrite(HB_LED, digitalRead(HB_LED) == LOW ? HIGH : LOW);
timeLast = millis();
}
#endif
handleWiFi();
scrollText();
}
How to solve mirror image and orientation problems of matrix display if you are using old MD_MAX72xx library.
This project is about moving LED matrix display. In this project we will use MAX7219 8×8 LED module for display, Arduino UNO for brain and Bluetooth serial module for communication. You will need an Android phone for controlling this display.
Things you will need:
Circuit Diagram:
Code :
/* 8x8 LED Matrix MAX7219 Scrolling Text Android Control via Bluetooth */ #include <MaxMatrix.h> #include <SoftwareSerial.h> #include <avr/pgmspace.h> PROGMEM const unsigned char CH[] = { 3, 8, B00000000, B00000000, B00000000, B00000000, B00000000, // space 1, 8, B01011111, B00000000, B00000000, B00000000, B00000000, // ! 3, 8, B00000011, B00000000, B00000011, B00000000, B00000000, // " 5, 8, B00010100, B00111110, B00010100, B00111110, B00010100, // # 4, 8, B00100100, B01101010, B00101011, B00010010, B00000000, // $ 5, 8, B01100011, B00010011, B00001000, B01100100, B01100011, // % 5, 8, B00110110, B01001001, B01010110, B00100000, B01010000, // & 1, 8, B00000011, B00000000, B00000000, B00000000, B00000000, // ' 3, 8, B00011100, B00100010, B01000001, B00000000, B00000000, // ( 3, 8, B01000001, B00100010, B00011100, B00000000, B00000000, // ) 5, 8, B00101000, B00011000, B00001110, B00011000, B00101000, // * 5, 8, B00001000, B00001000, B00111110, B00001000, B00001000, // + 2, 8, B10110000, B01110000, B00000000, B00000000, B00000000, // , 4, 8, B00001000, B00001000, B00001000, B00001000, B00000000, // - 2, 8, B01100000, B01100000, B00000000, B00000000, B00000000, // . 4, 8, B01100000, B00011000, B00000110, B00000001, B00000000, // / 4, 8, B00111110, B01000001, B01000001, B00111110, B00000000, // 0 3, 8, B01000010, B01111111, B01000000, B00000000, B00000000, // 1 4, 8, B01100010, B01010001, B01001001, B01000110, B00000000, // 2 4, 8, B00100010, B01000001, B01001001, B00110110, B00000000, // 3 4, 8, B00011000, B00010100, B00010010, B01111111, B00000000, // 4 4, 8, B00100111, B01000101, B01000101, B00111001, B00000000, // 5 4, 8, B00111110, B01001001, B01001001, B00110000, B00000000, // 6 4, 8, B01100001, B00010001, B00001001, B00000111, B00000000, // 7 4, 8, B00110110, B01001001, B01001001, B00110110, B00000000, // 8 4, 8, B00000110, B01001001, B01001001, B00111110, B00000000, // 9 2, 8, B01010000, B00000000, B00000000, B00000000, B00000000, // : 2, 8, B10000000, B01010000, B00000000, B00000000, B00000000, // ; 3, 8, B00010000, B00101000, B01000100, B00000000, B00000000, // < 3, 8, B00010100, B00010100, B00010100, B00000000, B00000000, // = 3, 8, B01000100, B00101000, B00010000, B00000000, B00000000, // > 4, 8, B00000010, B01011001, B00001001, B00000110, B00000000, // ? 5, 8, B00111110, B01001001, B01010101, B01011101, B00001110, // @ 4, 8, B01111110, B00010001, B00010001, B01111110, B00000000, // A 4, 8, B01111111, B01001001, B01001001, B00110110, B00000000, // B 4, 8, B00111110, B01000001, B01000001, B00100010, B00000000, // C 4, 8, B01111111, B01000001, B01000001, B00111110, B00000000, // D 4, 8, B01111111, B01001001, B01001001, B01000001, B00000000, // E 4, 8, B01111111, B00001001, B00001001, B00000001, B00000000, // F 4, 8, B00111110, B01000001, B01001001, B01111010, B00000000, // G 4, 8, B01111111, B00001000, B00001000, B01111111, B00000000, // H 3, 8, B01000001, B01111111, B01000001, B00000000, B00000000, // I 4, 8, B00110000, B01000000, B01000001, B00111111, B00000000, // J 4, 8, B01111111, B00001000, B00010100, B01100011, B00000000, // K 4, 8, B01111111, B01000000, B01000000, B01000000, B00000000, // L 5, 8, B01111111, B00000010, B00001100, B00000010, B01111111, // M 5, 8, B01111111, B00000100, B00001000, B00010000, B01111111, // N 4, 8, B00111110, B01000001, B01000001, B00111110, B00000000, // O 4, 8, B01111111, B00001001, B00001001, B00000110, B00000000, // P 4, 8, B00111110, B01000001, B01000001, B10111110, B00000000, // Q 4, 8, B01111111, B00001001, B00001001, B01110110, B00000000, // R 4, 8, B01000110, B01001001, B01001001, B00110010, B00000000, // S 5, 8, B00000001, B00000001, B01111111, B00000001, B00000001, // T 4, 8, B00111111, B01000000, B01000000, B00111111, B00000000, // U 5, 8, B00001111, B00110000, B01000000, B00110000, B00001111, // V 5, 8, B00111111, B01000000, B00111000, B01000000, B00111111, // W 5, 8, B01100011, B00010100, B00001000, B00010100, B01100011, // X 5, 8, B00000111, B00001000, B01110000, B00001000, B00000111, // Y 4, 8, B01100001, B01010001, B01001001, B01000111, B00000000, // Z 2, 8, B01111111, B01000001, B00000000, B00000000, B00000000, // [ 4, 8, B00000001, B00000110, B00011000, B01100000, B00000000, // \ backslash 2, 8, B01000001, B01111111, B00000000, B00000000, B00000000, // ] 3, 8, B00000010, B00000001, B00000010, B00000000, B00000000, // hat 4, 8, B01000000, B01000000, B01000000, B01000000, B00000000, // _ 2, 8, B00000001, B00000010, B00000000, B00000000, B00000000, // ` 4, 8, B00100000, B01010100, B01010100, B01111000, B00000000, // a 4, 8, B01111111, B01000100, B01000100, B00111000, B00000000, // b 4, 8, B00111000, B01000100, B01000100, B00101000, B00000000, // c 4, 8, B00111000, B01000100, B01000100, B01111111, B00000000, // d 4, 8, B00111000, B01010100, B01010100, B00011000, B00000000, // e 3, 8, B00000100, B01111110, B00000101, B00000000, B00000000, // f 4, 8, B10011000, B10100100, B10100100, B01111000, B00000000, // g 4, 8, B01111111, B00000100, B00000100, B01111000, B00000000, // h 3, 8, B01000100, B01111101, B01000000, B00000000, B00000000, // i 4, 8, B01000000, B10000000, B10000100, B01111101, B00000000, // j 4, 8, B01111111, B00010000, B00101000, B01000100, B00000000, // k 3, 8, B01000001, B01111111, B01000000, B00000000, B00000000, // l 5, 8, B01111100, B00000100, B01111100, B00000100, B01111000, // m 4, 8, B01111100, B00000100, B00000100, B01111000, B00000000, // n 4, 8, B00111000, B01000100, B01000100, B00111000, B00000000, // o 4, 8, B11111100, B00100100, B00100100, B00011000, B00000000, // p 4, 8, B00011000, B00100100, B00100100, B11111100, B00000000, // q 4, 8, B01111100, B00001000, B00000100, B00000100, B00000000, // r 4, 8, B01001000, B01010100, B01010100, B00100100, B00000000, // s 3, 8, B00000100, B00111111, B01000100, B00000000, B00000000, // t 4, 8, B00111100, B01000000, B01000000, B01111100, B00000000, // u 5, 8, B00011100, B00100000, B01000000, B00100000, B00011100, // v 5, 8, B00111100, B01000000, B00111100, B01000000, B00111100, // w 5, 8, B01000100, B00101000, B00010000, B00101000, B01000100, // x 4, 8, B10011100, B10100000, B10100000, B01111100, B00000000, // y 3, 8, B01100100, B01010100, B01001100, B00000000, B00000000, // z 3, 8, B00001000, B00110110, B01000001, B00000000, B00000000, // { 1, 8, B01111111, B00000000, B00000000, B00000000, B00000000, // | 3, 8, B01000001, B00110110, B00001000, B00000000, B00000000, // } 4, 8, B00001000, B00000100, B00001000, B00000100, B00000000, // ~ }; int dIn = 7; // DIN pin of MAX7219 module int clk = 6; // CLK pin of MAX7219 module int cs = 5; // CS pin of MAX7219 module int maxInUse = 2; // Number of MAX7219's connected MaxMatrix m(dIn, cs, clk, maxInUse); SoftwareSerial Bluetooth(8, 7); // Bluetooth byte buffer[10]; char incomebyte; int scrollSpeed = 100; char text[100] = "www.etechpath.com "; // Initial text message int brightness = 15; int count = 0; char indicator; void setup() { m.init(); // MAX7219 initialization m.setIntensity(brightness); // initial led matrix intensity, 0-15 Bluetooth.begin(38400); // Default communication rate of the Bluetooth module } void loop() { // Printing the text printStringWithShift(text, scrollSpeed); if (Bluetooth.available()) { // Checks whether data is comming from the serial port indicator = Bluetooth.read(); // Starts reading the serial port, the first byte from the incoming data // If we have pressed the "Send" button from the Android App, clear the previous text if (indicator == '1') { for (int i = 0; i < 100; i++) { text[i] = 0; m.clear(); } // Read the whole data/string comming from the phone and put it into text[] array. while (Bluetooth.available()) { incomebyte = Bluetooth.read(); text[count] = incomebyte; count++; } count = 0; } // Adjusting the Scrolling Speed else if (indicator == '2') { String sS = Bluetooth.readString(); scrollSpeed = 150 - sS.toInt(); // Milliseconds, subtraction because lower value means higher scrolling speed } // Adjusting the brightness else if (indicator == '3') { String sB = Bluetooth.readString(); brightness = sB.toInt(); m.setIntensity(brightness); } } } void printCharWithShift(char c, int shift_speed) { if (c < 32) return; c -= 32; memcpy_P(buffer, CH + 7 * c, 7); m.writeSprite(32, 0, buffer); m.setColumn(32 + buffer[0], 0); for (int i = 0; i < buffer[0] + 1; i++) { delay(shift_speed); m.shiftLeft(false, false); } } void printStringWithShift(char* s, int shift_speed) { while (*s != 0) { printCharWithShift(*s, shift_speed); s++; } } void printString(char* s) { int col = 0; while (*s != 0) { if (*s < 32) continue; char c = *s - 32; memcpy_P(buffer, CH + 7 * c, 7); m.writeSprite(col, 0, buffer); m.setColumn(col + buffer[0], 0); col += buffer[0] + 1; s++; } }
Steps :
Downloads :
Check this WiFi controlled MAX7219 LED Matrix using ESP-12 NodeMCU module