Overview
In this tutorial, we will learn how to make a Web Controlled Smart Notice Board with ESP8266 & Dot Matrix LED Display.
The traditional methods of writing the notice on paper, and having a person deliver the information to the respective groups, or having him paste the notice on the notice board, are prone to errors. The person delivering could deliver it to the wrong group, or tamper with the information being sent, etc.
With the electronics industry moving at a fast pace, we are able to solve many such problems with digital replacements. Our project, Smart Notice Board, aims at eliminating the use of paper in offices, schools & colleges, and other institutions. It also minimizes the risk of errors, by replacing paper with Dot Matrix LED displays.
In our project, the ESP8266 WiFi Module can be interfaced with an 8-in-1 MAX7219 Dot Matrix LED Display. The ESP8266 connects to a WiFi Network and generates a Web page. We can access the web page using the local IP Address of NodeMCU ESP8266. Using the Web Dashboard, we can send any message and display it on Dot Matrix LED Display.
Before moving ahead you can check some of our previous post to get started with Dot Matrix LED Display:
Bill of Materials
We need the following components to make the Smart Notice Board Project.
| S.N. | Components Name | Quantity | Purchase Links |
|---|---|---|---|
| 1 | NodeMCU ESP8266 Board | 1 | Amazon | AliExpress |
| 2 | 8-in-1 MAX7219 Dot Matrix LED Display | 1 | Amazon | AliExpress |
| 3 | Jumper Wires | 5 | Amazon | AliExpress |
| 4 | Breadboard | 1 | Amazon | AliExpress |
| 5 | Micro-USB Data Cable | 1 | Amazon | AliExpress |
Dot Matrix LED Display
LED matrices are available in different styles like single color, dual color, multi-color, or RGB LED matrix. They are also available in different dimensions like 5 x 7, 8 x 8, 16 x 16, 8 x 32, 32 x 32 etc.
This 8×64 LED Matrix Display is a cluster of 8 single modules, internally connected. These modules can also be separated, because every module carries the same Maxim MAX7219 chip, and comes with the same power and data connection.
Pin Configuration
The 8×8 LED matrix have 8 positive terminal & 8 negative terminals. The 8 negative terminals are 8 columns & 8 positive terminal are 8 rows.
The 8-in-1 8X8 LED Matrix are connected to each other via the MAX7219 Pins.
MAX7219 LED Driver IC
The LED matrix can be driven in two ways. They are parallel (where each row or column is sent with parallel data) and serial (where the data is sent serially and an IC is used to convert this serial data into parallel data).
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 x 8 LED matrix is connected to the MAX 7219. The data input is received from the Arduino board to the MAX7219.
Smart Notice Board with ESP8266 & Dot Matrix LED Display
Let us take a look at the hardware of the project. The hardware part is a combination of an 8-in-1 Dot Matrix LED Display and ESP8266 WiFi Module.
The left side of the display is basically for the input port which is connected to any GPIO pins of a Microcontroller. Similarly, the right side of the display is the output port which is used for expanding or adding additional LED Display.
From the left side, connect the VCC, GND of Dot Matrix Display to 3.3V & GND of NodeMCU Board. The default SPI GPIO pins of ESP8266 are being used to connect with each of the remaining SPI terminals of the MAX7219 module. Therefore, connect the DIN, CS, and CLK pin to the NodeMCU D7, D8 & D5 Pin.
Project PCB Gerber File & PCB Ordering Online
If you don’t want to assemble the circuit on a zero PCB and you want PCB for the project, then here is the PCB for you. I used EasyEDA to draw the schematic first. Then I converted the schematic to PCB. The PCB Board for this project looks something like below.
The Gerber File for the PCB is given below. You can simply download the Gerber File and order the PCB from ALLPCB at 1$ only.
You can use this Gerber file to order high quality PCB for this project. To do that visit the ALLPCB official website by clicking here: https://www.allpcb.com/.
You can now upload the Gerber File by choosing the Quote Now option. From these options, you can choose the Material Type, Dimensions, Quantity, Thickness, Solder Mask Color and other required parameters.
After filling all details, select your country and shipping method. Finally you can place the order.
You can assemble the components on the PCB Board.
Source Code/program
The program for the Smart Notice Board is taken from the library example. This code includes the WiFi Library for enabling the Nodemcu to create a webserver over a Wifi network. It also include the MD_MAX72xx & Parola Library for controlling the Led matrix & generating various LED Effect.
You can also change the design and appearance of the web page by changing the HTML and CSS part of the code. Only do this if you have prior knowledge of web development and design otherwise the web page may not be displayed.
From the following lines, change the WiFi SSID & Password.
|
1 2 3 |
// WiFi login parameters - network name and password const char* ssid = "***********"; const char* password = "***********"; |
Connect a Micro-USB Cable to your NodeMCU ESP8266 Board and upload the following code to it.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 |
#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 8 #define CS_PIN 15 // or SS // HARDWARE SPI MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES); // WiFi login parameters - network name and password const char* ssid = "***********"; const char* password = "***********"; // WiFi Server object and parameters WiFiServer server(80); // Scrolling parameters uint8_t frameDelay = 25; // default frame delay value textEffect_t scrollEffect = PA_SCROLL_LEFT; // Global message buffers shared by Wifi and Scrolling functions #define BUF_SIZE 512 char 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>" \ "<head>" \ "<title>MajicDesigns Test Page</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><b>Smart Notice Board</b></p>" \ "<form id=\"data_form\" name=\"frmText\">" \ "<label>Message:<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(); } } |
Testing the ESP8266 Smart Notice Board
Now let us test the working and demo of Smart Notice Board with ESP8266 & Dot Matrix LED Display. After uploading the code, the ESP8266 will connect to the WiFi Network using the WiFi Credentials. The Dot Matrix LED Display will show the IP Address after a successful connection.
Open your Web Browser and enter the IP Address. The browser will display the following page.
From the Web Page enter any message that you want to display on DoT Matrix Display as a Notice. Then hit send button. The Dot Matrix will show the new message in few seconds.
You can change the scrolling effect from left to right or from right to left. You can also change the scrolling speed and reverse the LED Display.
In conclusion we can say that this display can be easily integrated with all general-purpose display board thus proving its mobility. The message is transferred using wireless technology and is eventually obtained on the LED matrix. Thus we can use modern technology to replace conventional display boards & the Web Server interface can make this system even more user-friendly and popular.






















2 Comments
hi , can we reduce the number of led?
Bill of Materials for the PCB please