Giant LED - Tracking Adam Savage
by Ajaxjones in Circuits > LEDs
4788 Views, 24 Favorites, 0 Comments
Giant LED - Tracking Adam Savage
Here you will find a rendition of a Giant LED ,re-purposed to act as a Twitter, YouTube and Twitch alert lamp. It's main purpose for me is to provide an alert when there are tweets, videos or twitch streams by Adam Savage and the tested team, and to be fair, a couple of other people I follow like Robert Cowan, Marty the Mechanic and more.
Obviously I could use twitter, twitch etc, on my phone or laptop, but there are so many alerts from so many services and notifications that I basically turn them all off, plus the phone goes into silent mode after 10pm As it will also work with Webhooks I have one also configured to recieve updates from some Biq Query tables that are work related so as to let me know if they have been updated OK with a sufficient number of records each day.
Adafruit have a service called Adafruit IO that I wanted to try and I have been meaning all year to try and re-tackle the ESP8266 after hearing some good words on the Wemos D1 Mini release 3. It all started to come together when I found a design for a LED on thingiverse by Astro73. I started with that and reworked it a bit for scale and also to add a push button into the base and some other cosmetic changes. You can find the remix here https://www.thingiverse.com/thing:3290837
Plus it can be voice controlled through Alexa now as well with the advent of IFTTT alexa trigger word.
Ingredients
If you want to make one of these the list of parts is quite small and also releatively inexpensive. If you dont mind the wait you can source the main parts from overseas as well reducing the cost even more. The main ingredient however is the Giant LED case and base. If you have a 3D printer then you are all set , if not there are a few online printer companies that will print the parts. There are only 3 so that should also be fairly cheap.
1. Wemos D1 Mini R3
2. Neopixel 8 LED
3. Printed base and legs in black PETG
4. Printed lens and light holder in transparent PLA
5. Push Button Switch 12mm square x1
6. Round Push Button Cap x1
7. USB lead and adapter for power
8. M3x20 button head
9. M3 Nut
10. M2x8mm bolt x2
11.M2 Nut x2
12. Some Black, Red and Yellow wire
13. 300-500 Ohm Resistor
14. Small piece of heatshrink
You can use other ESP devices, or even a Huzzah, but case was designed for the mini which has mounting holes and avoids having to glue it in.
Tools
To create and build this you'll need the following
1. 3D printer
2. 1.5mm and 2mm Allen key
3. Soldering Iron and solder
4.Wirecutters
5.Pliers
6. Sense of humour
7. Scalpel for trimming
Code Requirements
So before we dive into the build I am going to outline some of the requirements that I wanted to include into this. Most of these I had in mind before starting and I'd sketched out a few flows to work out what I was going try. As it went on though I discovered some issues with services that I wanted to address.
Requirements.
I wanted the LED to show me when a new tweet or video was posted and also it turns out when a specfic Twitch channel starts up. I also wanted the alert to keep going until I cancelled it so that if I was away for a while I would know what had happened whilst I had been away. I also wanted it to be configurable for Wi-Fi access without having to reflash the software as well. One last thing that cropped up as well was in addition to responding to events live, I needed it to check every 15 minutes the status of the data fed to it
So with the basics in place, the next thing was to work out how each part was going to be executed. You can see my ideas below on which part would be handled by which type of software or platform.
1. Adafruit IO, this is used to set up the feeds for the alerts, you can get an account here http://io.adafruit.com
I am going to be using this as a message queuing service where I will be sending it messages from IFTTT and then the Giant LED receives those messages so that it can act on them.
2. IFTTT , https://ifttt.com/ and this is used to scan the chosen Twitter, YouTube and Twitch channels and then sends the event to the Adafruit IO
3. ESP8266 code to read these feeds and this is burnt into the ESP8266 by using the standard Arduino IDE (v1.8.8)
4. Arduino code, loaded onto the ESP8266 to read the Adafruit IO feeds and light up the Neopixel
5. Arduino code to read a push button to clear the alert
6. Be able to configure the WiFi adapter without having to reburn the ESP, and for this I used the WiFi Manager library by Tzapu , https://github.com/tzapu/WiFiManager although the setup options needed a little change to accomodate the Adafruit IO libraries.
Setting Up Adafruit IO
This is the first step as you will need the access keys you create here and also need to create the feeds that the IFTTT will send events to. You can set up both this and the IFTTT account and pretty much get everything set up and working before you move onto the Arduino part of this project.
Rather than copying the adafruit examples you can find the basics here https://learn.adafruit.com/gmailbox/adafruit-io-se... which will get you setup.
Then for the GIANT LED you will also need to add to the default channels the following feeds
1. color - this lets us change color remotely with something like Alexa
2. twitch
3. twitterfan
4. youtubefan
Then you also need to create a new group if you havent already called input, then into this group also create a feed called digital. This will let us also see the effect of pressing the button if we wanted to expand the use of this device for other purposes.
If you also want to at this point is to play with the dashboard so that you can add these feeds to it for information and fault finding purposes.
Setting Up IFTTT
You can also follow the Adafruit guide here, https://learn.adafruit.com/gmailbox/ifttt-setup. You then can select the Twitter, youtube and twitch actions to setup your watch lists and then send these through to the relevant feeds. I've attached a simple video so that you can see how quick it can be.
In addition if you want to voice control the color of your LED by Alexa there is now an Amazon Alexa applet. To set one of these select the app and choose the word blue, then connect it to the Adafruit feed you have set up called color and enter 0000ff as the data to send to that channel. You could also pass extra commands this way to the GIANT LED such as reset or reboot if you wanted to.
When you are setting up the IFTTT trigger you need to choose the data that is sent and this is called "Ingredients" in IFTTT. The first piece we need is the "UserName" then a space and then the "CreatedAt"
We pick both items so that when the data arrives in the ESP8266 we can then detect if it is a new tweet and that it is different from previous tweets by the same users. You can see what this should like from the attached image.
Installing ESP8266 Boards Into the Arduino IDE
This is where things are a little trickier and might take a bit more time to get sorted out. In addition to the ESP8266 you also need the Adafruit IO libraries and you can follow this guide for those.
https://learn.adafruit.com/gmailbox/arduino-setup
There is a simple explanation of how to add the ESP8266 boards here as well
http://esp8266.github.io/Arduino/versions/2.0.0/do...
Don't forget to make sure your Arduino IDE is up to the latest version as well and I was using 1.8.8 at the time of writing this.
One other library we use is the SimpleTimer as this will allow us to set up a background timer so we can periodically check the feeds , instructions for this can be found at
uses simpletimer https://playground.arduino.cc/Code/SimpleTimer#Download
Installing the WiFi Manager Library
To enable us to get remote configuration of the WiFi setup we are going to use the Tzapu Wifi Manger, details on this and how to install the libraries can be found here,
https://github.com/tzapu/WiFiManager
This is a pretty simple install of external libraries and the option is already in the Manage library section of your Arduino IDE tools section.
The ESP8266 Code - With Debug Printing
// This code contains print statements so you can monitor its operation via the Serial monitor // Based on the Adafruit IO RGB LED Output Example // Adafruit invests time and resources providing this open source code. // Please support Adafruit and open source hardware by purchasing // products from Adafruit! // // Written by Todd Treece for Adafruit Industries // Copyright (c) 2016-2017 Adafruit Industries // Licensed under the MIT license. // // All text above must be included in any redistribution. // uses simpletimer https://playground.arduino.cc/Code/SimpleTimer#Do... // https://playground.arduino.cc/Code/SimpleTimer#Do... // rest of code by Ajax Jones https://playground.arduino.cc/Code/SimpleTimer#Do // https://playground.arduino.cc/Code/SimpleTimer#Do... // ************************** Configuration ***********************************/ #define IO_USERNAME "your IO Username" #define IO_KEY "your IO Key" // leave blank as we will get them through the Wifi Manager, seems to be working fine this way #define WIFI_SSID "" #define WIFI_PASS "" // we dont include this as AdafruitIO will include its version //#include //https://github.com/esp8266/Arduino //needed for library #include #include #include "WiFiManager.h" //https://github.com/tzapu/WiFiManager #include SimpleTimer timer; #include "AdafruitIO_WiFi.h" AdafruitIO_WiFi io(IO_USERNAME, IO_KEY, WIFI_SSID, WIFI_PASS); //************************ NeoPixel configs *******************************// #include "Adafruit_NeoPixel.h" #define PIXEL_PIN 5 #define PIXEL_COUNT 8 int NUM_LEDS = PIXEL_COUNT; #define PIXEL_TYPE NEO_GRB + NEO_KHZ800 Adafruit_NeoPixel pixels = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE); // Main colors and the default color long default_color = 865554; long RED_color = 2689027; // red #290803 long GREEN_color = 865554; // green #0d3512 long BLUE_color = 856117; // blue #0d1035 long PURPLE_color = 2364968; // purple #241628 long BRIGHTRED_color = 15990784; // bright red #f40000 // ----------------------------------------------------------------------------------------- //time idea taken from https://www.safaribooksonline.com/library/view/arduino-cookbook-2nd/9781449321185/ch12.html https://playground.arduino.cc/Code/SimpleTimer#Do... https://playground.arduino.cc/Code/SimpleTimer#Do... const long oneSecond = 1000; // a second is a thousand milliseconds const long oneMinute = oneSecond * 60; const long fiveMinutes = oneMinute * 5; const long fifteenMinutes = fiveMinutes * 3; const long oneHour = fifteenMinutes * 4; // Twitter Users we like the most and these will flash and all other tweets we have chosen will just change the color String SuperTweet[] = { "ajaxjones", "donttrythis", "prodnose", "testedcom"}; String SuperTuber[] = {"tested", "cowan", "marty"}; // sets the alert status so we can keep flashing the LEDS in the main loop bool WHIZZY_TWEET = false; bool WHIZZY_TUBER = false; bool WHIZZY_TWITCH = false; // Saves the last tweet and youtube so we can poke the service to double check every now and then String lasttweet =""; String lasttube =""; String lasttwitch =""; // digital pin 5, this is the button we use to reset the alert colors #define BUTTON_PIN 4 // button state, not really that used as we are looking for the button on interupt bool current = false; bool last = false; // set up the 'color' feed, just so we can test and send colors on demand or use Alexa trigger AdafruitIO_Feed *color = io.feed("color"); // set up the 'twitterfan' feed - Blue AdafruitIO_Feed *twitter = io.feed("twitterfan"); // set up the 'youtubefan' feed - Red AdafruitIO_Feed *youtube = io.feed("youtubefan"); // set up the 'twitch' feed - Purple AdafruitIO_Feed *twitch = io.feed("twitch"); // set up the 'digital' feed AdafruitIO_Feed *digital = io.feed("input.digital"); // ----------------------------------------------------------------------------------------- void setup() { // set the button pin as an input, we use INPUT_PULLUP as we dont have to use external resistors pinMode(BUTTON_PIN, INPUT_PULLUP); // Attach an interrupt to the ISR vector for the button attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), handleInterrupt, FALLING); // Start serial and wait for serial monitor to open then connect to io.adafruit.com Serial.begin(115200); while (! Serial); // neopixel begin pixels.begin(); // Set the intial state to a red so we know we are offline and working setAll(0xf4, 0x00, 0x00); // red // for testing, this will show the status of the WiFi WiFi.printDiag(Serial); WiFiManager wifiManager; //set callback that gets called when connecting to a previous WiFi fails, and enters Access Point mode wifiManager.setAPCallback(configModeCallback); //reset saved settings , un comment this next line to force the testing of the WiFi Manager so you can connect //use your phone or tablet to look for the Giant LED network that will appear //wifiManager.resetSettings(); //sets timeout until configuration portal gets turned off //useful to make it all retry or go to sleep //in seconds wifiManager.setTimeout(240);<br>if (!wifiManager.autoConnect("GIANT LED")) { Serial.println(F("failed to connect and hit timeout")); //reset and try again delay(3000); ESP.reset(); delay(1000); } // for testing we can see if we have the right credentials to connect //Serial.println(WiFi.SSID()); //Serial.println(WiFi.psk());<br>//WiFi.begin(WIFI_SSID, WIFI_PASS); //while (WiFi.status() != WL_CONNECTED) { //delay(500); //Serial.print("."); //} Serial.println(); Serial.println(F("WiFi connected")); Serial.println(F("IP address: ")); Serial.println(WiFi.localIP()); // now we connect to the IO service Serial.print(F("Connecting to Adafruit IO")); io.connect(); // set up a message handler for the 'color' feed. color->onMessage(handleMessage); // set up a message handler for the 'twitterfan' feed. twitter->onMessage(twitterMessage); // set up a message handler for the 'youtubefan' feed. youtube->onMessage(youtubeMessage); // set up a message handler for the 'twitch' feed. twitch->onMessage(twitchMessage); // wait for a connection while (io.status() < AIO_CONNECTED) { Serial.print(F(".")); delay(500); } // we are connected Serial.println(); Serial.println(io.statusText()); //Serial.println(sizeof(SuperTweet)); //Serial.println(sizeof(SuperTweet[0])); // Print out a list of the Twitter accounts we are waiting for for (byte idx = 0; idx < sizeof(SuperTweet) / sizeof(SuperTweet[0]); idx++) { Serial.print(F("SuperTweet[")); Serial.print(idx); Serial.print("] = '"); Serial.print(SuperTweet[idx]); Serial.println("'"); } // Print out a list of the YouTube accounts we are waiting for for (byte idx = 0; idx < sizeof(SuperTuber) / sizeof(SuperTuber[0]); idx++) { Serial.print(F("SuperTuber[")); Serial.print(idx); Serial.print("] = '"); Serial.print(SuperTuber[idx]); Serial.println("'"); } // You can use this to get sent the last color , it will cause IO to resend the last color value //color->get(); // request the existing states of the feeds, so you will need to press the reset as it starts up youtube->get(); twitter->get(); twitch->get(); for (int i = 0; i < PIXEL_COUNT; ++i) { pixels.setPixelColor(i, default_color); } showStrip(); timer.setInterval(fifteenMinutes, gettweets); } void gettweets(){ // We make some calls to IO to get the twitter and youtube feeds resent in case we missed them // As they will have both the author and created date,we can check later to use them youtube->get(); twitter->get(); twitch->get(); Serial.print("getting some tweets"); Serial.print(" uptime (s): "); Serial.println(millis() / 1000); } // ----------------------------------------------------------------------------------------- void loop() { // io.run(); is required for all sketches. io.run(); timer.run(); if (WHIZZY_TWEET == true) { RunningLights(0x0d, 0x10, 0x35, 250); } if (WHIZZY_TUBER == true) { RunningLights(0x29, 0x08, 0x03, 250); } if (WHIZZY_TWITCH == true) { RunningLights(0x24, 0x16, 0x28, 250); } } // ----------------------------------------------------------------------------------------- // set the interupt to clear the alert when the button is pressed and check the internet void handleInterrupt() { WHIZZY_TWEET = false; WHIZZY_TUBER = false; WHIZZY_TWITCH = false; current = true; // send the current state to the 'input.digital' feed on adafruit io so we can see it digital->save(current); for (int i = 0; i < 16; ++i) { setAll(0xeb, 0xfb, 0x03); // Yellow ebfb03 } setAll(0x0d, 0x35, 0x12); // Green Serial.print(F("sending button -> ")); Serial.print(current); Serial.print(F(" and default color ")); Serial.println(default_color); current = false; digital->save(current); while (WiFi.status() != WL_CONNECTED) { delay(500); setAll(0xeb, 0xfb, 0x03); // Yellow ebfb03 } } // ----------------------------------------------------------------------------------------- // this is called whenever a 'twitter' message arrives - set the LED to Blue void twitterMessage(AdafruitIO_Data *data) { String tweeter = (data->toString()); tweeter.toLowerCase(); if ((lasttweet != tweeter) && (tweeter != "")) { lasttweet = tweeter; setAll(0x0d, 0x10, 0x35); // Set tweet blue color Serial.print(F("Tweet: ")); Serial.print(tweeter); // check for a favourtite tweeter for (byte idx = 0; idx < sizeof(SuperTweet) / sizeof(SuperTweet[0]); idx++) { if (tweeter.indexOf(SuperTweet[idx]) >= 0) { // Lets make their tweets whizzy #0d1035 WHIZZY_TWEET = true; Serial.print(" by "); Serial.print(SuperTweet[idx]); } } Serial.println(""); } } // ----------------------------------------------------------------------------------------- // this is called whenever a 'youtube' message arrives - set the LED to RED void youtubeMessage(AdafruitIO_Data *data) { String tuber = (data->toString()); tuber.toLowerCase(); if ((lasttube != tuber) && (tuber !="")) { lasttube = tuber; setAll(0x29, 0x08, 0x03); // Set youtube red color 290803 Serial.print(F("Youtube: ")); Serial.println(tuber); // check for a favourtite Youtuber for (byte idx = 0; idx < sizeof(SuperTuber) / sizeof(SuperTuber[0]); idx++) { if (tuber.indexOf(SuperTuber[idx]) >= 0) { // Lets make their videos whizzy #0d1035 WHIZZY_TUBER = true; Serial.print (" by "); Serial.print(SuperTuber[idx]); } } Serial.println(""); } } // ----------------------------------------------------------------------------------------- // this is called whenever a 'twitch' message arrives - set the LED to PURPLE void twitchMessage(AdafruitIO_Data *data) { String twitch = (data->toString()); twitch.toLowerCase(); if ((lasttwitch != twitch) && (twitch !="")) { lasttwitch = twitch; setAll(0x24, 0x16, 0x28); // Set twitch purple color #241628 Serial.print(F("Twitch: ")); Serial.println(twitch); // No check for a favourtite Twitcher we only follow one WHIZZY_TUBER = true; Serial.println(""); } } // ----------------------------------------------------------------------------------------- // this function is called whenever a 'color' message is received // which will set the default color on startup based on the last color feed value void handleMessage(AdafruitIO_Data *data) { // print RGB values and hex value Serial.print(F("Received HEX value: ")); Serial.println(data->value()); long color = data->toNeoPixel(); //default_color = color; Serial.print(F("Received HEX long: ")); Serial.println(color); for (int i = 0; i < PIXEL_COUNT; ++i) { pixels.setPixelColor(i, color); } showStrip(); } // ----------------------------------------------------------------------------------------- void RunningLights(byte red, byte green, byte blue, int WaveDelay) { int Position = 0; for (int j = 0; j < NUM_LEDS; j++) { Position++; // = 0; //Position + Rate; for (int i = 0; i < NUM_LEDS; i++) { setPixel(i, ((sin(i + Position) * 127 + 128) / 255)*red, ((sin(i + Position) * 127 + 128) / 255)*green, ((sin(i + Position) * 127 + 128) / 255)*blue); } showStrip(); delay(WaveDelay); } } // ----------------------------------------------------------------------------------------- // Neopixel routines void setAll(byte red, byte green, byte blue) { for (int i = 0; i < PIXEL_COUNT; i++ ) { setPixel(i, red, green, blue); } showStrip(); } // ----------------------------------------------------------------------------------------- void showStrip() { #ifdef ADAFRUIT_NEOPIXEL_H // NeoPixel pixels.show(); #endif #ifndef ADAFRUIT_NEOPIXEL_H // FastLED FastLED.show(); #endif } // ----------------------------------------------------------------------------------------- void setPixel(int Pixel, byte red, byte green, byte blue) { #ifdef ADAFRUIT_NEOPIXEL_H // NeoPixel pixels.setPixelColor(Pixel, pixels.Color(red, green, blue)); #endif #ifndef ADAFRUIT_NEOPIXEL_H // FastLED leds[Pixel].r = red; leds[Pixel].g = green; leds[Pixel].b = blue; #endif } // ----------------------------------------------------------------------------------------- // this is called when WiFiManager enters configuration mode, void configModeCallback (WiFiManager *myWiFiManager) { Serial.println(F("Entered config mode")); Serial.println(WiFi.softAPIP()); //if you used auto generated SSID, print it Serial.println(myWiFiManager->getConfigPortalSSID()); //entered config mode, set Neo Pixel to purple #241628 = 2364968 // setAll(0x24, 0x16, 0x28); setAll(0xeb, 0xfb, 0x03); // Yellow ebfb03 }
Soldering It All Together
Everything in this design is soldered together and should be quite easy to manage. I've used 3 different coloured wires to make things easy and the first thing is to measure wire for the neopixel to the WEMOS. I plaited them and put a small piece of heat-shrink on and then soldered them as shown so that it will lay flat in the lens.
The button was next and will fit snug into the base. One side of the button goes to Gnd and this is twisted together with the Ground wire of the neopixel. I then tinned them and soldered them as one into the ground pin of the WEMOS.
The power lead for the Neopixel goes to the 5v PIn. The signal wire , or Di (data in) of the neopixel is soldered to Wemos pin as D1. There are some sites that suggest inserting a 300-500 Ohm resistor in series with this, but as of yet I have had no problems so for now its just a direct connection.
To ensure good practice, and on the advice of sites like Adafruit I've put a 330R resistor in series with the Di line to the neopixel. It is to prevent the first LED in the ring from letting out the magic pixies and simply done by cutting the wire and putting a resistor in. A small piece of heatshrink will stop any wayward shorts. You can cut the resistor pretty short and just put a hoop in each end and do the same with the wire.
The other wire for the button goes direct to pin D2. There is no need for a pullup resistor as this is handled within the software by putting a PULLUP command against that pin.
That's basically all there is to it.
3D the Print
Attached here are the STL files we are using for the Giant LED. The files are a remix/rework of astro73 and you can grab all the files from https://www.thingiverse.com/thing:3290837 as well.
For the legs and base I used a Sunlu PETG+ filament which works really well on the Prusa i3 and I used either 10 or 20% gyroid infill.
For the LED itself I have been using Sunlu transparent PLA and using around 10% infill with concentric top and bottom layers.
With each I only use the stock Prusa PET and Prusa PLA settings in Slic3r and they've all worked out fine. I do get a bit of stringing on the legs, but I just waft a blowtorch over them and the stringing vanishes :)
Giant LED Assembly
All the pieces go together really easily, you have to press a M3 nut into the base to allow the screw to hold the thing together. You also need to wire the NeoPixel to the WEMOS through the legs first as well. I was considering how to put some connectors in, but decided that it wasnt going to come apart in the future.
The lens is just a push fit onto the legs and they in turn are bolted to the base with a single M3x20mm bolt. You might need to run a knife around the inside of the button hole so that it moves nice and freely. The Wemos is held in place with 2 M2x8 socket bolts screwed in from below.
To finish off, you can glue a piece of felt onto the base to stop any slippage if required.
Setup and Operating Instructions
With everything ready and the software uploaded apply some power to the usb and the GIANT LED should come up and the LED will go RED and then change to a yellow colour. This shows it is off line and waiting for wifi config. Using a phone or similar look for the GIANT LED wifi network and connect and you will get the WiFi Manager screen. It will have scanned your local area and you just enter your wifi details, the ESP will reboot and you will be now online with a green light. It will also connect at this point to IO and the alert lights will come up as it hasnt yet seen any previous messages. Press the button a couple of time and the GIANT LED is now ready for updates to arrive.
You can go onto the Adafruit IO dashboard at this point and add some data to each feed and see the lights go into alert mode.
Have fun !
What Else Can Giant LED Do
Once you have the basics of a design like this and with the IFTTT you can use it for many things. Gmail inbox alert is one easy one, and as Adafruit also works with Webhooks other programs can send data to it as well. I have one being set up at the moment to keep track on some Big Query data uploads as part of a work project.
Also with the button you can use it to signal other GIANT LED's as well, you could have one in different houses and use it as a remote indicator to get the other party to press the button to cancel the light.
Here is a useful link on the webhook method of sending data to the feed. In this case it is using an IFTTT applet but you can just as easily use a CURL method with python.
https://io.adafruit.com/blog/notebook/2018/11/26/f...
In fact it's even possible to fit an OLED 128x32 into the base to supplement the LED with some textual content and I'm currently working on that and will update the STL's and supply the code to utilise the IO with this as well.