"Stevie is a fish.
Stevie has no motors.
Stevie prefers that you don’t tap on the tank.
Stevie doesn’t know what Wi-Fi is.
This is a picture of a computer. It’s not a fish. Stevie is a fish!
I bet Stevie wishes he had hands so he could play with tablets."
This description is printed on a sign that sits next to Stevie’s tank.
Who is Stevie, you might ask? Stevie is DMC Boston’s office fish, and he is a valued member of the team. Like us, he needs to eat. Unlike us, he can’t feed himself from within the confines of his 10-gallon tank. Even with eleven employees in the office, it can be tough remembering when Stevie was fed last.
DMC used IoT to solve this problem. Next to Stevie’s tank is his button – more specifically, a Particle Internet Button. Whereas Stevie’s job is to swim around and entertain us Bostonians, the button’s job is to help us remember when Stevie was last fed, and, more importantly, remind us to actually feed him.
The way Stevie’s Button works is simple. Whenever someone feeds Stevie, they simply press the button and everyone in the office receives a message on Slack that Stevie was just fed. The button’s built-in LEDs are programmed to function as a 10-bit 24-hour binary clock. After 24 hours, the LEDs turn red, indicating that it’s time to feed Stevie again. After 26 hours of not feeding Stevie, Slack will notify everyone that he is hungry and is kindly requesting sustenance.
To further personalize this button and make use of its integrated piezo speaker, the button plays a short 8-bit rendition of Timmy Trumpet's Freaks, while simultaneously displaying a random and vibrant assortment of colors from the LEDs.
This idea was largely inspired by Andrew’s work on the Coffee Button in our Chicago Office. If you thought this project was cool and are interested in integrating the Internet Button into Slack, I recommend reading Andrew’s blog post. He goes into greater technical detail about creating the web hooks and code. It’s also another great example of how easy it is to get involved with IoT technology.
Stay tuned. Next time, I’ll talk about how I gave Stevie a witty personality using C# and more Slack integration.
I've added my Internet Button code here:
// This #include statement was automatically added by the Particle IDE.
#include "InternetButton/InternetButton.h"
#include
InternetButton internetButton = InternetButton();
unsigned long lastPublish;
int hoursPassed;
unsigned long tPassed;
int state;
#define DEBOUNCE_DELAY 20
void setup() {
internetButton.begin();
lastPublish = millis();
state = 0;
// Turn all LEDs white, but only about 10% brightness
internetButton.allLedsOn(25,25,25);
//Turn the last LED green. This indicates where the binary clock starts (the clock reads counterclockwise, because that's intuitive, right?)
internetButton.ledOn(11,0,255,0);
}
void loop() {
if (buttonPressed())
restart();
tPassed = millis() - lastPublish; //number of ms since last feeding
// 84375 ms is the duration of a state
if (tPassed >= 84375){
state++;
lastPublish = millis();
binaryLedHandler(state);
}
//93600000 is the number of ms in 26 hours
if (tPassed >= 93600000){
// Publish an event named "stevie" for Slack to receive as an incoming webhook.
Particle.publish("stevie", "I am hungry. Please feed me. :white_frowning_face:", 60, PRIVATE);
// Wait until the button has been pressed and Stevie has been fed
while (!buttonPressed()){}
restart();
}
}
bool buttonPressed(){
//Register a button press if any of the buttons were pressed for longer than the debounce delay of 20 ms
if (internetButton.buttonOn(1) || internetButton.buttonOn(2) || internetButton.buttonOn(3) || internetButton.buttonOn(4)){
delay(DEBOUNCE_DELAY);
if (internetButton.buttonOn(1) || internetButton.buttonOn(2) || internetButton.buttonOn(3) || internetButton.buttonOn(4)){
return true;
}
}
return false;
}
void binaryLedHandler(int state){
/*
* The Internet Button has 11 LEDs. Because the first LED is always set to green to indicate the start of the clock,
* there are only 10 LEDs that can be used for the clock. If there are 10 LEDs, and each LED can either be on or off, then
* the total number of possible states is 10^2, or 1024 states. If this 10-bit binary clock is to represent 24 hours, then
* each state must represent ~84 seconds.
*/
// If we've reached all 1024 states, then it has been 24 hours, so turn all LEDs red. Stevie is hungry!!
if (state >= 1024)
internetButton.allLedsOn(255,0,0);
//Logic for binary clock
else{
double rem = state;
for (int i = 9 ; i >= 0 ; i--){
if (rem >= pow(2,i)){
internetButton.ledOn(10-i,0,0,255);
rem = rem - pow(2,i);
}
else
internetButton.ledOn(10-i,25,25,25);
}
}
}
void restart(){
//Start with playing Freaks, by Timmy Trumpet
timmyTrumpet();
//Make all LEDs white, except the first light, which is green, visually identifying the starting state of the clock
internetButton.allLedsOn(25,25,25);
internetButton.ledOn(11,0,255,0);
// Publish a webhook that stevie has just been fed
Particle.publish("stevie", "I have just been fed.", 60, PRIVATE);
//reset times and states
lastPublish = millis();
tPassed = 0;
state = 0;
}
void timmyTrumpet(){
internetButton.setBPM(120);
switchLed();
internetButton.playSong("E4,8\n");
switchLed();
internetButton.playSong("E4,16\n");
switchLed();
internetButton.playSong("B4,16\n");
switchLed();
internetButton.playSong("E5,16,REST,16\n");
switchLed();
internetButton.playSong("E5,16,REST,16\n");
switchLed();
internetButton.playSong("E5,16,REST,16\n");
switchLed();
internetButton.playSong("E5,16,REST,16\n");
switchLed();
internetButton.playSong("E5,16,REST,16\n");
switchLed();
internetButton.playSong("B4,16,REST,16\n");
switchLed();
internetButton.playSong("C5,16,REST,16\n");
switchLed();
internetButton.playSong("E5,16,REST,16\n");
switchLed();
internetButton.playSong("E5,16,REST,16\n");
switchLed();
internetButton.playSong("C5,16,REST,16\n");
switchLed();
internetButton.playSong("B4,2\n");
switchLed();
internetButton.playSong("E4,8\n");
switchLed();
internetButton.playSong("E4,16\n");
switchLed();
internetButton.playSong("B4,16\n");
switchLed();
internetButton.playSong("E5,16,REST,16\n");
switchLed();
internetButton.playSong("E5,16,REST,16\n");
switchLed();
internetButton.playSong("E5,16,REST,16\n");
switchLed();
internetButton.playSong("E5,16,REST,16\n");
switchLed();
internetButton.playSong("E5,16,REST,16\n");
switchLed();
internetButton.playSong("B4,16,REST,16\n");
switchLed();
internetButton.playSong("C5,16,REST,16\n");
switchLed();
internetButton.playSong("B4,16,REST,16\n");
switchLed();
internetButton.playSong("G4,16,REST,16\n");
switchLed();
internetButton.playSong("F#4,16,REST,16\n");
switchLed();
internetButton.playSong("E4,2\n");
}
void switchLed(){
//randomize lights for playing timmy trumpet
internetButton.allLedsOff();
int ledN;
int r;
int g;
int bl;
for (int i = 1 ; i < (rand() % 9) + 2 ; i++){
ledN = rand() % (12);
r = rand() % (256);
g = rand() % (256);
bl = rand() % (256);
internetButton.ledOn(ledN,r,g,bl);
}
}