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/
Diff: main.cpp
- Revision:
- 1:362331cec9b7
- Parent:
- 0:887096209439
- Child:
- 2:99eb4c6e9ea4
--- a/main.cpp Tue Aug 18 16:03:29 2015 +0000 +++ b/main.cpp Thu Aug 20 07:41:02 2015 +0000 @@ -1,170 +1,230 @@ -/* main.cpp - Rob Dobson 2013 - More details at ??? -*/ +// +// Spidey Wall WebServer +// +// Rob Dobson 2015 #include "mbed.h" #include "EthernetInterface.h" -#include <stdio.h> +#include "RdWebServer.h" +#include "DrawingManager.h" #include <string.h> -#include "RdWebServer.h" -#include "ledstrip.h" -#include "LedCmdHandler.h" + +// Web port +const int WEBPORT = 80; // Port for web server -#define PORT 80 - -Serial pc(USBTX, USBRX); +// Debugging and status +RawSerial pc(USBTX, USBRX); +DigitalOut led1(LED1); // ticking (flashes) +DigitalOut led2(LED2); // +DigitalOut led3(LED3); // +DigitalOut led4(LED4); // web server status -RdWebServer webServer; - -EthernetInterface eth; +// Drawing Manager +DrawingManager drawingManager(1686, 780); -DigitalOut led1(LED1); //server listning status -DigitalOut led2(LED2); //socket connecting status - -Ticker ledTick; +//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(); +//} -char nameOfLights[50]; -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() +// Handle a command +char* lightwallCmd(int method, char* cmdStr, char* argStr, char* msgBuf) { - if(webServer.isListening()) + int cmdLen = RdWebServer::getPayloadLengthFromMsg(msgBuf); + unsigned char* cmdBuf = RdWebServer::getPayloadDataFromMsg(msgBuf); + pc.printf("Command Payload Len %d\r\n", cmdLen); + if (cmdLen == 256) { - blinkCtr++; - if (blinkCtr > 1) - { - led1 = !led1; - blinkCtr = 0; - } - } - else - { - led1 = false; + for (int i = 0; i < cmdLen; i++) + if (cmdBuf[i] != i) + { + printf("Binary content err at %d\r\n", i); + break; + } } - - 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); - } + char* respStr = ""; + respStr = drawingManager.start(cmdBuf, cmdLen); + return respStr; } -void reRunLastCommand() +// Create, configure and run the web server +void http_thread(void const* arg) { - // 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++; - } + pc.printf("Starting web server\r\n"); + char* baseWebFolder = "/sd/"; // should be /sd/ for SDcard files - not used for local file system + RdWebServer webServer; + webServer.addCommand("", RdWebServerCmdDef::CMD_LOCALFILE, NULL, "index.htm", true); + webServer.addCommand("favicon.ico", RdWebServerCmdDef::CMD_LOCALFILE, NULL, NULL, true); + webServer.addCommand("cmd", RdWebServerCmdDef::CMD_CALLBACK, &lightwallCmd); + webServer.init(WEBPORT, &led4, baseWebFolder); + webServer.run(); } -void setLightsConfig() +int main() { - 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"); - } + // Init + pc.baud(115200); + pc.printf("Light Wall - Rob Dobson 2015\r\n"); + + // 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"); + EthernetInterface::init(); + EthernetInterface::connect(); + pc.printf("IP Address: %s\r\n", EthernetInterface::getIPAddress()); + + // Web Server + Thread httpServer(&http_thread, NULL, osPriorityNormal, (DEFAULT_STACK_SIZE * 4)); - // Leds setup - pLedStrip = new ledstrip(ledsCount, ledSplitPoint); - wait_ms(100); - pLedStrip->Clear(); - pLedStrip->ShowLeds(); - - // Cmd handler - pLedCmdHandler = new LedCmdHandler(pLedStrip); -} + // Home + drawingManager.init(); -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(); + while(true) + { +// led1=!led1; + // Service drawing manager + drawingManager.service(); +// Thread::wait(500); + } }