Help Calculating A Running Total

Hi -

Relatively new to particle and C++… I’m having trouble calculating a running total for a simple project that measures the current coming from a solar panel and keeps track of the cumulative watt hours generated through out the day. I believe my basic use of the += operator is correct, but every time I run the code below and the variable wh_cum is published, it does not keep a running total. I suspect the structure of my main loop must not be correct. A thousand thanks for any help…

//Name pins, name functions, create variables////////////////////////////////////////////

int i_in = A0;
int load = A1;
int i = 1;
int state = 0;
double solar_sum = 0;
double solar_avg = 0;
double solar_i = 0;
double offset = 0;
double rawdata = 0;
double adc_res = 4096; // bits of resolution on ADC
double v_max = 3.283; // max voltage range on ADC (i.e. voltage on 3.3V pin)
double v_to_a = 185; // number of millivolts per AMP on current sensor model ACS712
double v_off = 2.436; // voltage output on ADV pin with no current flowing through ACS712
double v_man = 14.3; //maunal offset necessary for voltage to equal 0 when open circuit
double sol_area = 0.0723; //solar panel area in square Meters
double sol_v = 12.6; // close circuit voltage of panel
double w_inst = 0; // current power, in W per m^2
double wh_cum = 0; // cumulative energy collected today, in Wh / m^2
double sample_f = 5000; //amount of time to average current samples over
char publishData[] = ""; //empty variable which will hold data being set to cloud



void setup() {
    // Configure Pin types
    // Analog Pins do not require pinMode()
     // variable name max length is 12 characters long
     
     pinMode(load, OUTPUT);               // sets pin as output
     digitalWrite(load,LOW);

  Particle.variable("Current_Avg",solar_avg);
  Particle.variable("Current_Inst",solar_i);
  Particle.variable("Power",w_inst);
  Particle.variable("Energy",wh_cum);
 
  setADCSampleTime(480); // sets the ADC sampple time to the longest possible value equal to 480 cycles
  
    offset = (v_off / v_max) * adc_res;

}

void loop() {

// average reading over length of the delay
  while (i < 61)
  {
 delay(sample_f);
 rawdata = analogRead(i_in); // read the current comming from solar panel, bits of ADC
 solar_i = ((rawdata - offset) / v_to_a *1000) + v_man ;  // converting reading to milliamps
 solar_sum += solar_i; // x += y is the same as saying x = x + y 
 i++;
}
   
 // perform calculations on data
  solar_avg = solar_sum / i;
  w_inst = ((solar_avg / 1000) * sol_v ) / sol_area;
  wh_cum += (w_inst * (sample_f / 60000)); 
  
  // Publish Data
  sprintf(publishData,"%.2f ||| %.2f ||| %.3f",solar_avg,w_inst,wh_cum); //URL Example https://community.particle.io/t/example-using-ifttt-google-drive/8908
  Particle.publish("avg mA | W/m^2 | Wh/m^2",publishData,30); //ttl number must be less than writeinterval
  
   //toggle light every time the code goes through this point
  // digitalWrite(load, (state) ? HIGH : LOW);
    //state = !state;
  
  solar_sum = 0;
  i = 1;


}
1 Like

On first glance I wouldn’t see too much wrong with the math for wh_cum but could you elaborate which figures you get and what you expect.

Some general notes tho’
I’d not use a while() that keeps the flow trapped in loop() for five minutes but would rather do the measuring and cumulation in one iteration of loop() and do the extra stuf on the 60th iteration as “extended” path.

Update:
I have just seen a possible cause for your problem now.
It’s not the math, but your string operations.

You declare char publishData[] = "";
This only reserves an array of 1 character and after filling more than four characters into this array (due to 32bit alignment of variables), you’ll start overwriting your other variables. First sample_f and then wh_cum.
First you need to provide a useful size for your array and next I’d advise you to go for snprintf(buf, sizeof(buf), ...) to prevent sprintf() corrupting your data.

@qmnjb007, this is a recipe for danger:

char publishData[] = "";

This tells the compiler to allocate only what is necessary to fit the defined string “”. That ends up being a single element for the NULL terminator. You need to allocate a max size and I suggest something like this just to be sure on the size of the final published string:

char publishData[40] = "";

Try that and look at your published value shows. What does your “Energy” particle variable show?

1 Like

snap! :sunglasses:

@ScruffR @peekay123 Thank you so much for your help! Expanding the value of char publishData[] to a larger max size of 40 solved the problem. I will rework my code to no stay in a while loop for 5 min when I get a chance. Thanks!

2 Likes