top of page
Writer's pictureRamesh G

IoT Based Notice Board Using Dot Matrix Display

Updated: Jul 2, 2021



Wifi Controlled Display Board, In this tutorial, you will learn how to make an IOT “Internet of Things” based Notice Board using Nodemcu ESP8266 Wifi Module and Max7219 8×8 LED Matrix and to update a message via Wifi network Through a web page. The scrolling text message on the 8×8 LED Matrix can be updated at any time from local Web server.


Circuit diagram



components Required

  • NodeMCU ESP8266 12E

  • MAX7219 dot matrix Module 4 in 1 - 2 nos

  • Jumper Wires

  • Breadboard (optional)

MAX7219 4-in-1 Display Dot Matrix Module

This Module is an integrated serial input/output common-cathode display driver, it connects the microprocessor 7-segment digital LED display with 8 digits, you can also connect a bar graph display or 64 independent LED. Thereon including a B-type BCD encoder chip, multi-channel scanning loop segment word driver, but also a static RAM 8 x 8 for storing each data. Only one external register is used to set the segment current of each LED.


Specifications and Features:-

Dimensions: 128 x 32 x 1.5cm(LxWxH)(All 4 in 1) Dimension 32 x 32 x 1.5 cm (LxWxH) (Single Module) A single module can drive an 8×8 dot matrix common cathode Operating voltage: 5V Weight: 55 gm Fixing screws with 64 holes with a diameter 3mm Module with input and output interfaces Support for cascading multiple modules

Wiring Instructions:-

The left side of the module to the input port, the right to an output port.

When the control of a single module, simply input port connected to CPU

When a plurality of cascaded modules, input and output termination CPU, an input terminal of the second output end of the first module a module, the first two modules of the input terminal of the three termination modules, and so on..


Pin Description:-

VCC 5V GND GND DIN P2.2 CS P2.1 CLK P2.0


Installing Libraries

To install the library navigate to the Sketch > Include Library > Manage Libraries

Wait for Library Manager to download libraries index and update list of installed libraries.

And install MAX72xx Libraries.


Subscribe and Download code.

arduino Code


// Connections for ESP8266 hardware SPI are:

// Vcc 3v3 LED matrices seem to work at 3.3V

// GND GND GND

// DIN D7 HSPID or HMOSI

// CS or LD D8 HSPICS or HCS

// CLK D5 CLK or HCLK



#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)); }

#define PRINT(s, v)

#define PRINTS(s)



#if LED_HEARTBEAT

#define HB_LED D2

#define HB_LED_TIME 500 // in milliseconds


// Define the number of devices we have in the chain and the hardware interface

// NOTE: These pin numbers will probably not work with your hardware and may

// need to be adapted

//#define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW

#define HARDWARE_TYPE MD_MAX72XX::FC16_HW

#define MAX_DEVICES 8 // your connected no of display change it here


#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(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 = "TP-Link_3200"; // your SSID

const char* password = "9500112137"; // your WIFi Password


// 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>Wifi Display</title>" \


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

"<Center>"\

"<h1>IOT Based Notice Board Using Dot Matrix LED Display</h1>" \


"<form id=\"txt_form\" name=\"frmText\">" \

"<label>Type Your Message:<input type=\"text\" name=\"Message\" size=\"100\" maxlength=\"255\"></label><br><br>" \

"</form>" \

"<br>" \

"<input type=\"submit\" value=\"Send Message\" onclick=\"SendText()\">" \

"<Center>"\

"</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);


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

}


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");


#if LED_HEARTBEAT

pinMode(HB_LED, OUTPUT);

digitalWrite(HB_LED, LOW);


// 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();

}


handleWiFi();

scrollText();

}


Result

hen, upload the code to your NodeMCU board. Make sure you have selected the right board and COM port. Also, make sure you’ve inserted your WiFi Credentials in the code. After a successful upload, open the Serial Monitor at a baud rate of 115200. Press the “EN/RST” button on the ESP8266 board.

Now the IP address is Shown in Dot Matrix Display.


Click Web Browser and type IP address in the bar. Enter the message and hit Send Message button.



821 views0 comments

Comments


bottom of page