flyingangel
Published © GPL3+

RGB & CheerLights -Lamp (formerly known as NFL Indicator)

A RGB and CheerLights-lamp in American-Football Design.

BeginnerFull instructions provided2 hours946
RGB & CheerLights -Lamp (formerly known as NFL Indicator)

Things used in this project

Hardware components

Photon
Particle Photon
×1
Adafruit NeoPixel Stick - 8 x 5050 RGB LED with Integrated Drivers
×2

Software apps and online services

Blynk
Blynk
CheerLights

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Code

NFL_Indicator.ino

Arduino
Program for the particle photon
/*

NFL - Indicator

Detects over IFTTT if the Seahawks, Panthers or Vikings are playing
When one or more teams are playing, the LEDs are fading in the corresponding team-colors
When no team is playing you can change the color with BLYNK

*/

/*
        CheerLights
        Reads the latest CheerLights color on ThingSpeak,   Visit http://www.cheerlights.com for more info.
        ThingSpeak ( https://www.thingspeak.com ) is an analytic IoT platform service that allows you to aggregate, visualize and analyze live data streams in the cloud.
        Copyright 2017, The MathWorks, Inc.
        Documentation for the ThingSpeak Communication Library for Particle is in the doc folder where the library was installed.
        See the accompaning licence file for licensing information.
*/


// This #include statement was automatically added by the Particle IDE.
#include "privateStuff.h"   // Place, where private tokens are stored
#include <blynk.h>          // Connection to Blynk
#include <neopixel.h>       // Neopixel
#include <ThingSpeak.h>     // ThingSpeek for CheerLights



// ***************************************
// Definition teams (always 3-letters!!!) and the teamcolor
// all 32 teams
// ***************************************
// Teams (3 letters per team)
String teamName[] =    { "ARI",    "ATL",    "BAL",    "BUF",    "CAR",    "CHI",    "CIN",    "CLE",
                         "DAL",    "DEN",    "DET",    "GB_",    "HOU",    "IND",    "JAX",    "KC_", 
                         "LAR",    "MIA",    "MIN",    "NE_",    "NO_",    "NYG",    "NYJ",    "OAK", 
                         "PHI",    "PIT",    "LAC",    "SF_",    "SEA",    "TB_",    "TEN",    "WSH" };
// Teamcolors
uint32_t teamColor[] = { 0x9B2743, 0xA6192E, 0x241773, 0x00338D, 0x0085CA, 0xDC4405, 0xFC4C02, 0xEB3300,
                         0x003594, 0xFC4C02, 0x0069B1, 0x175E33, 0xA6192E, 0x001489, 0x006073, 0xC8102E, 
                         0x002244, 0x008E97, 0x620160, 0xC8102E, 0xA28D5B, 0x001E62, 0x0C371D, 0xA5ACAF, 
                         0x004851, 0xFFB81C, 0x0072CE, 0x9B2743, 0x4DFF00, 0xC8102E, 0x4B92DB, 0x862633 };


// ***************************************
// Definitions of CheerLights
// ***************************************

TCPClient client;

// List of CheerLights color names
String colorName[] = {"none","red","pink","green","blue","cyan","white","warmwhite","oldlace","purple","magenta","yellow","orange"};

// Map of RGB values for each of the Cheerlight color names
uint32_t cheerLightsColor[] = { 0x000000, 0xFF0000, 0xFF21CB, 0x00FF00, 0x0000FF, 0x00D74B, 0xFFFFFF, 0xFFDFDF,
                                0xFFDFDF, 0x800080, 0xFF00FF, 0xFFFF00, 0xFF3100 };

/* This is the ThingSpeak channel number for CheerLights
  https://thingspeak.com/channels/1417.  Field 1 contains a string with
  the latest CheerLights color. */
unsigned long cheerLightsChannelNumber = 1417;

long interval = 10000;           // interval at which to run CheerLights (milliseconds)

// ***************************************


// def Bit-Operationen
#ifndef bitRead
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
#endif

// configure Neopixel
#define PIXEL_COUNT 16
#define PIXEL_PIN D3
#define PIXEL_TYPE WS2812B
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);


