Back to Parent

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!

0