![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
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/
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/
main.cpp
- Committer:
- Bobty
- Date:
- 2015-08-31
- Revision:
- 3:e5ea80fae61d
- Parent:
- 2:99eb4c6e9ea4
- Child:
- 4:b521815f2657
File content as of revision 3:e5ea80fae61d:
// // LightWall WebServer // // Rob Dobson 2015 #include "mbed.h" #include "EthernetInterface.h" #include "RdWebServer.h" #include "DrawingManager.h" #include <string.h> // Web port const int WEBPORT = 80; // Port for web server // Debugging and status RawSerial pc(USBTX, USBRX); DigitalOut led1(LED1); // flashes on command received DigitalOut led2(LED2); // DigitalOut led3(LED3); // DigitalOut led4(LED4); // web server status // System configuration char systemName[20] = "LightWall"; int systemNumLEDS = 20; int systemLEDSSplitPoint = systemNumLEDS; // Drawing Manager DrawingManager drawingManager; //int ledsCount = 904; //int ledSplitPoint = 448; //ledstrip* pLedStrip = NULL; // //char* indexHtmName = "index.htm"; // //const int TICK_MS = 100; //LedCmdHandler* pLedCmdHandler = NULL; //int blinkCtr = 0; // //void ledTickfunc() //{ // if(webServer.isListening()) // { // blinkCtr++; // if (blinkCtr > 1) // { // led1 = !led1; // blinkCtr = 0; // } // } // else // { // led1 = false; // } // // if (pLedCmdHandler != NULL) // pLedCmdHandler->NextGen(); //} // //void handleCmd_ledControl(char* cmdStr, char* argStr) //{ // printf("LEDS COMMAND %s %s\r\n", cmdStr, argStr); // if (argStr == NULL) // return; // pLedCmdHandler->DoCommand(argStr); // // // Store last command // LocalFileSystem local("local"); // FILE* fp = fopen("/local/lastcmd.inf", "w"); // if (fp != NULL) // { // fwrite(argStr, 1, strlen(argStr)+1, fp); // fclose(fp); // } //} // //void reRunLastCommand() //{ // // Store last command // LocalFileSystem local("local"); // FILE* fp = fopen("/local/lastcmd.inf", "r"); // if (fp != NULL) // { // char buf[501]; // buf[sizeof(buf)-1] = 0; // int nread = fread(buf, 1, sizeof(buf), fp); // fclose(fp); // if (nread > 0 && nread <= sizeof(buf)) // { // buf[nread] = 0; // pLedCmdHandler->DoCommand(buf); // } // } //} // //#include "colourconverters.h" // //void BodgeSmooth(ledstrip* pLedStrip) //{ // pLedStrip->Clear(); // pLedStrip->ShowLeds(); // // // RgbColor startRGB(50,0,0); // HsvColor curHsv = RgbToHsv(startRGB); // while(1) // for (int k = 0; k < 1000; k++) // for (int j = 0; j < 255; j++) // { // pLedStrip->Clear(); // RgbColor colrVal = HsvToRgb(curHsv); // pLedStrip->Fill(0,pLedStrip->GetNumLeds(),colrVal.r, colrVal.g, colrVal.b); // pLedStrip->ShowLeds(); // wait_ms(250); // curHsv.h++; // } //} // //void setLightsConfig() //{ // printf("Rob LightWall - Configured for "); // // Check for a config file on the local file system // strcpy(nameOfLights, "Spidey"); // LocalFileSystem local("local"); // FILE* fp = fopen("/local/spidey.cnf", "r"); // if (fp != NULL) // { // char buf[201]; // buf[sizeof(buf)-1] = 0; // int nread = fread(buf, 1, sizeof(buf), fp); // if (nread > 0 && nread <= sizeof(buf)) // { // buf[nread] = 0; // sscanf(buf, "%s %d %d", nameOfLights, &ledsCount, &ledSplitPoint); // } // fclose(fp); // printf("%s (%d LEDs, Split at %d)", nameOfLights, ledsCount, ledSplitPoint); // printf("\n\r"); // } // // // Leds setup // pLedStrip = new ledstrip(ledsCount, ledSplitPoint); // wait_ms(100); // pLedStrip->Clear(); // pLedStrip->ShowLeds(); // // // Cmd handler // pLedCmdHandler = new LedCmdHandler(pLedStrip); //} //int main (void) //{ // pc.baud(115200); // // setLightsConfig(); // // BodgeSmooth(pLedStrip); // // ledTick.attach(&ledTickfunc,TICK_MS / 1000.0); // //// reRunLastCommand(); // // // setup ethernet interface // eth.init(); //Use DHCP // eth.connect(); // printf("IP Address is %s\n\r", eth.getIPAddress()); // // webServer.addCommand("", RdWebServerCmdDef::CMD_LOCALFILE, NULL, indexHtmName, true); // webServer.addCommand("cmd", RdWebServerCmdDef::CMD_CALLBACK, &handleCmd_ledControl); // webServer.init(PORT, &led2); // webServer.run(); //} // Handle a command char* lightwallCmd(int method, char* cmdStr, char* argStr, char* msgBuf) { // Blink LED led1 = !led1; // Get message payload int cmdLen = RdWebServer::getPayloadLengthFromMsg(msgBuf); unsigned char* cmdBuf = RdWebServer::getPayloadDataFromMsg(msgBuf); // Check if the command length is 0 - in this case respond ok as it might be a // pre-flight check on a Cross Domain request - https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS char* respStr = "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"; if (cmdLen != 0) { // Process command drawingManager.start(cmdBuf, cmdLen); } return respStr; } // Get system name char* lightwallGetSystemName(int method, char* cmdStr, char* argStr, char* msgBuf) { // Return the system name return systemName; } // Create, configure and run the web server void http_thread(void const* arg) { // Init the web server pc.printf("Starting web server\r\n"); char* baseWebFolder = "/sd/"; // should be /sd/ for SDcard files - not used for local file system RdWebServer webServer; // Add commands to handle the home page and favicon webServer.addCommand("", RdWebServerCmdDef::CMD_LOCALFILE, NULL, "index.htm", true); webServer.addCommand("favicon.ico", RdWebServerCmdDef::CMD_LOCALFILE, NULL, NULL, true); // Add the lightwall control commands webServer.addCommand("cmd", RdWebServerCmdDef::CMD_CALLBACK, &lightwallCmd); webServer.addCommand("name", RdWebServerCmdDef::CMD_CALLBACK, &lightwallGetSystemName); // Start the server webServer.init(WEBPORT, &led4, baseWebFolder); webServer.run(); } void getSystemConfig() { printf("LightWall - Configured for "); // Check for a config file on the local file system LocalFileSystem local("local"); FILE* fp = fopen("/local/lights.txt", "r"); if (fp != NULL) { char buf[201]; buf[sizeof(buf)-1] = 0; int nread = fread(buf, 1, sizeof(buf), fp); if (nread > 0 && nread <= sizeof(buf)) { buf[nread] = 0; // Read config details from the file sscanf(buf, "%s %d %d", systemName, &systemNumLEDS, &systemLEDSSplitPoint); } fclose(fp); printf("%s (%d LEDs, Split at %d)", systemName, systemNumLEDS, systemLEDSSplitPoint); printf("\r\n"); } } int main() { // Init pc.baud(115200); pc.printf("Light Wall - Rob Dobson 2015\r\n"); // Get the configuration of the system getSystemConfig(); // Drawing manager controls the LEDs drawingManager.init(systemNumLEDS, systemLEDSSplitPoint); // Setup ethernet interface char macAddr[6]; mbed_mac_address(macAddr); 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]); pc.printf("Connecting to ethernet ...\r\n"); // Init ethernet EthernetInterface::init(); // Using code described here https://developer.mbed.org/questions/1602/How-to-set-the-TCPIP-stack-s-hostname-pr/ // to setName on the ethernet interface EthernetInterface::setName(systemName); // Connect ethernet EthernetInterface::connect(); pc.printf("IP Address: %s HostName %s\r\n", EthernetInterface::getIPAddress(), EthernetInterface::getName()); // Web Server used to run in a thread - but I've found this slows performance a lot as described here: // http://robdobson.com/2015/08/a-reliable-mbed-webserver/ // Fortunately it doesn't matter as the LED code is all interrupt driven // This is the previous code... // Thread httpServer(&http_thread, NULL, osPriorityNormal, (DEFAULT_STACK_SIZE * 3)); http_thread(""); // Forever - actually it won't even get here as the server has a forever loop in it too while(true) { } }