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)
{
}
}