Budget Clock
/*
Budget Clock
There is a webhook configured to grab data from
http://nomu.co/lab/photon-financial-clock/getFinancialData.php
@author Stephen Nomura, Josh Sirchio, Yubing Zhang
@version 0.3
*/
/* CONSTANTS & VARIABLES
------------------------------------------------------*/
int rgbLedPins[] = { TX, D0, D1 };
int dayServoPin = A4;
int budgetServoPin = A5;
Servo dayServo;
Servo budgetServo;
float currentDay;
float daysInMonth;
int monthPercent;
int monthAngle;
int monthAnglePrev = -1;
float currentSpend = 0; // initial values prevent servo glitchout
float budget = 1;
int budgetPercent;
int budgetAngle;
int budgetAnglePrev = -1;
int minimumDeg = 10;
int maximumDeg = 170;
/* SETUP
------------------------------------------------------*/
void setup(){
/* SET PINS */
pinMode(rgbLedPins[0], OUTPUT);
pinMode(rgbLedPins[1], OUTPUT);
pinMode(rgbLedPins[2], OUTPUT);
dayServo.attach(dayServoPin);
budgetServo.attach(budgetServoPin);
Serial.begin(9600);
setRgbLedByHex("#000000", rgbLedPins);
/* CLOUD */
// Listen for hook response
Spark.subscribe("hook-response/getFinancialData", gotFinancialData, MY_DEVICES);
}
/* LOOP
------------------------------------------------------*/
void loop(){
updateFinancialData();
updateDevice();
delay(1000);
}
/* FUNCTIONS
------------------------------------------------------*/
void updateDevice(){
// update month hand
Time.zone(-4); // Eastern Time
currentDay = Time.day();
/*currentDay = 0;*/
daysInMonth = getDaysInMonth( Time.month() );
monthPercent = currentDay / daysInMonth * 100;
monthAngle = monthPercent * maximumDeg / 100;;
if( monthAngle != monthAnglePrev ){
setServoPosition(dayServo, monthAngle, TRUE );
}
monthAnglePrev = monthAngle;
// update budget hand
budgetPercent = currentSpend / budget * 100;
budgetAngle = budgetPercent * maximumDeg / 100;;
if( budgetAngle != budgetAnglePrev ){
setServoPosition(budgetServo, budgetAngle, FALSE );
}
budgetAnglePrev = budgetAngle;
// update LED
if( budgetPercent < monthPercent ){
setRgbLedByHex("#00FF00", rgbLedPins);
}
else {
setRgbLedByHex("FF0000", rgbLedPins);
}
}
void updateFinancialData(){
Particle.publish("getFinancialData"); // trigger webhook
}
void gotFinancialData(const char *name, const char *data){
String dataString = String(data);
// https://stackoverflow.com/questions/11068450/arduino-c-language-parsing-string-with-delimiter-input-through-serial-interfa
int commaIndex = dataString.indexOf(':');
String firstValue = dataString.substring(0, commaIndex);
String secondValue = dataString.substring(commaIndex+1);
currentSpend = firstValue.toInt();
budget = secondValue.toInt();
}
int setServoPosition(Servo &theServo, int angle, bool invert){
// https://daraghbyrne.github.io/diotlabs/6-controlling-outputs/servo/
int position = constrain(angle, minimumDeg , maximumDeg);
if( invert ){
position = position - 180;
position = abs( position );
}
theServo.write( position );
return 1;
}
int setRgbLedByHex(String hex, int pins[]){
if( hex.startsWith("#") ) hex = hex.substring(1);
if( hex.length() != 6 ) return -1;
analogWrite( pins[0], 255 - strtol(hex.substring(0,2),NULL,16) );
analogWrite( pins[1], 255 - strtol(hex.substring(2,4),NULL,16) );
analogWrite( pins[2], 255 - strtol(hex.substring(4,6),NULL,16) );
return 1;
}
int setLED(String hex){
setRgbLedByHex(hex, rgbLedPins);
return 1;
}
int getDaysInMonth(int month){
// http://www.engineersgarage.com/c-language-programs/display-number-days-month-using-switch-statement
switch(month){
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
return 31;
break;
case 2:
return 28; // ignores leap years, whatever
break;
case 4:
case 6:
case 9:
case 11:
return 30;
break;
}
}
author Stephen Nomura, Josh Sirchio, Yubing Zhang
Click to Expand
Content Rating
Is this a good/useful/informative piece of content to include in the project? Have your say!
You must login before you can post a comment. .