Alright, so I figured it out, and then some. I’m pretty sure there is a simpler way to do this though.
Let me know your thoughts.
Thank you as always!
typedef struct {
int onTime;
int offTime;
float totalDose;
float doseRate; // mL/min
int connectedPin;
} Channel;
void updateChannel(Channel c);
float now;
char getRelay1[75];
char getRelay2[75];
char getRelay3[75];
char getRelay4[75];
Channel channels[4];
void setup() {
channels[0].connectedPin = D0;
channels[1].connectedPin = D1;
channels[2].connectedPin = D2;
channels[3].connectedPin = D3;
pinMode(D0,OUTPUT);
pinMode(D1,OUTPUT);
pinMode(D2,OUTPUT);
pinMode(D3,OUTPUT);
Serial.begin(9600);
Time.zone(-4);
delay(3000);
Particle.function("setupChannel", setupChannel);
Particle.variable("getRelay1", getRelay1);
Particle.variable("getRelay2", getRelay2);
Particle.variable("getRelay3", getRelay3);
Particle.variable("getRelay4", getRelay4);
Particle.function("manual1", manual1);
Particle.function("manual2", manual2);
Particle.function("manual3", manual3);
Particle.function("manual4", manual4);
Particle.function("calibrate1", calibrate1);
Particle.function("calibrate2", calibrate2);
Particle.function("calibrate3", calibrate3);
Particle.function("calibrate4", calibrate4);
}
void loop() {
now = Time.hour() * 3600 + Time.minute() * 60 + Time.second();
Serial.println(now);
for (int i=0;i<4;i++) {
updateChannel(i);
}
delay(5000);
}
void updateChannel(int index) {
Channel *c = &channels[index];
if (c->onTime <= now && c->totalDose > 0) {
digitalWrite(c->connectedPin, HIGH);
Serial.printlnf("Fired Relay %d", index);
c->onTime += 7200;
}
if (c->offTime <= now && c->totalDose > 0) {
digitalWrite(c->connectedPin, LOW);
Serial.printlnf("Turned off Relay %d", index);
c->offTime += 7200;
}
}
int setupChannel(String cmd) { // cmd syntax: "channel#,startTime,doseRate, dose" (startTime is sent as hour*3600 + minute*60 + second)
Serial.println(cmd);
char *rmdr;
char *stringArgs = (char*)cmd.c_str();
int index = atoi(strtok_r(stringArgs, ",", &rmdr));
Channel* c = &channels[index];
c->onTime = atof(strtok_r(NULL, ",", &rmdr));
c->doseRate = atof(strtok_r(NULL, ",", &rmdr));
c->totalDose = atof(rmdr);
float dosePerActuation = c->totalDose/12;
float durationPerActuation = (dosePerActuation/c->doseRate) * 60; // assuming doseRate is in volume/minute
c->offTime = c->onTime + durationPerActuation;
Serial.printlnf("channel#: %d, onTime: %d, doseRate: %f, totalDose: %f", index, c->onTime, c->doseRate, c->totalDose);
char *str;
switch (index) {
case 0:
str = getRelay1;
break;
case 1:
str = getRelay2;
break;
case 2:
str = getRelay3;
break;
case 3:
str = getRelay4;
break;
}
sprintf(str, "channel#: %d, onTime: %d, doseRate: %.1f, totalDose: %.1f", index, c->onTime, c->doseRate, c->totalDose);
return 1;
}
int manual1(String cmd){
if (cmd=="on") {
digitalWrite(D0,HIGH);
return 1;
}
else if (cmd=="off") {
digitalWrite(D0,LOW);
return 0;
}
else {
return -1;
}
}
int manual2(String cmd){
if (cmd=="on") {
digitalWrite(D1,HIGH);
return 1;
}
else if (cmd=="off") {
digitalWrite(D1,LOW);
return 0;
}
else {
return -1;
}
}
int manual3(String cmd){
if (cmd=="on") {
digitalWrite(D2,HIGH);
return 1;
}
else if (cmd=="off") {
digitalWrite(D2,LOW);
return 0;
}
else {
return -1;
}
}
int manual4(String cmd){
if (cmd=="on") {
digitalWrite(D3,HIGH);
return 1;
}
else if (cmd=="off") {
digitalWrite(D3,LOW);
return 0;
}
else {
return -1;
}
}
int calibrate1(String cmd){
if (cmd=="on") {
digitalWrite(D0,HIGH);
delay(60000);
digitalWrite(D0,LOW);
return 1;
}
else if (cmd=="off") {
digitalWrite(D0,LOW);
return 0;
}
else {
return -1;
}
}
int calibrate2(String cmd){
if (cmd=="on") {
digitalWrite(D1,HIGH);
delay(60000);
digitalWrite(D1,LOW);
return 1;
}
else if (cmd=="off") {
digitalWrite(D1,LOW);
return 0;
}
else {
return -1;
}
}
int calibrate3(String cmd){
if (cmd=="on") {
digitalWrite(D2,HIGH);
delay(60000);
digitalWrite(D2,LOW);
return 1;
}
else if (cmd=="off") {
digitalWrite(D2,LOW);
return 0;
}
else {
return -1;
}
}
int calibrate4(String cmd){
if (cmd=="on") {
digitalWrite(D3,HIGH);
delay(60000);
digitalWrite(D3,LOW);
}
else if (cmd=="off") {
digitalWrite(D3,LOW);
return 0;
}
else {
return -1;
}
}