// Internet Mood Light as found on projects.xief.net // Code for the ESP8266 that connects to thingspeak talkback and gets the next color to display from there. It also uploads the current color to thingspeak as feedback. #include #include #include #include //for the modolo function fmod // light ring setup #define NUMPIXELS 16 #define PIN 13 #define ROTSPEED 150 //delay in ms for each pixel unsigned long wheelMillis, currMillis = 0; //wheel spin timers Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); #define NUMLAG 7 //has to be the number in lag, changes length of the tail when rotating byte lag[NUMLAG] = {1, 255, 50, 30, 10, 5, 2}; //This devines how much darker the pixels are when rotating #define ROTATIONTIME 20000 // time in ms the wheel is rotating, overall time should be larger than 15s, in order to allow for color update (max 15s update rate) #define FADESTEP 5 //speed of fade in and out. when next led is lit up, increase brightness by this struct color { byte R; byte G; byte B; }; // wifi setup const char* ssid = "SSID"; const char* password = "PASSWORD"; const char* host = "api.thingspeak.com"; String TalkBackID = "TALKBACK ID"; String TalkBackAPIKey = "TALKBACKAPIKEY"; String apiKey = "APIKEY"; //key to write current color into a channel void setup() { Serial.begin(115200); pixels.begin(); // This initializes the NeoPixel library. delay(100); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); int wifi_ctr = 0; while (WiFi.status() != WL_CONNECTED) { delay(100); //Serial.print("."); } Serial.println("WiFi connected"); Serial.println("IP address: " + WiFi.localIP()); } byte colors[NUMPIXELS + 1][3] = {}; //16 pixels, 3 colors red,green,blue, need to be globally defined as they change in functions boolean plotColor = 0; //this color keeps track if in the previous iteration there was a color displayed. That way only set color to -1 once void loop() { WiFiClient client; const int httpPort = 80; if (!client.connect(host, httpPort)) { Serial.println("connection failed"); return; } String url = "/talkbacks/" + TalkBackID + "/commands/execute?api_key=" + TalkBackAPIKey; // This will send the request to the server client.print(String("GET ") + url + "&headers=false" + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); delay(500); // apparently some timeout is needed here String messageLength = ""; String messageBody = ""; while (client.available()) { String line = client.readStringUntil('\n'); if (line.length() == 1) { //actual content starts after empty line (that has length 1) messageLength = client.readStringUntil('\n'); messageBody = client.readStringUntil('\n'); break; } } byte msgLength = messageLength.toInt(); // that is totally buggy - basically the length is returned a hex, however from 0-9 this works as this is identical Serial.print("Found a message, the message is:"); Serial.println(messageBody); Serial.print("Message Length: "); Serial.print(messageLength); Serial.print(", length as integer = "); Serial.println(msgLength); client.stop(); if (msgLength == 9) { // new command present String red = (String)messageBody[0] + (String)messageBody[1] + (String)messageBody[2]; byte r = red.toInt(); String green = (String)messageBody[3] + (String)messageBody[4] + (String)messageBody[5]; byte g = green.toInt(); String blue = (String)messageBody[6] + (String)messageBody[7] + (String)messageBody[8]; byte b = blue.toInt(); plotColor = true; //plotted the color updateColor(messageBody,client); upload current color to Thingspeak Serial.println("Fading in..."); int lastPixel = fadeIn(r, g, b); Serial.println("Rotating..."); lastPixel = rotate(r, g, b, lastPixel); Serial.println("Fade out..."); fadeOut(r, g, b, lastPixel); } else { if (plotColor) { updateColor("-1",client); } plotColor = false; delay(5000); //in case there is no message, not to poll like crazy } } int fadeIn(byte r, byte g, byte b) { byte i = 0; int pix = 0; for (byte i = 0; i < 255; i = i + FADESTEP) { colors[pix][1] = r / 255.0 * i; colors[pix][2] = g / 255.0 * i; colors[pix][3] = b / 255.0 * i; for (byte i = 0; i < NUMLAG; i++) { //now also adjust some more pixels to have a couple of pixels fade out according to the scheme defined in lag byte pixLag = ((pix + i) % NUMPIXELS); pixels.setPixelColor(pixLag, pixels.Color(colors[pixLag][1] / lag[i], colors[pixLag][2] / lag[i], colors[pixLag][3] / lag[i])); // Moderately bright green color. } pixels.show(); // This sends the updated pixel color to the hardware. pix++; if (pix >= NUMPIXELS) pix = 0; //iterate over pixels delay(ROTSPEED); } return pix; //return current pixel value in order to continue correctly } int rotate(byte r, byte g, byte b, int pix) { byte i = 0; unsigned long goalTime = millis() + ROTATIONTIME; while (millis() < goalTime) { colors[pix][1] = r; colors[pix][2] = g; colors[pix][3] = b; for (byte i = 0; i < NUMLAG; i++) { //now also adjust some more pixels to have a couple of pixels fade out according to the scheme defined in lag byte pixLag = ((pix + i) % NUMPIXELS); pixels.setPixelColor(pixLag, pixels.Color(colors[pixLag][1] / lag[i], colors[pixLag][2] / lag[i], colors[pixLag][3] / lag[i])); // Moderately bright green color. } pixels.show(); // This sends the updated pixel color to the hardware. pix++; if (pix >= NUMPIXELS) pix = 0; //iterate over pixels delay(ROTSPEED); } return pix; //return current pixel value in order to continue correctly } void fadeOut(byte r, byte g, byte b, int pix) { byte i = 0; for (int i = 255; i > -NUMPIXELS * FADESTEP; i = i - FADESTEP) { if (i > 0) { colors[pix][1] = r / 255.0 * i; colors[pix][2] = g / 255.0 * i; colors[pix][3] = b / 255.0 * i; } else { colors[pix][1] = 0; colors[pix][2] = 0; colors[pix][3] = 0; } for (byte i = 0; i < NUMLAG; i++) { //now also adjust some more pixels to have a couple of pixels fade out according to the scheme defined in lag byte pixLag = ((pix + i) % NUMPIXELS); pixels.setPixelColor(pixLag, pixels.Color(colors[pixLag][1] / lag[i], colors[pixLag][2] / lag[i], colors[pixLag][3] / lag[i])); // Moderately bright green color. } pixels.show(); // This sends the updated pixel color to the hardware. pix++; if (pix >= NUMPIXELS) pix = 0; //iterate over pixels delay(ROTSPEED); } } void updateColor(String colorMessage, WiFiClient client) { if (client.connect(host,80)) { String postStr = apiKey; postStr +="&field1="; postStr += colorMessage; postStr += "\r\n\r\n"; client.print("POST /update HTTP/1.1\n"); client.print("Host: api.thingspeak.com\n"); client.print("Connection: close\n"); client.print("X-THINGSPEAKAPIKEY: "+apiKey+"\n"); client.print("Content-Type: application/x-www-form-urlencoded\n"); client.print("Content-Length: "); client.print(postStr.length()); client.print("\n\n"); client.print(postStr); Serial.print("Set color to: "); Serial.println(colorMessage); } else { Serial.println("Error with color update in Thingspeak"); } }