Created
April 20, 2021 08:05
-
-
Save ovidb/37f5836720cc29c2a3d075c2feeceb8f to your computer and use it in GitHub Desktop.
Pomodoro Particle Internet Button
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "InternetButton/InternetButton.h" | |
#include "math.h" | |
/* Here's a nice combination of features that I like to use. | |
Note the use of the allButtons function. */ | |
InternetButton b = InternetButton(); | |
int NO_LEDS = 12; | |
int focusDuration = 60 * 40; | |
int breakDuration = 60 * 5; | |
int maxChecks = 10; | |
float focusIncreaseRatio = 1.5; | |
int focusFitnessIncrease = 1; | |
int focusFitnessDecrease = 2; | |
int focusIncreaseRangeMultiplier = 2; | |
int defaultFocusFitness = 1; | |
int defaultCheckWindow = 20; | |
// mutable variables | |
int checkWindow = defaultCheckWindow; | |
int focusFitness = 1; | |
int checksDone = 0; | |
int startFocusTime = 0; | |
int startBreakTime = 0; | |
int startRedAlertTime = 0; | |
int startCheckingTime = 0; | |
int focusSessions = 0; | |
int breakSessions = 0; | |
bool focusSessionStarted = false; | |
bool breakSessionStarted = false; | |
bool redAlertStarted = false; | |
bool focusCheckingStarted = false; | |
bool allowFocusInput = false; | |
void setup() { | |
// Tell b to get everything ready to go | |
// Use b.begin(1); if you have the original SparkButton, which does not have a buzzer or a plastic enclosure | |
// to use, just add a '1' between the parentheses in the code above. | |
b.begin(); | |
} | |
void loop(){ | |
if (b.buttonOn(1)) { | |
startFocus(); | |
} | |
if (b.buttonOn(2)) { | |
startBreak(); | |
} | |
if (b.buttonOn(3)) { | |
focused(); | |
} | |
if (b.buttonOn(4)) { | |
stop(); | |
} | |
// focus | |
playAnimation(focusSessionStarted, startFocusTime, focusDuration, 0, 100, 0); | |
// break | |
playAnimation(breakSessionStarted, startBreakTime, breakDuration, 0, 0, 100); | |
checkkFocus(); | |
playRedAlert(); | |
} | |
void startFocus() { | |
focusCheckingStarted = true; | |
focusSessionStarted = true; | |
breakSessionStarted = false; | |
redAlertStarted = false; | |
focusSessions++; | |
checkWindow = defaultCheckWindow; | |
checksDone = 0; | |
startFocusTime = Time.now(); | |
startCheckingTime = Time.now(); | |
b.playSong("E5,8,G5,8,E6,8,C6,8,D6,8,G6,8"); | |
blinkAllLeds(1, 300, 0, 100, 0); | |
publish("Start Focus: ", focusSessions); | |
} | |
void startBreak() { | |
focusCheckingStarted = false; | |
focusSessionStarted = false; | |
breakSessionStarted = true; | |
redAlertStarted = false; | |
breakSessions++; | |
startBreakTime = Time.now(); | |
b.playSong("E5,8,G5,8,E6,8,C6,8,D6,8,G6,8,E5,8,G5,8,E6,8,C6,8"); | |
blinkAllLeds(1, 300, 0, 0, 100); | |
publish("Start Break: ", breakSessions); | |
} | |
void stop() { | |
focusCheckingStarted = false; | |
focusSessionStarted = false; | |
breakSessionStarted = false; | |
redAlertStarted = false; | |
checkWindow = defaultCheckWindow; | |
b.playSong("F5,8,E5,8,D4,8,C4,8"); | |
blinkAllLeds(2, 300, 100, 50, 50); | |
focusSessions = 0; | |
breakSessions = 0; | |
focusFitness = defaultFocusFitness; | |
} | |
void startRedAlert() { | |
if (redAlertStarted) { | |
return; | |
} | |
focusSessionStarted = false; | |
breakSessionStarted = false; | |
focusCheckingStarted = false; | |
redAlertStarted = true; | |
} | |
void playRedAlert() { | |
if (!redAlertStarted) { | |
return; | |
} | |
b.playSong("C4,4,D4,4,E4,4"); | |
blinkAllLeds(3, 300, 255, 20, 20); | |
blinkAllLeds(3, 300, 20, 20, 255); | |
focusFitness -= focusFitnessDecrease; | |
publish("focusFitness: ", focusFitness); | |
if (focusFitness <= defaultFocusFitness) { | |
publish("focusFitness <= defaultFocusFitness", focusFitness); | |
focusFitness = defaultFocusFitness; | |
} | |
} | |
void focused() { | |
if (!allowFocusInput) { | |
return; | |
} | |
focusCheckingStarted = true; | |
focusSessionStarted = true; | |
breakSessionStarted = false; | |
redAlertStarted = false; | |
focusFitness += focusFitnessIncrease; | |
int currentCheckWindow = defaultCheckWindow * pow(focusIncreaseRatio, focusFitness); | |
publish("Focused. currentCheckWindow", currentCheckWindow); | |
checkWindow = random(currentCheckWindow, currentCheckWindow * focusIncreaseRangeMultiplier); | |
startCheckingTime = Time.now(); | |
checksDone = 0; | |
allowFocusInput = false; | |
} | |
void checkkFocus() { | |
if (!focusCheckingStarted) { | |
return; | |
} | |
int ellapsed = Time.now() - startCheckingTime; | |
if (ellapsed > checkWindow) { | |
publish("checksDone: ", checksDone); | |
allowFocusInput = true; | |
checksDone++; | |
// b.playSong("C2,2,D2,2"); | |
blinkAllLeds(checksDone, 2000 / checksDone, 100 + (15* checksDone), 100, 100); | |
if (checksDone > maxChecks) { | |
startRedAlert(); | |
} | |
} | |
} | |
/** utility functions */ | |
void playAnimation(bool shouldRun, int sinceStart, int duration, int r, int g, int b) { | |
if (!shouldRun) { | |
return; | |
} | |
int ellapsed = Time.now() - sinceStart; | |
if (ellapsed > duration) { | |
if (focusSessionStarted) { | |
startBreak(); | |
return; | |
} | |
if (breakSessionStarted) { | |
startFocus(); | |
return; | |
} | |
} | |
showDuration(duration, ellapsed, 75, r, g, b); | |
} | |
void publish(char* message, int value) { | |
if (Particle.connected()) { | |
Particle.publish(message, String(value)); | |
} | |
} | |
void blinkAllLeds(int times, int millis, int red, int green, int blue) { | |
for (int i = 0; i < times; i++) { | |
b.allLedsOn(red, green, blue); | |
delay(millis/2); | |
b.allLedsOff(); | |
delay(millis/2); | |
} | |
} | |
void showDuration(int duration, int ellapsed, int delayMs, int red, int green, int blue) { | |
int ratio = duration / NO_LEDS; | |
for(int i = 0; i < NO_LEDS; i++) { | |
if ((ellapsed / ratio) >= i - 1) { | |
b.ledOn(i, red, green, blue); | |
} | |
delay(delayMs); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment