Wireless Notice Board Using ESP8266 & Matrix Display

This project deals with an innovative and visual method of conveying the message to the people using a wireless notice board which is developed using WiFi technology. This will help us show any electronic message almost immediately with negligible delay just by sending a short message from the mobile application. That is better and more reliable than the old traditional way of passing the news on the notice board.

In today’s world, mobile phones and related technologies are becoming more and more popular. Various technical arenas in the field of Telecommunication and Embedded Systems are becoming upright to the people. Notice boards are one of the widely used ones ranging from primary schools to significant organizations to convey messages to large groups of people. A lot of paper is being used and which is later just to get wasted. It leads to a lot of deforestation, thus leading to global warming. A small innovative step in making use of technology for regular purposes would have an adverse effect on the environmental issues with which we are presently concerned.

The aim of this project is how to make a web-controlled Wireless Notice Board using ESP8266 NodeMCU and Dot Matrix Display. In our project, the ESP8266 NodeMCU establishes a strong connection between a WiFi network and the board itself and generates a webpage given by a local IP address. Using the Web dashboard, we can send any message by just typing in the blank space. And the NodeMCU will display it on the Dot Matrix Display as well.

I will recommend you to check out our another IoT Projects.


Wireless Notice Board

Circuit Diagram

Wireless Notice Board Circuit Diagram

Components Required

  • ESP8266 NodeMCU
  • 4:1 MAX7219 Dot Matrix Display
  • 7805 Regulator
  • Capacitor (10uF/16V, 100uF/25V)
  • Connection Wire
  • Veroboard
  • 5 Volt Power Source

About Parts of the Wireless Notice Board

Dot Matrix Display


LED matrices are available in the market in different colours like single colour, dual colour, and RGB colour. They are also available in different dimensions like 5×7, 8×8, 16×16, 8×32, 32×32, and more.


This 8×32 LED Matrix Display is a multitude of 4 single Matrix Displays which are internally connected. These displays also have the ability to separate from each other, as every module carries the same Maxim MAX7219 chip, and can be connected with the same power and data connection. That’s why if any of the single displays get damaged, they will be easily replaceable.

MAX7219 LED Driver Chip

This Matrix Displays can be driven in two ways. One is a parallel way where the parallel data is sent to each row or column. The second one is the serial way where the data is sent serially and an IC is used to convert this serial data into parallel data.

MAX7219 Dot Matrix LED Driver IC

MAX7219 is a common cathode display driver with serial input and parallel output. It is used to interface microprocessors and microcontrollers with 64 individual LEDs. The 8×8 LED matrix is connected to the MAX 7219. The data input is received from the Arduino board to the MAX7219.

Circuit Connection of Wireless Notice Board

The left side of the Dot Matrix Display is basically for the input pins which are connected to any GPIO pins of a microcontroller. Similarly, the right side of the display is the output port for adding additional displays.

From the left side, connect the VCC and GND of the Dot Matrix Display to the 3.3V and GND of the ESP8266 board. The default SPI and GPIO pins of the ESP8266 are being used to connect with each of the remaining SPI terminals of the MAX7219 display module. Therefore, connect the DIN, CS, and CLK pins to the ESP8266 board’s D7, D8, and D5 pins.

NodeMCU Code

To compile this below code, you have to install these two library files into your Arduino IDE.



After uploading the code to ESP8266, you can see the IP address on the Dot Matrix Display for entering the webpage.

