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/

main.cpp

Committer:
Bobty
Date:
2015-08-29
Revision:
2:99eb4c6e9ea4
Parent:
1:362331cec9b7
Child:
3:e5ea80fae61d

File content as of revision 2:99eb4c6e9ea4:

// 
// 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);
    pc.printf("Command Payload Len %d\r\n", cmdLen);

    // Process command
    char* respStr = "";
    respStr = 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
    strcpy(systemName, "Spidey");
    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");
    EthernetInterface::init();
    EthernetInterface::connect();
    pc.printf("IP Address: %s\r\n", EthernetInterface::getIPAddress());

    // Web Server
    Thread httpServer(&http_thread, NULL, osPriorityNormal, (DEFAULT_STACK_SIZE * 3));
    
    // Forever
    while(true)
    {
        // Service drawing manager
        drawingManager.service();
    }
}