Need help, not adding after 1024

Good day, Im trying to simulate AC Energy consumption. After the Energy adds up to 1024, it stops adding the Energy. On the “Setup” I have stated the from where the Energy should start “finalEnergyValue = 1023.9995;” but, once it adds up to 1024 it just doesn’t add anymore. Below is the code:


float accumulateEnergy = 0;
float finalEnergyValue = 0;

float voltage = 0;
float current = 0;
float power_factor = 0;
float realPower = 0;

void setup() {
  Serial.begin(9600);

  finalEnergyValue = 1023.9995; // Start with 1023.9995 to count beyond 1024
}

void loop() {

  voltage = 237.0;
  current = 0.5;
  power_factor = 1.0;

  realPower = voltage * current * power_factor;

  accumulateEnergy = realPower / 3600000.0;  // Energy in Watt-Hour
  finalEnergyValue = finalEnergyValue + accumulateEnergy;

  Serial.println(finalEnergyValue, 4);

  delay(977);
}

Result:
1023.9998
1023.9999
1024.0000
1024.0000
1024.0000
1024.0000
1024.0000
1024.0000
1024.0000

It Doesn't add from 1024

Float variables can accurately represent values with at most 6 to 7 decimal digits. 1023.9995 has eight.

Instead, use type double on MCUs that support that type (Arduino Uno, Mega and other AVR MCUs do not) and to maintain numerical accuracy, avoid adding very small values to large values.

Thank you very much for the reply, I changed from float to double, but as soon as it reaches 1024 it still doesn’t add from there. Im still new to Arduino, I really appreciate you helping me.

Post the revised code, and state which Arduino you are using.

Im using a Uno, and the the revised code is:


double accumulateEnergy = 0;
double finalEnergyValue = 0;

double voltage = 0;
double current = 0;
double power_factor = 0;
double realPower = 0;

void setup() {

  Serial.begin(9600);

  finalEnergyValue = 1023.9995; // Start with 1023.9995 to count beyond 1024
}



void loop() {

  voltage = 237.0;
  current = 0.5;
  power_factor = 1.0;

  realPower = voltage * current * power_factor;

  accumulateEnergy = realPower / 3600000.0;  // Energy in Watt-Hour
  finalEnergyValue = finalEnergyValue + accumulateEnergy;

  Serial.println(finalEnergyValue, 4);


  delay(977);
}

1023.9998
1023.9999
1024.0000
1024.0000
1024.0000
1024.0000
1024.0000
1024.0000
1024.0000

Doesnt add from 1024

The Uno does not support type double, so that is the expected result.

Is there any other solution?

Yes, rewrite the code to avoid adding very small floating point numbers to large ones.

For example, you could accumulate Watt-hours in short steps, maybe per hour instead of days or weeks.

But the “current” values are smaller than the “voltage” any other way to solve it? Thank you for taking the time appreciate it.

These two lines cause the problem:

  accumulateEnergy = realPower / 3600000.0;  // Energy in Watt-Hour
  finalEnergyValue = finalEnergyValue + accumulateEnergy;

Oh, I see, I will try to see how I can redo the formula, Thank you, really appreciate it.

There's probably a more elegant way to achieve the same result, but maybe something along these lines would work?

  finalEnergyDecimal = finalEnergyDecimal + accumulateEnergy;
  
  if (finalEnergyDecimal > 1) {
     finalEnergyValue += (int) finalEnergyDecimal;
     finalEnergyDecimal -= (int) finalEnergyDecimal;
  }

(store only the integer value in finalEnergyValue, and the decimal value in finalEnergyDecimal).

Thank you for your reply, since I’m still new to Arduino, what should it print” the “finalEnergyValue” or the “finalEnergyDecimal”?

Both. if the energy is 1025.87654, then finalEnergyValue will be 1025, and finalEnergyDecimal will be 0.87654.

Yes it worked, Thank you very much.

Glad I could help. If your problem is solved, you should mark the most relevant answer as the thread solution, by clicking the :white_check_mark: below the comment:
image

@x365
Where did you get these lines? Are you sure they are correct?

First, the comment in the second line does not correspond to reality, the formula does not give watt-hours, but kilowatt-hours.
And second, the most important thing is that the energy spent can only be calculated from the instantaneous power by integrating over time, which is not in this code
For integration, precise control of time intervals is required, without this, your formulas will give data that is very far from reality

Thanks for the reply, Yes, I should have changed my comment to “kilowatt-hours” it used to be “watt-hours” then I made it “kilowatt-hours” but forgot to change the comment to “kilowatt-hours.” This is only a simulation, just want to know why its not adding after 1024.

Just to update you, after testing your code for some time, I realised that it started counting backwards then I removed this line of code and it is working perfectly.

Removed this line:
finalEnergyDecimal -= (int) finalEnergyDecimal

Working code:

finalEnergyDecimal = finalEnergyDecimal + accumulateEnergy;

if (finalEnergyDecimal > 1) {
finalEnergyValue += (int) finalEnergyDecimal;
}

Thank you once again for coming up with a solution for me, really appreciate it.

Another approach is to use 32-bit or 64-bit integers.
Knowing that volts × amps × seconds = joules (1 J = 0.00027777 Wh), you can accumulate the joules and then divide by 3600 or 3,600,000 to obtain the Wh or kWh.