WiFi RGB Lamp Web Server

Dependencies:   mbed ESP8266_WebServer

RGB WiFi Lamp

Firmware

This is the official firmware repository for the BinarySpace RGB WiFi Lamp project. This firmware is still in alpha stage, and subject to change.

Planned changes include:

  • Configure the WiFi Lamp to connect onto your SSID
  • Variety of operating modes like
    • Fixed colour operation
    • Rainbow gradient
    • Time-based colour changing
    • API-based colour changing

Connecting to the WiFi lamp

To connect to the WiFi lamp web server, scan for an open WiFi network using your cellphone, tablet or laptop that begins with the letters ESP_xxxxxx. This is the automatically created SSID of the ESP8266 WiFi module used in the lamp. Your WiFi client needs to be configured to use DHCP.

Once connected, simply point your browser at http://192.168.4.1 and you should see the rudementary web interface allowing you to switch the WiFi lamp on in the red colour or off.

A second option is to enter the following URL
http://192.168.4.1/setcolor?r=x&g=x&b=x
where x is a number between 0 and 255 for the intensity of (r)ed, (g)reen and (b)lue respectively. Any of the r,g,b parts not specified will automatically default to 0

Supported Platforms

  • ST Nucleo F103RB
  • ST Nucleo F302R8
  • ST Nucleo L152RE
  • ST Nucleo F401RE

Unsupported Platforms

  • ST Nucleo F030R8 (unsupported due to insufficient registers for PololuLed library)

How to update your firmware

One of the best things about the ST Nucleo series is that they enumerate as a USB Mass Storage device when plugged in. Updating the firmware is as simple as compiling it using mbed compiler(free registration required to use) for your selected platform, plugging in your Nucleo and copying the .bin file created by the compiler to the USB drive enumerated by the Nucleo. That's it!

Code is fully Open Source

Please feel free to fork this repository and to submit pull requests if you make any cool additions/changes.

If you are developing changes to the firmware and monitoring via serial console for debugging purposes, note than you can simply comment out the #define DEBUG_WIFI line at the top of the main.cpp file to make the output much less verbose. This effectively disables debugging of the WebServer library code and echoing of communications between the Nucleo and the ESP. It also makes the web server noticeably faster, as it doesn't have to output a lot of serial data before handling requests.

LED Strip colour inconsistency

If you are experiencing problems with the LED's not all changing colour, or perhaps flickering or incorrect colour, there could be 2 potential problems we have identified.

  • Power Supply problems - If the power supply is not providing enough power, or not clean enough power, you may experience flickering or random colour changes. Ensure that your power supply can provide enough power (1A @ 5V recommended). If this does not solve your problem, soldering a capacitor over the power supply lines(5V, GND) may help to clean out any noise from the power supply. (100uF minimum)
  • Depending on cable lengths and connectors, noise on the data line may also be a problem. Try soldering a 100Ω - 500Ω resistor in line on the Din pin of the LED strip

Firmware update for the ESP8266 Module

We suggest you upgrade the firmware on the ESP8266 module to the latest official AT firmware from Espressif. Click Here for a detailed upgrade quide.