String data1 = "";      // Test from ITTT activated from ESPN
uint32_t activeTeam = 0;            // indicator of playing team (one bit per team)
// activeTeam = 0x10040010;         // Example: CAR, MIN, SEA
int teamsTotal = sizeof(teamName)/sizeof(teamName[0]);  // calc defined teams
boolean showCheerLights = true;     // CheerLights
uint8_t stdColor = 85;              // define standard-color (0-255): red
boolean showRainbow = false;        // Rainbow-Effekt or solid color
int rainbowSpeed = 10;
uint8_t displayBright = 127;


// Send RGB Values from zeRGBa to hardware
// use the same Virtual Pin as your Terminal Widget

BLYNK_WRITE(V1) {  // rainbow on/off

    int i=param.asInt();
    if (i==1) {
        showRainbow = true;
        showCheerLights = false;
    }
    else {
        showRainbow = false;
    }
}

BLYNK_WRITE(V2) {  // speed of rainbow

    int i=param.asInt();
    rainbowSpeed = i;
    
    showRainbow = true;                     // activate rainbow
    showCheerLights = false;
    Blynk.virtualWrite(V1, showRainbow);    // update Blynk-App

}

BLYNK_WRITE(V3) {  // brightness of display

    int i=param.asInt();
    displayBright = i;
}

BLYNK_WRITE(V4) {   // solid color of lamp when no team is playing

    int i=param.asInt();
    stdColor = i;

    showRainbow = false;                    // deactivate rainbow
    Blynk.virtualWrite(V1, showRainbow);    // update Blynk-App
    showCheerLights = false;                     // deactivate white color
    Blynk.virtualWrite(V5, showCheerLights);     // update Blynk-App

}

BLYNK_WRITE(V5) {   // white display?

    int i=param.asInt();
    showCheerLights = i;

    showRainbow = false;        // deactivate rainbow
    Blynk.virtualWrite(V1, showRainbow);
    
}

// The code in setup() runs once when the device is powered on or reset. Used for setting up states, modes, etc
void setup() {

    // activate serial-Interface
    Serial.begin(9600);
    
    // activate Blynk
    Blynk.begin(BLYNK_AUTH_TOKEN);
    Blynk.virtualWrite(V1, showRainbow);
    Blynk.virtualWrite(V2, rainbowSpeed);
    Blynk.virtualWrite(V3, displayBright);
    Blynk.virtualWrite(V5, showCheerLights);

    // aktiviere die Neopixel
    strip.begin();
    strip.show(); // Initialize all pixels to 'off'


    //We "Subscribe" to our IFTTT event called button so that we get events for it 
    Particle.subscribe("touchdown", touchdown);

    // Variable in Console ausgeben
    Particle.variable("text", data1);
    
    // Connect and Subscribe to Thingspeak channel
    ThingSpeak.begin(client);

}


void loop() {
    
    Blynk.run();    //start Blynk

    uint32_t activeTeamColor[teamsTotal];
    
    int playingTeams = 0;   // how many teams are playing?
    for (int i=0; i < teamsTotal; i++) {  // scanning all possible teams
        
        if (bitRead(activeTeam, i)) {               // team playing? 
            activeTeamColor[playingTeams] = teamColor[i]; // active team has teamcolor
            playingTeams ++;
            
        }
    }
    
    if (playingTeams == 0) {        // no team is playing --> constant color from Blynk or rainbow
        if (showRainbow == 1) {
            rainbow();
        } else {
            if (showCheerLights == false) {
                colorLeds(Wheel(stdColor), displayBright);     // solid color
            } else {
 
            cheerlight();

            }
        }
        
    } else {

        // fading LED in colors from playing Teams
        for (int i=0; i<playingTeams; i++) {

            fadeInOut(activeTeamColor[i], displayBright, 12);  // fade in and out with speed 12

        }
    }
}

// ***************************************
// LED-Routines
// ***************************************

// fade in - fade out
void fadeInOut(uint32_t color, uint8_t maxBrightness, int speed) {
    for(int i=0; i<=255; i++) {     // fade in
        colorLeds(color, i * maxBrightness / 255);    // fade 0 to maxBrightness
        delay(speed);
    }
    for(int i=255; i>=0; i--) {     // fade out
        colorLeds(color, i * maxBrightness / 255);    // fade maxBrightness to 0
        delay(speed);
    }
    delay(50);  // short delay when brightness is 0
}

