Hardware components | ||||||
![]() |
| × | 1 | |||
| × | 2 | ||||
Software apps and online services | ||||||
![]() |
| |||||
| ||||||
Hand tools and fabrication machines | ||||||
![]() |
|
The next NFL season and Super Bowl are near, and so is my new project: The NFL Indicator...
This was the reason I build this lamp. But ESPN and IFTTT are no partners anymore, so the service I used to indicate if a NFL-Team is playing doesn't work anymore. But I left the parts in the code - maybe there will be a similar service sometime, and then ...
The first part was the code for my Particle Photon. This IoT computer has all I need: a simple code and an internet connection.
The helmet is a RGB lamp, where you can choose the color with your smartphone (with Blynk). Or you can choose the rainbow effect with variable speed.
But there is more:
In a model-railway-forum I saw something really cool: CheerLights (thanks to Frank)
I love the idea, that anybody in this world can choose a color, and everywhere the lights are changing. And so I implemented some code, and now I have a CheerLight in my living-room.
/*
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
Arduinohttps://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"
Comments