I have created a simple Relay Switch that turns my milliwatt propane fireplace ON/OFF using Argon, a remote control or Apple’s Homekit or by a button on a Xenon. It works great, It’s pretty cool, but I also got a big propane bill this month. To reduce that I’d like to make the cost more visible to the family and hopefully change behaviors (ahem) of leaving the fireplace on for long periods of time. Pardon my nasty code - I’m new to coding in general.
I would like to create a small LCD display that:
- counts how many minutes the fireplace has been on
- after being turned on - auto turns off after 60mins
- Can display the dollar amount of propane used this ‘session’
- Display the total dollar amount spent since I reset it
The propane ‘measurement’ will simply be me calibrating the propane usage of the fireplace by watching the gas meter for an hour - then using that approximate value to count how many gallons is used per hour. Don’t worry, there will be no direct monitoring of propane gas.
I’d like the LCD to update every minute or so and Display something like:
Run time: 23min Cost: $1.23
Total Spent (since reset): $27.49
I’ve tried to read up on millis(), timer(), and other related approaches - and I think I’ll need to do something like the following:
- Have a simple server that can capture how many minutes/gallons are used in one session so that value can persist across particle reboots, etc. I probably need to update that every minute it runs?
Likely using webhooks to pass a variable via GET
** Persist the current market price of Propane (which i will manually update)
** Allow me to reset the total usage counter by blanking out the stored value - Modify my current code to have a timer for 60 minutes that turns off after it has been first started (call a function which acts as a toggle for the fire)
- Retrieve the values from my server (Total_Minutes, Propane_price) every minute and then update the LCD
** Session Cost will be calculated on the device using the Propane_Cost value from my server
I realize:
- If i change the price at some point - ALL the previous recorded hours will be priced according to the new price. That’s OK, I’ll probably reset it when I change the price.
- Session is not persistent on reset, but every minute the particle will update total time on my server, so I’m not worried about “losing” much time.
Questions:
- How should I setup the timer in my code. I’m confused. I’m pretty sure Delay() is useless here
- Do I use webhooks to get the data back from the server?
int fire_switch = D0;
int remote_sensor = D2;
int homekit_state;
int MAIN_STATUS;
// Variables will change:
int buttonPushCounter = 0; // counter for the number of button presses
int remote_state = 0; // current state of the button
int lastRemote_state = 0; // previous state of the button
void setup() {
pinMode(fire_switch, OUTPUT);
digitalWrite(fire_switch,HIGH);
pinMode(remote_sensor, INPUT_PULLDOWN);
Particle.function("fireplace",fireToggle);
Particle.function("hktogg",hktoggle);
Particle.variable("MAIN_STATUS", MAIN_STATUS);
Particle.subscribe("Button_change", xenon_handler);
Particle.subscribe("hook-response/minute_used", myHandler, MY_DEVICES);
}
void loop() {
remote_state = digitalRead(remote_sensor);
Particle.variable("remote_state", remote_state);
// compare the buttonState to its previous state
if (remote_state != lastRemote_state) {
// if the state has changed, increment the counter
if (remote_state == HIGH) {
// if the current state is HIGH then the button went from off to on:
buttonPushCounter++;
Particle.publish("button Change","on");
Particle.publish("number of button pushes:", String(buttonPushCounter));
Particle.variable("PushCounter",String(buttonPushCounter));
fireToggle("1");
} else {
// if the current state is LOW then the button went from on to off:
Particle.publish("button Change","off");
fireToggle("0");
}
// Delay a little bit to avoid bouncing
delay(50);
}
// save the current state as the last state, for next time through the loop
lastRemote_state = remote_state;
/*
if (remote_state == 1)
{
// Fire should be ON
fireToggle("1");
// Particle.publish("Loop 1", "Toggle ON");
delay(100);
}
else if (remote_state == 0)
{
fireToggle("0");
// Particle.publish("Loop 2", "Toggle OFF");
delay(100);
}
// Particle.publish("LOOP", String(remote_state));
*/
delay(200);
}
int hktoggle(String command) {
if (command=="1") { // Turn ON
delay(100);
fireToggle("1");
Particle.publish("Homekit:", "ON");
return 1;
}
else if (command=="0") { // turn off
fireToggle("0");
Particle.publish("Homekit:", "OFF");
return 0;
}
else if (command=="?"){ // check state
if (MAIN_STATUS==1) { // Currently On
Particle.publish("Homekit Status:", "ON");
return 1;
}
else if (MAIN_STATUS==0) { // Currently off
Particle.publish("Homekit Status:", "OFF");
return 0;
}
}
else {
return -1;
}
}
void xenon_handler(const char *event, const char *data)
{
fireToggle(data);
}
int fireToggle(String command) {
/* Spark.functions always take a string as an argument and return an integer.
Since we can pass a string, it means that we can give the program commands on how the function should be used.
In this case, telling the function "on" will turn the LED on and telling it "off" will turn the LED off.
Then, the function returns a value to us to let us know what happened.
In this case, it will return 1 for the LEDs turning on, 0 for the LEDs turning off,
and -1 if we received a totally bogus command that didn't do anything to the LEDs.
*/
if (command=="1") { // Turn ON
digitalWrite(fire_switch,LOW);
delay(100);
MAIN_STATUS=1;
Particle.publish("Firetoggle:", String("Turned On"));
Particle.publish("minute_used", "1", PRIVATE);
return 1;
}
else if (command=="0") { // turn off
digitalWrite(fire_switch,HIGH);
Particle.publish("Firetoggle:", String("Turned Off"));
MAIN_STATUS=0;
return 0;
}
else {
return -1;
}
}
Any help or constructive suggestions are appreciated!