// show color with brightness on neopixels
void colorLeds(uint32_t colorSet, uint8_t brightness) {
    
    //Seplit colorSet to RGB
    uint8_t r = colorSet >> 16;
    uint8_t g = colorSet >> 8;
    uint8_t b = colorSet >> 0;
    
    // calculating color with defined brightness
    uint32_t c = strip.Color(r * brightness/255, g * brightness/255, b * brightness/255);  
    
    // activate all neopixels in stripe
    for(int i=0; i<strip.numPixels(); i++) {
        strip.setPixelColor(i, c);
    }
    strip.show();
  
}

// rainbow-Effekt
void rainbow () {
    uint16_t i, j;

    for(j=0; j<256; j++) {
        for(i=0; i<strip.numPixels(); i++) {
            strip.setPixelColor(i, Wheel(j));
        }
    
        strip.show();

        // check if "Show Rainbow" is "0"
        Blynk.run();    // get latest values
        if (showRainbow == 0) {   // exit loop when "Show Rainbow" is "0"

            break;
        }

        delay(rainbowSpeed);

    }
}


// Slightly different, this makes the rainbow equally distributed throughout, then wait (ms)
void rainbowCycle(uint8_t wait) {
    uint16_t i, j;

    for(j=0; j<256; j++) { // 1 cycle of all colors on wheel
        for(i=0; i< strip.numPixels(); i++) {
            strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
        }
        strip.show();
        delay(wait);
    }
}


// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
// the brightness is calculated color * brightness / 255
uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
   return strip.Color((WheelPos * 3) * displayBright / 255, (255 - WheelPos * 3) * displayBright / 255, 0);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return strip.Color((255 - WheelPos * 3) * displayBright / 255, 0, (WheelPos * 3) * displayBright / 255);
  } else {
   WheelPos -= 170;
   return strip.Color(0, (WheelPos * 3) * displayBright / 255, (255 - WheelPos * 3) * displayBright / 255);
  }
}



// ***************************************
// CheerLights
// ***************************************

void cheerlight()
{
    
    static long LastCheck = 0; 

    // check to see if the time interval has passed
    if (millis() - LastCheck > interval)
    {  
        // save the last time you ran the routine
        LastCheck = millis();
    
        // Read the Thingspeak channel, the latest value from field 1 of channel 1417
        String cheerColor = ThingSpeak.readStringField(cheerLightsChannelNumber, 1);

        for(int i = 0; i <= 12; i++)
        {
            if(cheerColor == colorName[i])
            {
               colorLeds(cheerLightsColor[i], displayBright); 
               // Particle.publish("cheerLights", cheerColor);  // see the actual color in the console
            }
        }
    }
}



// ***************************************
// IFTTT-Messages
// ***************************************

void touchdown(const char *event, const char *data){

    // print text from IFTTT on seriell Interface
    Serial.print(event);
    Serial.print(" - ");
    Serial.println(data);
    
    // converting IFTTT-text to string
    data1 = String(data);

    // ***************************************
    // e-mail?
    // ***************************************

    // is "@gmx" part of string? (-1 if not)
    if (data1.indexOf("@gmx") != -1) {      // if "@gmx" exist
        for(int i=0; i < 5; i++) {          // Rainbow-Effekt 5 times
            rainbowCycle(5);
        }
    }

    // ***************************************
    // process IFTTT-message (zB. "SEA kickoff")
    // ***************************************

    for(int i=0; i < teamsTotal; i++) {                         // scanning all possible teams
 
        if (data1.indexOf(teamName[i] + " kickoff") == 0) {     // Kickoff?
            bitSet(activeTeam, i);                              // set relevant Bit
        }
        
        if (data1.indexOf(teamName[i] + " final") == 0) {       // End of game?
            bitClear(activeTeam, i);                            // clear relevant Bit
        }

        if (data1.indexOf(teamName[i] + " update") == 0) {      // actual Message?
            
            for(int j=0; j < 10; j++) {                         // fade in and out in team-color with speed 1
                fadeInOut(teamColor[i], displayBright, 1);
            }
            
            
        }

    }

}

privateStuff.h

Arduino
In this file all secret numbers are stored. Add this code to the original-code or put it in an additional file.
https://docs.particle.io/guide/getting-started/build/photon/#adding-files-to-your-app
// Private Tokens and PINs

// #define BLYNK_AUTH_TOKEN "store-real-blynk-token-here"
#define BLYNK_AUTH_TOKEN "store-real-blynk-token-here"

Credits

flyingangel

flyingangel

2 projects • 6 followers

Comments