Committer:
tomvdb
Date:
Mon Dec 01 13:19:53 2014 +0000
Revision:
4:4a502f72cbe3
Parent:
1:f07afcffeb5a
Child:
7:f15c81074400
added setcolor url

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sschocke 0:d21e3e1c0a4b 1 #include "mbed.h"
sschocke 1:f07afcffeb5a 2 #include "PololuLedStrip.h"
sschocke 0:d21e3e1c0a4b 3 #include <string>
sschocke 0:d21e3e1c0a4b 4 #define DEBUG_WIFI
sschocke 0:d21e3e1c0a4b 5
sschocke 1:f07afcffeb5a 6 PololuLedStrip ledStrip(PA_7);
sschocke 1:f07afcffeb5a 7
sschocke 1:f07afcffeb5a 8 #define LED_COUNT 4
sschocke 1:f07afcffeb5a 9 rgb_color colors[LED_COUNT];
sschocke 1:f07afcffeb5a 10
sschocke 0:d21e3e1c0a4b 11 DigitalOut wifiCHPD(D4);
sschocke 0:d21e3e1c0a4b 12 DigitalOut wifiReset(D9);
sschocke 0:d21e3e1c0a4b 13
sschocke 0:d21e3e1c0a4b 14 int wifiOn = 0;
sschocke 0:d21e3e1c0a4b 15
sschocke 0:d21e3e1c0a4b 16 Serial wifiSerial(D8,D2);
sschocke 0:d21e3e1c0a4b 17 Serial pc(USBTX,USBRX);
sschocke 0:d21e3e1c0a4b 18
sschocke 0:d21e3e1c0a4b 19 char buffer[1024];
sschocke 0:d21e3e1c0a4b 20 char reply[1024];
sschocke 0:d21e3e1c0a4b 21 char response[2048];
sschocke 1:f07afcffeb5a 22 char httpMethod[64];
sschocke 1:f07afcffeb5a 23 char httpURI[512];
sschocke 0:d21e3e1c0a4b 24 char* rxptr = buffer;
sschocke 0:d21e3e1c0a4b 25
sschocke 0:d21e3e1c0a4b 26 void rxint() {
sschocke 0:d21e3e1c0a4b 27 char c = wifiSerial.getc();
sschocke 0:d21e3e1c0a4b 28 if( wifiOn == 0 ) return;
sschocke 0:d21e3e1c0a4b 29 #ifdef DEBUG_WIFI
sschocke 0:d21e3e1c0a4b 30 pc.putc(c);
sschocke 0:d21e3e1c0a4b 31 #endif
sschocke 0:d21e3e1c0a4b 32 *rxptr = c;
sschocke 0:d21e3e1c0a4b 33 rxptr++;
sschocke 0:d21e3e1c0a4b 34 *rxptr = 0;
sschocke 0:d21e3e1c0a4b 35 }
sschocke 0:d21e3e1c0a4b 36
sschocke 0:d21e3e1c0a4b 37 void readBuffer() {
sschocke 0:d21e3e1c0a4b 38 strncpy(reply, buffer, 1024);
sschocke 0:d21e3e1c0a4b 39 rxptr = buffer;
sschocke 0:d21e3e1c0a4b 40 *rxptr = 0;
sschocke 0:d21e3e1c0a4b 41 }
sschocke 0:d21e3e1c0a4b 42
sschocke 0:d21e3e1c0a4b 43 short data_waiting(void)
sschocke 0:d21e3e1c0a4b 44 {
sschocke 0:d21e3e1c0a4b 45 char* ok = strstr(buffer, "OK\r\n");
sschocke 0:d21e3e1c0a4b 46 char* error = strstr(buffer, "ERROR\r\n");
sschocke 0:d21e3e1c0a4b 47 char* nochange = strstr(buffer, "no change\r\n");
sschocke 0:d21e3e1c0a4b 48
sschocke 0:d21e3e1c0a4b 49 if( (ok != NULL) || (error != NULL ) || (nochange != NULL ) )
sschocke 0:d21e3e1c0a4b 50 {
sschocke 0:d21e3e1c0a4b 51 return 1;
sschocke 0:d21e3e1c0a4b 52 }
sschocke 0:d21e3e1c0a4b 53
sschocke 0:d21e3e1c0a4b 54 return 0;
sschocke 0:d21e3e1c0a4b 55 }
sschocke 0:d21e3e1c0a4b 56
sschocke 0:d21e3e1c0a4b 57 short string_waiting(const char* str)
sschocke 0:d21e3e1c0a4b 58 {
sschocke 0:d21e3e1c0a4b 59 char* pr = strstr(buffer, str);
sschocke 0:d21e3e1c0a4b 60 char* error = strstr(buffer, "ERROR\r\n");
sschocke 0:d21e3e1c0a4b 61
sschocke 0:d21e3e1c0a4b 62 if( (pr != NULL) || (error != NULL ) )
sschocke 0:d21e3e1c0a4b 63 {
sschocke 0:d21e3e1c0a4b 64 return 1;
sschocke 0:d21e3e1c0a4b 65 }
sschocke 0:d21e3e1c0a4b 66
sschocke 0:d21e3e1c0a4b 67 return 0;
sschocke 0:d21e3e1c0a4b 68 }
sschocke 0:d21e3e1c0a4b 69
tomvdb 4:4a502f72cbe3 70 void setColor( uint8_t r, uint8_t g, uint8_t b )
tomvdb 4:4a502f72cbe3 71 {
tomvdb 4:4a502f72cbe3 72 for ( int c = 0; c < LED_COUNT; c++ )
tomvdb 4:4a502f72cbe3 73 {
tomvdb 4:4a502f72cbe3 74 colors[c].red = r;
tomvdb 4:4a502f72cbe3 75 colors[c].green = g;
tomvdb 4:4a502f72cbe3 76 colors[c].blue = b;
tomvdb 4:4a502f72cbe3 77 }
tomvdb 4:4a502f72cbe3 78
tomvdb 4:4a502f72cbe3 79 ledStrip.write(colors, LED_COUNT);
tomvdb 4:4a502f72cbe3 80 }
tomvdb 4:4a502f72cbe3 81
sschocke 0:d21e3e1c0a4b 82 int main() {
sschocke 0:d21e3e1c0a4b 83 pc.printf("WiFi Lamp Test...\r\n");
tomvdb 4:4a502f72cbe3 84
tomvdb 4:4a502f72cbe3 85 setColor( 250, 0, 0);
tomvdb 4:4a502f72cbe3 86
sschocke 0:d21e3e1c0a4b 87 wifiCHPD = 0;
sschocke 0:d21e3e1c0a4b 88 wifiReset = 0;
sschocke 0:d21e3e1c0a4b 89 wifiSerial.baud(9600);
sschocke 0:d21e3e1c0a4b 90 wifiSerial.attach(&rxint);
sschocke 0:d21e3e1c0a4b 91 wait_ms(1000);
sschocke 0:d21e3e1c0a4b 92
sschocke 0:d21e3e1c0a4b 93 pc.printf("Powering WiFi...\r\n");
sschocke 0:d21e3e1c0a4b 94 wifiCHPD = 1;
sschocke 0:d21e3e1c0a4b 95 wait_ms(250);
sschocke 0:d21e3e1c0a4b 96 pc.printf("Hardware Reset WiFi...\r\n");
sschocke 0:d21e3e1c0a4b 97 wifiReset = 1;
sschocke 0:d21e3e1c0a4b 98 wifiOn = 1;
sschocke 0:d21e3e1c0a4b 99 readBuffer();
sschocke 0:d21e3e1c0a4b 100 while( string_waiting("\r\nready\r\n") == 0 ) {
sschocke 0:d21e3e1c0a4b 101 wait_ms(10);
sschocke 0:d21e3e1c0a4b 102 }
sschocke 0:d21e3e1c0a4b 103 readBuffer();
sschocke 0:d21e3e1c0a4b 104
sschocke 0:d21e3e1c0a4b 105 pc.printf("Starting WiFi...\r\n");
sschocke 0:d21e3e1c0a4b 106 pc.printf("Setting Operating Mode...");
sschocke 0:d21e3e1c0a4b 107 wifiSerial.printf("AT+CWMODE=3\r\n");
sschocke 0:d21e3e1c0a4b 108 while( data_waiting() == 0 ) {
sschocke 0:d21e3e1c0a4b 109 wait_ms(10);
sschocke 0:d21e3e1c0a4b 110 }
sschocke 0:d21e3e1c0a4b 111 readBuffer();
sschocke 0:d21e3e1c0a4b 112
sschocke 0:d21e3e1c0a4b 113 pc.printf("Done\r\nAccept Multiple connections...");
sschocke 0:d21e3e1c0a4b 114 wifiSerial.printf("AT+CIPMUX=1\r\n");
sschocke 0:d21e3e1c0a4b 115 while( data_waiting() == 0 ) {
sschocke 0:d21e3e1c0a4b 116 wait_ms(10);
sschocke 0:d21e3e1c0a4b 117 }
sschocke 0:d21e3e1c0a4b 118 readBuffer();
sschocke 0:d21e3e1c0a4b 119
sschocke 0:d21e3e1c0a4b 120 pc.printf("Done\r\nStarting Web Server...");
sschocke 0:d21e3e1c0a4b 121 wifiSerial.printf("AT+CIPSERVER=1,80\r\n");
sschocke 0:d21e3e1c0a4b 122 while( data_waiting() == 0 ) {
sschocke 0:d21e3e1c0a4b 123 wait_ms(10);
sschocke 0:d21e3e1c0a4b 124 }
sschocke 0:d21e3e1c0a4b 125 readBuffer();
sschocke 0:d21e3e1c0a4b 126
sschocke 0:d21e3e1c0a4b 127 pc.printf("Done\r\n");
sschocke 0:d21e3e1c0a4b 128
tomvdb 4:4a502f72cbe3 129 setColor( 0, 250, 0);
tomvdb 4:4a502f72cbe3 130 wait_ms(500);
tomvdb 4:4a502f72cbe3 131 setColor( 0, 0, 0);
tomvdb 4:4a502f72cbe3 132
sschocke 0:d21e3e1c0a4b 133 while(true) {
sschocke 0:d21e3e1c0a4b 134 if( (string_waiting("+IPD") == 1) && (string_waiting("\r\nOK\r\n") == 1) ) {
sschocke 0:d21e3e1c0a4b 135 pc.printf("\r\nGot Data\r\n");
sschocke 0:d21e3e1c0a4b 136 readBuffer();
sschocke 0:d21e3e1c0a4b 137
sschocke 0:d21e3e1c0a4b 138 char* ipdPacket = strstr(reply, "+IPD");
sschocke 0:d21e3e1c0a4b 139 int linkID, bytesRecv, ipdLen;
sschocke 0:d21e3e1c0a4b 140 int numMatched = sscanf(ipdPacket,"+IPD,%d,%d:%n", &linkID, &bytesRecv, &ipdLen);
sschocke 0:d21e3e1c0a4b 141 if( numMatched != 2 ) {
sschocke 0:d21e3e1c0a4b 142 pc.printf("IPD ERROR : Matched %d, LinkID=%d, BytesRecv=%d, IPD Header Len=%d\r\n", numMatched, linkID, bytesRecv, ipdLen);
sschocke 0:d21e3e1c0a4b 143 continue;
sschocke 0:d21e3e1c0a4b 144 }
sschocke 0:d21e3e1c0a4b 145
sschocke 0:d21e3e1c0a4b 146 pc.printf("IPD Data: LinkID=%d, BytesRecv=%d, IPD Header Len=%d\r\n", linkID, bytesRecv, ipdLen);
sschocke 0:d21e3e1c0a4b 147 if( strstr(ipdPacket, "HTTP") != NULL ) {
sschocke 0:d21e3e1c0a4b 148 pc.printf("Got HTTP Request\r\n");
sschocke 0:d21e3e1c0a4b 149 char* httpPacket = ipdPacket + ipdLen;
sschocke 1:f07afcffeb5a 150 //pc.printf("HTTP Packet: %s\r\n", httpPacket);
sschocke 1:f07afcffeb5a 151
sschocke 1:f07afcffeb5a 152 numMatched = sscanf(httpPacket, "%s %s HTTP/%*c.%*c", httpMethod, httpURI);
sschocke 1:f07afcffeb5a 153 if( numMatched != 2 ) {
sschocke 1:f07afcffeb5a 154 pc.printf("HTTP ERROR : Matched %d, Method=%s, URI=%s\r\n", numMatched, httpMethod, httpURI);
sschocke 1:f07afcffeb5a 155 continue;
sschocke 1:f07afcffeb5a 156 }
sschocke 1:f07afcffeb5a 157 pc.printf("HTTP %s %s\r\n", httpMethod, httpURI);
sschocke 1:f07afcffeb5a 158
sschocke 1:f07afcffeb5a 159 std::string method = httpMethod;
sschocke 1:f07afcffeb5a 160 std::string uri = httpURI;
sschocke 0:d21e3e1c0a4b 161
sschocke 1:f07afcffeb5a 162 std::string httpReply;
sschocke 1:f07afcffeb5a 163 std::string httpReplyPacket;
sschocke 1:f07afcffeb5a 164 if( uri == "/" ) {
sschocke 1:f07afcffeb5a 165 httpReply = "<html><head><title>WiFi Lamp</title></head><body><h1>The WiFi Lamp is alive(<a href='/red'>Red</a>)</h1></body></html>";
sschocke 1:f07afcffeb5a 166 httpReplyPacket = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: %d\r\n\r\n%s";
tomvdb 4:4a502f72cbe3 167 setColor(0,0,0);
tomvdb 4:4a502f72cbe3 168
sschocke 1:f07afcffeb5a 169 } else if( uri == "/red" ) {
sschocke 1:f07afcffeb5a 170 httpReply = "<html><head><title>WiFi Lamp</title></head><body><h1>The WiFi Lamp(Red) is alive(<a href='/'>Off</a>)</h1></body></html>";
sschocke 1:f07afcffeb5a 171 httpReplyPacket = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: %d\r\n\r\n%s";
tomvdb 4:4a502f72cbe3 172 setColor(100, 0, 0);
tomvdb 4:4a502f72cbe3 173
tomvdb 4:4a502f72cbe3 174 } else if ( uri.substr(0, 9) == "/setcolor" ) {
tomvdb 4:4a502f72cbe3 175
tomvdb 4:4a502f72cbe3 176 int r=0, g=0, b=0;
tomvdb 4:4a502f72cbe3 177
tomvdb 4:4a502f72cbe3 178 r = atoi( uri.substr( 12,3 ).c_str() );
tomvdb 4:4a502f72cbe3 179 g = atoi( uri.substr( 18,3 ).c_str() );
tomvdb 4:4a502f72cbe3 180 b = atoi( uri.substr( 24,3 ).c_str() );
tomvdb 4:4a502f72cbe3 181
tomvdb 4:4a502f72cbe3 182 pc.printf( "Set color to (%i, %i, %i)\r\n", r,g,b);
tomvdb 4:4a502f72cbe3 183
tomvdb 4:4a502f72cbe3 184 setColor( r,g,b );
tomvdb 4:4a502f72cbe3 185
tomvdb 4:4a502f72cbe3 186
tomvdb 4:4a502f72cbe3 187 httpReply = "<html><head><title>WiFi Lamp</title></head><body>ok</body></html>";
tomvdb 4:4a502f72cbe3 188 httpReplyPacket = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: %d\r\n\r\n%s";
tomvdb 4:4a502f72cbe3 189
sschocke 1:f07afcffeb5a 190 } else {
sschocke 1:f07afcffeb5a 191 httpReply = "404 Not Found";
sschocke 1:f07afcffeb5a 192 httpReplyPacket = "HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\nContent-Length: %d\r\n\r\n%s";
sschocke 1:f07afcffeb5a 193 }
sschocke 0:d21e3e1c0a4b 194
sschocke 0:d21e3e1c0a4b 195 sprintf(response, httpReplyPacket.c_str(), httpReply.length(), httpReply.c_str());
sschocke 0:d21e3e1c0a4b 196 int bytes = strlen(response);
sschocke 0:d21e3e1c0a4b 197 pc.printf("HTTP Reply Packet(%d bytes): %s\r\n", bytes, response);
sschocke 0:d21e3e1c0a4b 198 wifiSerial.printf("AT+CIPSEND=%d,%d\r\n", linkID, bytes);
sschocke 0:d21e3e1c0a4b 199 wait_ms(500);
sschocke 0:d21e3e1c0a4b 200 if( (string_waiting("\r\n>") == 1) ) {
sschocke 0:d21e3e1c0a4b 201 wifiSerial.printf(response);
sschocke 0:d21e3e1c0a4b 202 }
sschocke 0:d21e3e1c0a4b 203 while( string_waiting("\r\nSEND OK\r\n") == 0 ) {
sschocke 0:d21e3e1c0a4b 204 wait_ms(10);
sschocke 0:d21e3e1c0a4b 205 }
sschocke 0:d21e3e1c0a4b 206 pc.printf("\r\nHTTP Reply Sent\r\n");
sschocke 0:d21e3e1c0a4b 207 }
sschocke 0:d21e3e1c0a4b 208 }
sschocke 1:f07afcffeb5a 209
sschocke 0:d21e3e1c0a4b 210 wait_ms(10);
sschocke 0:d21e3e1c0a4b 211 }
sschocke 0:d21e3e1c0a4b 212 }