Spidey Wall is the name for a physical wall lit up by multiple addressable LED strips. This program is an LPC1768 web server to control the wall from a browser.

Dependencies:   EthernetInterfacePlusHostname RdWebServer mbed-rtos mbed

This project is part of a Light-Wall using addressable LED strips (WS2801). I have published a few posts on my blog about the construction of the wall and building a game to play on it (PacMan). I have also had a guest post from a friend who has set his children the task of producing some interesting animations. The original post is http://robdobson.com/2015/07/spidey-wall/ /media/uploads/Bobty/20130722_112945_img_9674_62895-1184x1579.jpg

So far, however, I hadn't fully connected the physical (and electronic) wall with the web-browser creations to drive it. This project is hopefully the final link. A fast and reliable web server using REST commands to drive the 1686 LEDs in the Spidey Wall from code running in a browser (say on an iPad while you are playing a game).

The approach taken here results in the ability to control the RGB values of all 1686 LEDs at a rate of 20 frames per second.

A blog post describing the whole thing is here:

http://robdobson.com/2015/08/a-reliable-mbed-webserver/

Committer:
Bobty
Date:
Thu Sep 03 20:17:23 2015 +0000
Revision:
6:8df79fe1afcd
Parent:
5:910909f34907
Fixed an unforeseen problem with messages not aligned on RGB boundaries; Fixed potential hanging pointer problem in colourconverters; Changed Idle screen to a set of colourful snakes

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Bobty 1:362331cec9b7 1 //
Bobty 2:99eb4c6e9ea4 2 // LightWall WebServer
Bobty 1:362331cec9b7 3 //
Bobty 4:b521815f2657 4 // Rob Dobson (C) 2015
Bobty 4:b521815f2657 5 //
Bobty 4:b521815f2657 6 // See http://robdobson.com/2015/07/spidey-wall/ and http://robdobson.com/2015/08/a-reliable-mbed-webserver/
Bobty 4:b521815f2657 7 //
Bobty 0:887096209439 8
Bobty 0:887096209439 9 #include "mbed.h"
Bobty 0:887096209439 10 #include "EthernetInterface.h"
Bobty 1:362331cec9b7 11 #include "RdWebServer.h"
Bobty 1:362331cec9b7 12 #include "DrawingManager.h"
Bobty 5:910909f34907 13 #include "Idler.h"
Bobty 0:887096209439 14 #include <string.h>
Bobty 1:362331cec9b7 15
Bobty 1:362331cec9b7 16 // Web port
Bobty 1:362331cec9b7 17 const int WEBPORT = 80; // Port for web server
Bobty 0:887096209439 18
Bobty 1:362331cec9b7 19 // Debugging and status
Bobty 1:362331cec9b7 20 RawSerial pc(USBTX, USBRX);
Bobty 2:99eb4c6e9ea4 21 DigitalOut led1(LED1); // flashes on command received
Bobty 1:362331cec9b7 22 DigitalOut led2(LED2); //
Bobty 1:362331cec9b7 23 DigitalOut led3(LED3); //
Bobty 1:362331cec9b7 24 DigitalOut led4(LED4); // web server status
Bobty 0:887096209439 25
Bobty 2:99eb4c6e9ea4 26 // System configuration
Bobty 2:99eb4c6e9ea4 27 char systemName[20] = "LightWall";
Bobty 2:99eb4c6e9ea4 28 int systemNumLEDS = 20;
Bobty 2:99eb4c6e9ea4 29 int systemLEDSSplitPoint = systemNumLEDS;
Bobty 2:99eb4c6e9ea4 30
Bobty 1:362331cec9b7 31 // Drawing Manager
Bobty 2:99eb4c6e9ea4 32 DrawingManager drawingManager;
Bobty 0:887096209439 33
Bobty 5:910909f34907 34 // Idler - to display something when not being driven by the web interface
Bobty 5:910909f34907 35 Idler idler(&led2, &drawingManager);
Bobty 5:910909f34907 36
Bobty 4:b521815f2657 37 // General response string for REST requests
Bobty 4:b521815f2657 38 char* generalRespStr = "HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Methods: POST, GET, OPTIONS\r\nAccess-Control-Allow-Headers:accept, content-type\r\nContent-Length: 0\r\nContent-Type: application/octet-stream\r\n\r\n";
Bobty 2:99eb4c6e9ea4 39
Bobty 4:b521815f2657 40 // Get system name - No arguments required
Bobty 4:b521815f2657 41 char* lightwallGetSystemName(int method, char*cmdStr, char* argStr, char* msgBuffer, int msgLen,
Bobty 4:b521815f2657 42 int contentLen, unsigned char* pPayload, int payloadLen, int splitPayloadPos)
Bobty 2:99eb4c6e9ea4 43 {
Bobty 2:99eb4c6e9ea4 44 // Return the system name
Bobty 2:99eb4c6e9ea4 45 return systemName;
Bobty 2:99eb4c6e9ea4 46 }
Bobty 2:99eb4c6e9ea4 47
Bobty 4:b521815f2657 48 // Clear LEDS - No arguments required
Bobty 4:b521815f2657 49 char* lightwallClear(int method, char*cmdStr, char* argStr, char* msgBuffer, int msgLen,
Bobty 4:b521815f2657 50 int contentLen, unsigned char* pPayload, int payloadLen, int splitPayloadPos)
Bobty 4:b521815f2657 51 {
Bobty 5:910909f34907 52 idler.notIdle();
Bobty 4:b521815f2657 53 drawingManager.Clear();
Bobty 4:b521815f2657 54 return generalRespStr;
Bobty 4:b521815f2657 55 }
Bobty 4:b521815f2657 56
Bobty 4:b521815f2657 57 // RawFill - arguments for start LED (e.g. /rawfill?start=0)
Bobty 4:b521815f2657 58 // - payload of message contains binary data for RGB (1 byte for each) for each LED to be set
Bobty 4:b521815f2657 59 char* lightwallRawFill(int method, char*cmdStr, char* argStr, char* msgBuffer, int msgLen,
Bobty 4:b521815f2657 60 int contentLen, unsigned char* pPayload, int payloadLen, int splitPayloadPos)
Bobty 4:b521815f2657 61 {
Bobty 5:910909f34907 62 idler.notIdle();
Bobty 4:b521815f2657 63 drawingManager.RawFill(argStr, pPayload, payloadLen, splitPayloadPos);
Bobty 4:b521815f2657 64 return generalRespStr;
Bobty 4:b521815f2657 65 }
Bobty 4:b521815f2657 66
Bobty 4:b521815f2657 67 // Fill - arguments for start, numLeds, initial-R/G/B and ending-R/G/B (optional)
Bobty 4:b521815f2657 68 // - e.g. /fill?start=0&len=100&r1=20&g1=30&b1=50
Bobty 4:b521815f2657 69 // - e.g. /fill?start=0&len=100&r1=20&g1=30&b1=50&r2=50&g2=100&b2=23
Bobty 4:b521815f2657 70 char* lightwallFill(int method, char*cmdStr, char* argStr, char* msgBuffer, int msgLen,
Bobty 4:b521815f2657 71 int contentLen, unsigned char* pPayload, int payloadLen, int splitPayloadPos)
Bobty 4:b521815f2657 72 {
Bobty 5:910909f34907 73 idler.notIdle();
Bobty 4:b521815f2657 74 drawingManager.Fill(argStr);
Bobty 4:b521815f2657 75 return generalRespStr;
Bobty 4:b521815f2657 76 }
Bobty 4:b521815f2657 77
Bobty 4:b521815f2657 78 // ShowLeds - no arguments
Bobty 4:b521815f2657 79 char* lightwallShowLeds(int method, char*cmdStr, char* argStr, char* msgBuffer, int msgLen,
Bobty 4:b521815f2657 80 int contentLen, unsigned char* pPayload, int payloadLen, int splitPayloadPos)
Bobty 4:b521815f2657 81 {
Bobty 4:b521815f2657 82 // Blink LED
Bobty 4:b521815f2657 83 led1 = !led1;
Bobty 4:b521815f2657 84 // Show LEDS
Bobty 5:910909f34907 85 idler.notIdle();
Bobty 4:b521815f2657 86 drawingManager.ShowLeds();
Bobty 4:b521815f2657 87 return generalRespStr;
Bobty 4:b521815f2657 88 }
Bobty 4:b521815f2657 89
Bobty 1:362331cec9b7 90 // Create, configure and run the web server
Bobty 4:b521815f2657 91 void http_server(void const* arg)
Bobty 0:887096209439 92 {
Bobty 2:99eb4c6e9ea4 93 // Init the web server
Bobty 1:362331cec9b7 94 pc.printf("Starting web server\r\n");
Bobty 1:362331cec9b7 95 char* baseWebFolder = "/sd/"; // should be /sd/ for SDcard files - not used for local file system
Bobty 1:362331cec9b7 96 RdWebServer webServer;
Bobty 2:99eb4c6e9ea4 97
Bobty 2:99eb4c6e9ea4 98 // Add commands to handle the home page and favicon
Bobty 1:362331cec9b7 99 webServer.addCommand("", RdWebServerCmdDef::CMD_LOCALFILE, NULL, "index.htm", true);
Bobty 1:362331cec9b7 100 webServer.addCommand("favicon.ico", RdWebServerCmdDef::CMD_LOCALFILE, NULL, NULL, true);
Bobty 2:99eb4c6e9ea4 101
Bobty 2:99eb4c6e9ea4 102 // Add the lightwall control commands
Bobty 2:99eb4c6e9ea4 103 webServer.addCommand("name", RdWebServerCmdDef::CMD_CALLBACK, &lightwallGetSystemName);
Bobty 4:b521815f2657 104 webServer.addCommand("clear", RdWebServerCmdDef::CMD_CALLBACK, &lightwallClear);
Bobty 4:b521815f2657 105 webServer.addCommand("rawfill", RdWebServerCmdDef::CMD_CALLBACK, &lightwallRawFill);
Bobty 4:b521815f2657 106 webServer.addCommand("fill", RdWebServerCmdDef::CMD_CALLBACK, &lightwallFill);
Bobty 4:b521815f2657 107 webServer.addCommand("showleds", RdWebServerCmdDef::CMD_CALLBACK, &lightwallShowLeds);
Bobty 2:99eb4c6e9ea4 108
Bobty 2:99eb4c6e9ea4 109 // Start the server
Bobty 1:362331cec9b7 110 webServer.init(WEBPORT, &led4, baseWebFolder);
Bobty 1:362331cec9b7 111 webServer.run();
Bobty 0:887096209439 112 }
Bobty 0:887096209439 113
Bobty 2:99eb4c6e9ea4 114 void getSystemConfig()
Bobty 2:99eb4c6e9ea4 115 {
Bobty 2:99eb4c6e9ea4 116 printf("LightWall - Configured for ");
Bobty 2:99eb4c6e9ea4 117 // Check for a config file on the local file system
Bobty 2:99eb4c6e9ea4 118 LocalFileSystem local("local");
Bobty 2:99eb4c6e9ea4 119 FILE* fp = fopen("/local/lights.txt", "r");
Bobty 2:99eb4c6e9ea4 120 if (fp != NULL)
Bobty 2:99eb4c6e9ea4 121 {
Bobty 2:99eb4c6e9ea4 122 char buf[201];
Bobty 2:99eb4c6e9ea4 123 buf[sizeof(buf)-1] = 0;
Bobty 2:99eb4c6e9ea4 124 int nread = fread(buf, 1, sizeof(buf), fp);
Bobty 2:99eb4c6e9ea4 125 if (nread > 0 && nread <= sizeof(buf))
Bobty 2:99eb4c6e9ea4 126 {
Bobty 2:99eb4c6e9ea4 127 buf[nread] = 0;
Bobty 2:99eb4c6e9ea4 128 // Read config details from the file
Bobty 2:99eb4c6e9ea4 129 sscanf(buf, "%s %d %d", systemName, &systemNumLEDS, &systemLEDSSplitPoint);
Bobty 2:99eb4c6e9ea4 130 }
Bobty 2:99eb4c6e9ea4 131 fclose(fp);
Bobty 2:99eb4c6e9ea4 132 printf("%s (%d LEDs, Split at %d)", systemName, systemNumLEDS, systemLEDSSplitPoint);
Bobty 2:99eb4c6e9ea4 133 printf("\r\n");
Bobty 2:99eb4c6e9ea4 134 }
Bobty 2:99eb4c6e9ea4 135 }
Bobty 2:99eb4c6e9ea4 136
Bobty 1:362331cec9b7 137 int main()
Bobty 0:887096209439 138 {
Bobty 1:362331cec9b7 139 // Init
Bobty 1:362331cec9b7 140 pc.baud(115200);
Bobty 1:362331cec9b7 141 pc.printf("Light Wall - Rob Dobson 2015\r\n");
Bobty 6:8df79fe1afcd 142
Bobty 6:8df79fe1afcd 143 // Wait for a moment
Bobty 6:8df79fe1afcd 144 wait(1);
Bobty 5:910909f34907 145
Bobty 2:99eb4c6e9ea4 146 // Get the configuration of the system
Bobty 2:99eb4c6e9ea4 147 getSystemConfig();
Bobty 6:8df79fe1afcd 148
Bobty 2:99eb4c6e9ea4 149 // Drawing manager controls the LEDs
Bobty 4:b521815f2657 150 drawingManager.Init(systemNumLEDS, systemLEDSSplitPoint);
Bobty 1:362331cec9b7 151
Bobty 6:8df79fe1afcd 152 // Start idler
Bobty 6:8df79fe1afcd 153 idler.start();
Bobty 6:8df79fe1afcd 154
Bobty 1:362331cec9b7 155 // Setup ethernet interface
Bobty 1:362331cec9b7 156 char macAddr[6];
Bobty 1:362331cec9b7 157 mbed_mac_address(macAddr);
Bobty 1:362331cec9b7 158 pc.printf("Ethernet MAC address: %02x:%02x:%02x:%02x:%02x:%02x\r\n", macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5]);
Bobty 1:362331cec9b7 159 pc.printf("Connecting to ethernet ...\r\n");
Bobty 5:910909f34907 160
Bobty 3:e5ea80fae61d 161 // Init ethernet
Bobty 1:362331cec9b7 162 EthernetInterface::init();
Bobty 1:362331cec9b7 163
Bobty 3:e5ea80fae61d 164 // Using code described here https://developer.mbed.org/questions/1602/How-to-set-the-TCPIP-stack-s-hostname-pr/
Bobty 3:e5ea80fae61d 165 // to setName on the ethernet interface
Bobty 3:e5ea80fae61d 166 EthernetInterface::setName(systemName);
Bobty 5:910909f34907 167
Bobty 3:e5ea80fae61d 168 // Connect ethernet
Bobty 3:e5ea80fae61d 169 EthernetInterface::connect();
Bobty 3:e5ea80fae61d 170 pc.printf("IP Address: %s HostName %s\r\n", EthernetInterface::getIPAddress(), EthernetInterface::getName());
Bobty 3:e5ea80fae61d 171
Bobty 3:e5ea80fae61d 172 // Web Server used to run in a thread - but I've found this slows performance a lot as described here:
Bobty 3:e5ea80fae61d 173 // http://robdobson.com/2015/08/a-reliable-mbed-webserver/
Bobty 3:e5ea80fae61d 174 // Fortunately it doesn't matter as the LED code is all interrupt driven
Bobty 3:e5ea80fae61d 175 // This is the previous code...
Bobty 4:b521815f2657 176 // Thread httpServer(&http_server, NULL, osPriorityNormal, (DEFAULT_STACK_SIZE * 3));
Bobty 4:b521815f2657 177 http_server("");
Bobty 5:910909f34907 178
Bobty 3:e5ea80fae61d 179 // Forever - actually it won't even get here as the server has a forever loop in it too
Bobty 1:362331cec9b7 180 while(true)
Bobty 1:362331cec9b7 181 {
Bobty 1:362331cec9b7 182 }
Bobty 0:887096209439 183 }