48675_LAB04: Controlling Motors
Made by Phoebe
Made by Phoebe
A physical notification flag that waves with respect to important emails
Created: December 3rd, 2022
int motorPin = A3;
int buttonPin = D3;
//https://maker.ifttt.com/trigger/button_pressed/json/with/key/bcFhSXZcj5VFoJT1n0CjFo
int medSpeed = 100;
int lowSpeed = 50;
int hiSpeed = 180;
int motorSpeed = 100;
String statename[4] = {"WORK","QUICK BREAK","LONG BREAK","INACTIVE"};
String currentState = "NOT STARTED";
typedef struct {
uint32_t totalTime = 0;
uint8_t state = 3;
unsigned long timer = 0;
unsigned long totaltimer = 0;
bool active = false;
}Pomodoro;
uint32_t pomTime[3] = {25,5,15};
Pomodoro myPom;
Pomodoro *pPom;
long motorTimer = 0;
int motorDelayMillis = 5000;
int timeLeft = 0;
bool motorOn = false;
bool button_press = false;
long buttonTimer = 0;
long buttonLength;
int buttonState;
void initPom(){
pomTime[0] = min2milli(pomTime[0]);
pomTime[1] = min2milli(pomTime[1]);
pomTime[2] = min2milli(pomTime[2]);
pPom = &myPom;
}
int startPomSession(String command){
int mintime = command.toInt();
myPom.totalTime = min2milli(mintime);
myPom.state = 0;
myPom.active = true;
myPom.timer = millis();
myPom.totaltimer = millis();
motorControl(myPom.state);
return myPom.totalTime;
}
void pomCheck(){
currentState = statename[myPom.state];
timeLeft = milli2min(myPom.totalTime-millis()-myPom.totaltimer);
if (myPom.active == false || myPom.state == 3){
motorOn = false;
analogWrite(motorPin, 0);
return;
}
if (millis()-myPom.totaltimer>=myPom.totalTime){
myPom.active = false;
myPom.state = 3;
motorOn = false;
motorControl(4);
return;
}
else if (millis()-myPom.timer>=pomTime[myPom.state]){
//go to next state and restart timer
myPom.state ++;
if (myPom.state > 3) myPom.state = 0;
myPom.timer = millis();
//trigger appropriate flag wave
motorControl(myPom.state);
}
}
void setup() {
initPom();
pinMode(motorPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
Particle.function("StartPomSession", startPomSession);
Particle.variable("PomodoroState", ¤tState, STRING);
Particle.variable("PomLeft", &timeLeft, INT);
}
void loop() {
pomCheck();
motorTimerCheck();
buttonCheck();
}
void motorControl(int command)
{
// Set Activation Time and Speed
if (command == 0){
TimerAdj(8);
motorSpeed = hiSpeed;
}
else if (command == 1){
TimerAdj(3);
motorSpeed = hiSpeed;
}
else if (command == 2){
TimerAdj(12);
motorSpeed = medSpeed;
}
else if (command == 3){
TimerAdj(2);
motorSpeed = 0;
}
else if (command == 4){
//finish
TimerAdj(2);
motorSpeed = lowSpeed;
analogWrite(motorPin, motorSpeed);
delay(4000);
return;
}
analogWrite(motorPin, motorSpeed);
motorOn = true;
motorTimer = millis();
// done
}
void motorTimerCheck(){
// if timer has elapsed
if (motorOn && millis()-motorTimer>= motorDelayMillis){
motorSpeed = 0;
motorOn = false;
analogWrite(motorPin, motorSpeed);
}
if (motorOn == false) analogWrite(motorPin, 0);
}
void TimerAdj(int seconds){
// convert to seconds
motorDelayMillis = 1000* seconds;
}
int min2milli(int minutes){
return 1000*60*60*minutes;
}
int milli2min(int milli){
return milli/1000/60/60;
}
void buttonCheck(){
if (digitalRead(buttonPin)==LOW){
analogWrite(motorPin,0);
myPom.state = 3;
motorControl(3);
myPom.active = false;
}
}
Click to Expand
For this lab I experimented with controlling a couple different types of motors using the Particle Argon and IFTTT. The setup I eventually landed upon was a sort of eccentric cam/ yoke driven by a DC motor that causes a flag to wave back and forth. Originally my plan was to have the flag wave when I received any emails tagged "important" or "urgent" however IFTTT doesn't support any triggers based on receiving an email, my next thought was to setup a pomodoro timer - I was hoping to link this with one of my existing focus apps or the iOS focus time setting but this was also unavailable. Ultimately I landed on a simple pomodoro timer set in the console which can be shut off by a button. This theoretically could be connected to a webhook app so I can use the button to start a focus time or gcal event to trigger the pomodoro.
The total time for the pomodoro session is entered via the console. The flag waves at different speeds and lengths of time for different pomodoro states - fast for 8 seconds is "time to work", fast for 3 seconds is "short break", med for 10 seconds is "long break". When the total pomodoro duration elapses or the button is pressed the flag waves slowly for 5 seconds and then will go to an inactive state.
Setting up the pomodoro timer function ended up taking me a few hours of extra coding and debugging. I ended up having some contradictions in managing both flag waving and pomodoro states as well as mishaps with using out of range arrays or calling functions with the wrong type of variable. The online Particle IDE doesn't notify you of many of these issues unless you go into the raw error data which makes me want to switch to VS.code. I was also frustrated around the narrow options for IFTTT - many are available only for paid accounts or with paid apps.
int motorPin = A3;
int hiSpeed = 150;
int medSpeed = 100;
int lowSpeed = 50;
int motorSpeed = 100;
long motorTimer = 0;
int motorDelayMillis = 5000;
bool motorOn = false;
void setup() {
pinMode(motorPin, OUTPUT);
Particle.function("motorSpeed", motorControl);
Particle.variable( "motorSpeed" , &motorSpeed , INT );
}
void loop() {
motorTimerCheck();
}
int motorControl(String command)
{
// Set Activation Time and Speed
if (command == "HIGH"){
TimerAdj(10);
motorSpeed = hiSpeed;
}
else if (command == "MED"){
TimerAdj(5);
motorSpeed = medSpeed;
}
else if (command == "LOW"){
TimerAdj(2);
motorSpeed = lowSpeed;
}
analogWrite(motorPin, motorSpeed);
motorOn = true;
motorTimer = millis();
return 1;
// done
}
void TimerAdj(int seconds){
// convert to seconds
motorDelayMillis = 1000* seconds;
}
void motorTimerCheck(){
// if timer has elapsed
if (motorOn && (millis()-motorTimer>= motorDelayMillis)){
motorSpeed = 0;
motorOn = false;
analogWrite(motorPin, motorSpeed);
}
}
Click to Expand