#include <ESP8266WiFi.h>#include <MD_Parola.h>#include <MD_MAX72xx.h>#include <SPI.h>// Turn on debug statements to the serial output#define  DEBUG  0#if  DEBUG#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }#define PRINTS(x) Serial.print(F(x))#define PRINTX(x) Serial.println(x, HEX)#else#define PRINT(s, x)#define PRINTS(x)#define PRINTX(x)#endif#define HARDWARE_TYPE MD_MAX72XX::FC16_HW#define MAX_DEVICES 4  //Maximum single module connected#define CS_PIN    15// HARDWARE SPIMD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);// WiFi network SSID and Passconst char* ssid = "**********";const char* password = "**********";// WiFi Server object and parametersWiFiServer server(80);// Scrolling parametersuint8_t frameDelay = 25;  // default frame delay valuetextEffect_t  scrollEffect = PA_SCROLL_LEFT;// Global message buffers shared by Wifi and Scrolling functions#define BUF_SIZE  512char curMessage[BUF_SIZE];char newMessage[BUF_SIZE];bool newMessageAvailable = false;const char WebResponse[] = "HTTP/1.1 200 OK\nContent-Type: text/html\n\n";const char WebPage[] =  "<!DOCTYPE html>" \  "<html>" \  "<center>" \  "<head>" \  "<title>Electro Gadget</title>" \  "<script>" \  "strLine = \"\";" \  "function SendData()" \  "{" \  "  nocache = \"/&nocache=\" + Math.random() * 1000000;" \  "  var request = new XMLHttpRequest();" \  "  strLine = \"&MSG=\" + document.getElementById(\"data_form\").Message.value;" \  "  strLine = strLine + \"/&SD=\" + document.getElementById(\"data_form\").ScrollType.value;" \  "  strLine = strLine + \"/&I=\" + document.getElementById(\"data_form\").Invert.value;" \  "  strLine = strLine + \"/&SP=\" + document.getElementById(\"data_form\").Speed.value;" \  "  request.open(\"GET\", strLine + nocache, false);" \  "  request.send(null);" \  "}" \  "</script>" \  "</head>" \  "<body>" \  "<p><font size=\"6\"><b>Wireless Notice Board</b></font></p>" \  "<form id=\"data_form\" name=\"frmText\">" \  "<label><font size=\"4\"><b>Type Your Message</b></font><br><input type=\"text\" name=\"Message\" maxlength=\"255\"></label>" \  "<br><br>" \  "<input type = \"radio\" name = \"Invert\" value = \"0\" checked> Normal" \  "<input type = \"radio\" name = \"Invert\" value = \"1\"> Inverse" \  "<br>" \  "<input type = \"radio\" name = \"ScrollType\" value = \"L\" checked> Left Scroll" \  "<input type = \"radio\" name = \"ScrollType\" value = \"R\"> Right Scroll" \  "<br><br>" \  "<label>Speed<br>Fast<input type=\"range\" name=\"Speed\"min=\"10\" max=\"200\">Slow"\  "<br>" \  "</form>" \  "<br>" \  "<input type=\"submit\" value=\"Send Data\" onclick=\"SendData()\">" \  "</body>" \  "</html>";const 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);}void getData(char *szMesg, uint16_t len)// Message may contain data for:// New text (/&MSG=)// Scroll direction (/&SD=)// Invert (/&I=)// Speed (/&SP=){  char *pStart, *pEnd;      // pointer to start and end of text  // check text message  pStart = strstr(szMesg, "/&MSG=");  if (pStart != NULL)  {    char *psz = newMessage;    pStart += 6;  // skip to start of data    pEnd = strstr(pStart, "/&");    if (pEnd != NULL)    {      while (pStart != pEnd)      {        if ((*pStart == '%') && isxdigit(*(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      newMessageAvailable = (strlen(newMessage) != 0);      PRINT("\nNew Msg: ", newMessage);    }  }  // check scroll direction  pStart = strstr(szMesg, "/&SD=");  if (pStart != NULL)  {    pStart += 5;  // skip to start of data    PRINT("\nScroll direction: ", *pStart);    scrollEffect = (*pStart == 'R' ? PA_SCROLL_RIGHT : PA_SCROLL_LEFT);    P.setTextEffect(scrollEffect, scrollEffect);    P.displayReset();  }  // check invert  pStart = strstr(szMesg, "/&I=");  if (pStart != NULL)  {    pStart += 4;  // skip to start of data    PRINT("\nInvert mode: ", *pStart);    P.setInvert(*pStart == '1');  }  // check speed  pStart = strstr(szMesg, "/&SP=");  if (pStart != NULL)  {    pStart += 5;  // skip to start of data    int16_t speed = atoi(pStart);    PRINT("\nSpeed: ", P.getSpeed());    P.setSpeed(speed);    frameDelay = speed;  }}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      getData(szBuf, BUF_SIZE);      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 setup(){  Serial.begin(57600);  PRINTS("\n[MD_Parola WiFi Message Display]\nType a message for the scrolling display from your internet browser");  P.begin();  P.setIntensity(0);  P.displayClear();  P.displaySuspend(false);  P.displayScroll(curMessage, PA_LEFT, scrollEffect, frameDelay);  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(){  handleWiFi();  if (P.displayAnimate())  {    if (newMessageAvailable)    {      strcpy(curMessage, newMessage);      newMessageAvailable = false;    }    P.displayReset();  }}

Post a Comment

Previous Post Next Post