Advertisement
Guest User

Untitled

a guest
Oct 17th, 2018
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.91 KB | None | 0 0
  1. // Use the MD_MAX72XX library to scroll text on the display
  2. // received through the ESP8266 WiFi interface.
  3. //
  4. // Demonstrates the use of the callback function to control what
  5. // is scrolled on the display text. User can enter text through
  6. // a web browser and this will display as a scrolling message on
  7. // the display.
  8. //
  9. // IP address for the ESP8266 is displayed on the scrolling display
  10. // after startup initialization and connected to the WiFi network.
  11. //
  12. // Connections for ESP8266 hardware SPI are:
  13. // Vcc 3v3 LED matrices seem to work at 3.3V
  14. // GND GND GND
  15. // DIN D7 HSPID or HMOSI
  16. // CS or LD D8 HSPICS or HCS
  17. // CLK D5 CLK or HCLK
  18. //
  19.  
  20. #include <ESP8266WiFi.h>
  21. #include <MD_MAX72xx.h>
  22. #include <SPI.h>
  23. #include <time.h>
  24.  
  25. #include <TimeLib.h>
  26. #include <WiFiUdp.h>
  27.  
  28. // NTP Servers:
  29. static const char ntpServerName[] = "sg.pool.ntp.org";
  30. //static const char ntpServerName[] = "time.nist.gov";
  31. //static const char ntpServerName[] = "time-a.timefreq.bldrdoc.gov";
  32. //static const char ntpServerName[] = "time-b.timefreq.bldrdoc.gov";
  33. //static const char ntpServerName[] = "time-c.timefreq.bldrdoc.gov";
  34.  
  35. const int timeZone = +8; // Central European Time
  36. //const int timeZone = -5; // Eastern Standard Time (USA)
  37. //const int timeZone = -4; // Eastern Daylight Time (USA)
  38. //const int timeZone = -8; // Pacific Standard Time (USA)
  39. //const int timeZone = -7; // Pacific Daylight Time (USA)
  40.  
  41.  
  42. WiFiUDP Udp;
  43. unsigned int localPort = 8888; // local port to listen for UDP packets
  44.  
  45. time_t getNtpTime();
  46. void digitalClockDisplay();
  47. void printDigits(int digits);
  48. void sendNTPpacket(IPAddress &address);
  49.  
  50.  
  51. #define PRINT_CALLBACK 0
  52. #define DEBUG 0
  53. #define LED_HEARTBEAT 0
  54.  
  55. #if DEBUG
  56. #define PRINT(s, v) { Serial.print(F(s)); Serial.print(v); }
  57. #define PRINTS(s) { Serial.print(F(s)); }
  58. #else
  59. #define PRINT(s, v)
  60. #define PRINTS(s)
  61. #endif
  62.  
  63.  
  64. #if LED_HEARTBEAT
  65. #define HB_LED D2
  66. #define HB_LED_TIME 800 // in milliseconds
  67. #endif
  68.  
  69. // Define the number of devices we have in the chain and the hardware interface
  70. // NOTE: These pin numbers will probably not work with your hardware and may
  71. // need to be adapted
  72. #define HARDWARE_TYPE MD_MAX72XX::FC16_HW
  73. #define MAX_DEVICES 8
  74.  
  75. #define CLK_PIN D5 // or SCK
  76. #define DATA_PIN D7 // or MOSI
  77. #define CS_PIN D8 // or SS
  78.  
  79. // SPI hardware interface
  80. MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
  81. // Arbitrary pins
  82. //MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
  83.  
  84. // WiFi login parameters - network name and password
  85. const char* ssid = "pv6";
  86. const char* password = "amenhype";
  87.  
  88.  
  89. // WiFi Server object and parameters
  90. WiFiServer server(80);
  91.  
  92. // Global message buffers shared by Wifi and Scrolling functions
  93. const uint8_t MESG_SIZE = 255;
  94. const uint8_t CHAR_SPACING = 1;
  95. const uint8_t SCROLL_DELAY = 100;
  96.  
  97. char curMessage[MESG_SIZE];
  98. char newMessage[MESG_SIZE];
  99. bool newMessageAvailable = false;
  100.  
  101. char WebResponse[] = "HTTP/1.1 200 OKnContent-Type: text/htmlnn";
  102.  
  103. char WebPage[] =
  104. "<!DOCTYPE html>"
  105. "<html>"
  106. "<head>"
  107. "<title>Wifi Display</title>"
  108.  
  109. "<script>"
  110. "strLine = "";"
  111.  
  112. "function SendText()"
  113. "{"
  114. " nocache = "/&nocache=" + Math.random() * 1000000;"
  115. " var request = new XMLHttpRequest();"
  116. " strLine = "&MSG=" + document.getElementById("txt_form").Message.value;"
  117. " request.open("GET", strLine + nocache, false);"
  118. " request.send(null);"
  119. "}"
  120. "</script>"
  121. "</head>"
  122.  
  123. "<body>"
  124. "<Center>"
  125. "<h1>Smart Notice Board </h1>"
  126.  
  127. "<form id="txt_form" name="frmText">"
  128. "<label>Type Your Message:<input type="text" name="Message" size="100" maxlength="255"></label><br><br>"
  129. "</form>"
  130. "<br>"
  131. "<input type="submit" value="Send Message" onclick="SendText()">"
  132. "<Center>"
  133. "</body>"
  134. "</html>";
  135.  
  136. char *err2Str(wl_status_t code)
  137. {
  138. switch (code)
  139. {
  140. case WL_IDLE_STATUS: return("IDLE"); break; // WiFi is in process of changing between statuses
  141. case WL_NO_SSID_AVAIL: return("NO_SSID_AVAIL"); break; // case configured SSID cannot be reached
  142. case WL_CONNECTED: return("CONNECTED"); break; // successful connection is established
  143. case WL_CONNECT_FAILED: return("CONNECT_FAILED"); break; // password is incorrect
  144. case WL_DISCONNECTED: return("CONNECT_FAILED"); break; // module is not configured in station mode
  145. default: return("??");
  146. }
  147. }
  148.  
  149. uint8_t htoi(char c)
  150. {
  151. c = toupper(c);
  152. if ((c >= '0') && (c <= '9')) return(c - '0');
  153. if ((c >= 'A') && (c <= 'F')) return(c - 'A' + 0xa);
  154. return(0);
  155. }
  156.  
  157. boolean getText(char *szMesg, char *psz, uint8_t len)
  158. {
  159. boolean isValid = false; // text received flag
  160. char *pStart, *pEnd; // pointer to start and end of text
  161.  
  162. // get pointer to the beginning of the text
  163. pStart = strstr(szMesg, "/&MSG=");
  164.  
  165. if (pStart != NULL)
  166. {
  167. pStart += 6; // skip to start of data
  168. pEnd = strstr(pStart, "/&");
  169.  
  170. if (pEnd != NULL)
  171. {
  172. while (pStart != pEnd)
  173. {
  174. if ((*pStart == '%') && isdigit(*(pStart+1)))
  175. {
  176. // replace %xx hex code with the ASCII character
  177. char c = 0;
  178. pStart++;
  179. c += (htoi(*pStart++) << 4);
  180. c += htoi(*pStart++);
  181. *psz++ = c;
  182. }
  183. else
  184. *psz++ = *pStart++;
  185. }
  186.  
  187. *psz = ''; // terminate the string
  188. isValid = true;
  189. }
  190. }
  191.  
  192. return(isValid);
  193. }
  194.  
  195. void handleWiFi(void)
  196. {
  197. static enum { S_IDLE, S_WAIT_CONN, S_READ, S_EXTRACT, S_RESPONSE, S_DISCONN } state = S_IDLE;
  198. static char szBuf[1024];
  199. static uint16_t idxBuf = 0;
  200. static WiFiClient client;
  201. static uint32_t timeStart;
  202.  
  203. switch (state)
  204. {
  205. case S_IDLE: // initialize
  206. PRINTS("nS_IDLE");
  207. idxBuf = 0;
  208. state = S_WAIT_CONN;
  209. break;
  210.  
  211. case S_WAIT_CONN: // waiting for connection
  212. {
  213. client = server.available();
  214. if (!client) break;
  215. if (!client.connected()) break;
  216.  
  217. #if DEBUG
  218. char szTxt[20];
  219. sprintf(szTxt, "%03d:%03d:%03d:%03d", client.remoteIP()[0], client.remoteIP()[1], client.remoteIP()[2], client.remoteIP()[3]);
  220. PRINT("nNew client @ ", szTxt);
  221. #endif
  222. //=======================================
  223. hour(), minute(), second(), day(), month(), year(),
  224. timeStart = millis();
  225. state = S_READ;
  226. }
  227. break;
  228.  
  229. case S_READ: // get the first line of data
  230. PRINTS("nS_READ");
  231. while (client.available())
  232. {
  233. char c = client.read();
  234. if ((c == 'r') || (c == 'n'))
  235. {
  236. szBuf[idxBuf] = '';
  237. client.flush();
  238. PRINT("nRecv: ", szBuf);
  239. state = S_EXTRACT;
  240. }
  241. else
  242. szBuf[idxBuf++] = (char)c;
  243. }
  244. if (millis() - timeStart > 1000)
  245. {
  246. PRINTS("nWait timeout");
  247. state = S_DISCONN;
  248. }
  249. break;
  250.  
  251.  
  252. case S_EXTRACT: // extract data
  253. PRINTS("nS_EXTRACT");
  254. // Extract the string from the message if there is one
  255. newMessageAvailable = getText(szBuf, newMessage, MESG_SIZE);
  256. PRINT("nNew Msg: ", newMessage);
  257. state = S_RESPONSE;
  258. break;
  259.  
  260. case S_RESPONSE: // send the response to the client
  261. PRINTS("nS_RESPONSE");
  262. // Return the response to the client (web page)
  263. client.print(WebResponse);
  264. client.print(WebPage);
  265. state = S_DISCONN;
  266. break;
  267.  
  268. case S_DISCONN: // disconnect client
  269. PRINTS("nS_DISCONN");
  270. client.flush();
  271. client.stop();
  272. state = S_IDLE;
  273. break;
  274.  
  275. default: state = S_IDLE;
  276. }
  277. }
  278.  
  279. void scrollDataSink(uint8_t dev, MD_MAX72XX::transformType_t t, uint8_t col)
  280. // Callback function for data that is being scrolled off the display
  281. {
  282. #if PRINT_CALLBACK
  283. Serial.print("n cb ");
  284. Serial.print(dev);
  285. Serial.print(' ');
  286. Serial.print(t);
  287. Serial.print(' ');
  288. Serial.println(col);
  289. #endif
  290. }
  291.  
  292. uint8_t scrollDataSource(uint8_t dev, MD_MAX72XX::transformType_t t)
  293. // Callback function for data that is required for scrolling into the display
  294. {
  295. static enum { S_IDLE, S_NEXT_CHAR, S_SHOW_CHAR, S_SHOW_SPACE } state = S_IDLE;
  296. static char *p;
  297. static uint16_t curLen, showLen;
  298. static uint8_t cBuf[8];
  299. uint8_t colData = 0;
  300.  
  301. // finite state machine to control what we do on the callback
  302. switch (state)
  303. {
  304. case S_IDLE: // reset the message pointer and check for new message to load
  305. PRINTS("nS_IDLE");
  306. p = curMessage; // reset the pointer to start of message
  307. if (newMessageAvailable) // there is a new message waiting
  308. {
  309. strcpy(curMessage, newMessage); // copy it in
  310. newMessageAvailable = false;
  311. }
  312. state = S_NEXT_CHAR;
  313. break;
  314.  
  315. case S_NEXT_CHAR: // Load the next character from the font table
  316. PRINTS("nS_NEXT_CHAR");
  317. if (*p == '')
  318. state = S_IDLE;
  319. else
  320. {
  321. showLen = mx.getChar(*p++, sizeof(cBuf) / sizeof(cBuf[0]), cBuf);
  322. curLen = 0;
  323. state = S_SHOW_CHAR;
  324. }
  325. break;
  326.  
  327. case S_SHOW_CHAR: // display the next part of the character
  328. PRINTS("nS_SHOW_CHAR");
  329. colData = cBuf[curLen++];
  330. if (curLen < showLen)
  331. break;
  332.  
  333. // set up the inter character spacing
  334. showLen = (*p != '' ? CHAR_SPACING : (MAX_DEVICES*COL_SIZE)/2);
  335. curLen = 0;
  336. state = S_SHOW_SPACE;
  337. // fall through
  338.  
  339. case S_SHOW_SPACE: // display inter-character spacing (blank column)
  340. PRINT("nS_ICSPACE: ", curLen);
  341. PRINT("/", showLen);
  342. curLen++;
  343. if (curLen == showLen)
  344. state = S_NEXT_CHAR;
  345. break;
  346.  
  347. default:
  348. state = S_IDLE;
  349. }
  350.  
  351. return(colData);
  352. }
  353.  
  354. void scrollText(void)
  355. {
  356. static uint32_t prevTime = 0;
  357.  
  358. // Is it time to scroll the text?
  359. if (millis() - prevTime >= SCROLL_DELAY)
  360. {
  361. mx.transform(MD_MAX72XX::TSL); // scroll along - the callback will load all the data
  362. prevTime = millis(); // starting point for next time
  363. }
  364. }
  365.  
  366. void setup()
  367. {
  368. #if DEBUG
  369. Serial.begin(115200);
  370. PRINTS("n[MD_MAX72XX WiFi Message Display]nType a message for the scrolling display from your internet browser");
  371. #endif
  372.  
  373. #if LED_HEARTBEAT
  374. pinMode(HB_LED, OUTPUT);
  375. digitalWrite(HB_LED, LOW);
  376. #endif
  377.  
  378. // Display initialization
  379. mx.begin();
  380. mx.setShiftDataInCallback(scrollDataSource);
  381. mx.setShiftDataOutCallback(scrollDataSink);
  382.  
  383. curMessage[0] = newMessage[0] = '';
  384.  
  385. // Connect to and initialize WiFi network
  386. PRINT("nConnecting to ", ssid);
  387.  
  388. WiFi.begin(ssid, password);
  389.  
  390. while (WiFi.status() != WL_CONNECTED)
  391. {
  392. PRINT("n", err2Str(WiFi.status()));
  393. delay(500);
  394. Serial.print(".");
  395. }
  396. PRINTS("nWiFi connected");
  397. Serial.print("IP number assigned by DHCP is ");
  398. Serial.println(WiFi.localIP());
  399. Serial.println("Starting UDP");
  400. Udp.begin(localPort);
  401. Serial.print("Local port: ");
  402. Serial.println(Udp.localPort());
  403. Serial.println("waiting for sync");
  404. setSyncProvider(getNtpTime);
  405. setSyncInterval(300);
  406. // Start the server
  407. server.begin();
  408. PRINTS("nServer started");
  409.  
  410. // Set up first message as the IP address
  411. sprintf(curMessage, "%02d:%02d:%02d, %02d/%02d/%02d, %03d.%03d.%03d.%03d", hour(), minute(), second(), day(), month(), year(), WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3]);
  412. PRINT("nAssigned IP ", curMessage);
  413. }
  414. time_t prevDisplay = 1; // when the digital clock was displayed
  415. void loop()
  416. {
  417. #if LED_HEARTBEAT
  418. static uint32_t timeLast = 0;
  419.  
  420. if (millis() - timeLast >= HB_LED_TIME)
  421. {
  422. digitalWrite(HB_LED, digitalRead(HB_LED) == LOW ? HIGH : LOW);
  423. timeLast = millis();
  424. }
  425. #endif
  426.  
  427. if (timeStatus() != timeNotSet) {
  428. if (now() != prevDisplay) { //update the display only if time has changed
  429. prevDisplay = now();
  430. digitalClockDisplay();
  431. }
  432. }
  433.  
  434. handleWiFi();
  435. scrollText();
  436. }
  437.  
  438.  
  439. void digitalClockDisplay()
  440. {
  441. // digital clock display of the time
  442. Serial.print(hour());
  443. printDigits(minute());
  444. printDigits(second());
  445. Serial.print(" ");
  446. Serial.print(day());
  447. Serial.print(".");
  448. Serial.print(month());
  449. Serial.print(".");
  450. Serial.print(year());
  451. Serial.println();
  452. }
  453.  
  454. void printDigits(int digits)
  455. {
  456. // utility for digital clock display: prints preceding colon and leading 0
  457. Serial.print(":");
  458. if (digits < 10)
  459. Serial.print('0');
  460. Serial.print(digits);
  461. }
  462.  
  463. /*-------- NTP code ----------*/
  464.  
  465. const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
  466. byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets
  467.  
  468. time_t getNtpTime()
  469. {
  470. IPAddress ntpServerIP; // NTP server's ip address
  471.  
  472. while (Udp.parsePacket() > 0) ; // discard any previously received packets
  473. Serial.println("Transmit NTP Request");
  474. // get a random server from the pool
  475. WiFi.hostByName(ntpServerName, ntpServerIP);
  476. Serial.print(ntpServerName);
  477. Serial.print(": ");
  478. Serial.println(ntpServerIP);
  479. sendNTPpacket(ntpServerIP);
  480. uint32_t beginWait = millis();
  481. while (millis() - beginWait < 1500) {
  482. int size = Udp.parsePacket();
  483. if (size >= NTP_PACKET_SIZE) {
  484. Serial.println("Receive NTP Response");
  485. Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer
  486. unsigned long secsSince1900;
  487. // convert four bytes starting at location 40 to a long integer
  488. secsSince1900 = (unsigned long)packetBuffer[40] << 24;
  489. secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
  490. secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
  491. secsSince1900 |= (unsigned long)packetBuffer[43];
  492. return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
  493. }
  494. }
  495. Serial.println("No NTP Response :-(");
  496. return 0; // return 0 if unable to get the time
  497. }
  498.  
  499. // send an NTP request to the time server at the given address
  500. void sendNTPpacket(IPAddress &address)
  501. {
  502. // set all bytes in the buffer to 0
  503. memset(packetBuffer, 0, NTP_PACKET_SIZE);
  504. // Initialize values needed to form NTP request
  505. // (see URL above for details on the packets)
  506. packetBuffer[0] = 0b11100011; // LI, Version, Mode
  507. packetBuffer[1] = 0; // Stratum, or type of clock
  508. packetBuffer[2] = 6; // Polling Interval
  509. packetBuffer[3] = 0xEC; // Peer Clock Precision
  510. // 8 bytes of zero for Root Delay & Root Dispersion
  511. packetBuffer[12] = 49;
  512. packetBuffer[13] = 0x4E;
  513. packetBuffer[14] = 49;
  514. packetBuffer[15] = 52;
  515. // all NTP fields have been given values, now
  516. // you can send a packet requesting a timestamp:
  517. Udp.beginPacket(address, 123); //NTP requests are to port 123
  518. Udp.write(packetBuffer, NTP_PACKET_SIZE);
  519. Udp.endPacket();
  520. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement