@@ -119,7 +119,7 @@ void EnergyMeterData::deserialize(StaticJsonDocument<capacity> &doc)
119119 // old OpenEvse total_energy imported flag
120120 imported = doc[" im" ];
121121 }
122- if (doc.containsKey (" el" ) && doc[" el" ].is <uint32_t >())
122+ if (doc.containsKey (" el" ) && doc[" el" ].is <double >())
123123 {
124124 // elapsed
125125 elapsed = doc[" el" ];
@@ -134,7 +134,6 @@ void EnergyMeterData::deserialize(StaticJsonDocument<capacity> &doc)
134134EnergyMeter::EnergyMeter () : _last_upd(0 ),
135135 _write_upd(0 ),
136136 _rotate_upd(0 ),
137- _elapsed(0 ),
138137 _switch_state(0 ){};
139138
140139EnergyMeter::~EnergyMeter ()
@@ -230,51 +229,23 @@ bool EnergyMeter::update()
230229 if (_monitor->isCharging ())
231230 {
232231 // increment elapsed time
233- _data.elapsed += dms / 1000U ;
232+ _data.elapsed += dms / 1000.0 ;
234233
235234 DBUGLN (" Energy Meter: Incrementing" );
236235 // accumulate data
237- uint32_t mv = _monitor->getVoltage () * 1000 ;
238- uint32_t ma = _monitor->getAmps () * 1000 ;
239-
240- /*
241- * The straightforward formula to compute 'milliwatt-seconds' would be:
242- * mws = (mv/1000) * (ma/1000) * dms;
243- *
244- * However, this has some serious drawbacks, namely, truncating values
245- * when using integer math. This can introduce a lot of error!
246- * 5900 milliamps -> 5.9 amps (float) -> 5 amps (integer)
247- * 0.9 amps difference / 5.9 amps -> 15.2% error
248- *
249- * The crazy equation below helps ensure our intermediate results always
250- * fit in a 32-bit unsigned integer, but retain as much precision as
251- * possible throughout the calculation. Here is how it was derived:
252- * mws = (mv/1000) * (ma/1000) * dms;
253- * mws = (mv/(2**3 * 5**3)) * (ma/(2**3 * 5**3)) * dms;
254- * mws = (mv/2**3) * (ma/(2**3) / 5**6 * dms;
255- * mws = (mv/2**4) * (ma/(2**2) / 5**6 * dms;
256- *
257- * By breaking 1000 into prime factors of 2 and 5, and shifting things
258- * around, we almost match the precision of floating-point math.
259- *
260- * Using 16 and 4 divisors, rather than 8 and 8, helps precision because
261- * mv is always greater than ~100000, but ma can be as low as ~6000.
262- *
263- * A final note- the divisions by factors of 2 are done with right shifts
264- * by the compiler, so the revised equation, although it looks quite
265- * complex, only requires one divide operation.
266- */
267- double mws = (mv / 16 ) * (ma / 4 ) / 15625 * dms;
236+ double v = _monitor->getVoltage ();
237+ double a = _monitor->getAmps ();
238+ double mws = v * a * dms;
268239 if (config_threephase_enabled ())
269240 {
270241 // Multiply calculation by 3 to get 3-phase energy.
271242 mws *= 3 ;
272243 }
273244
274245 // convert to w/h
275- double wh = mws / 3600000UL ;
246+ double wh = mws / 3600000 ;
276247 _data.session += wh;
277- double kwh = wh / 1000UL ;
248+ double kwh = wh / 1000 ;
278249 _data.total += kwh;
279250 DBUGVAR (_data.session );
280251 _data.daily += kwh;
@@ -318,7 +289,7 @@ bool EnergyMeter::publish()
318289
319290void EnergyMeter::createEnergyMeterJsonDoc (JsonDocument &doc)
320291{
321- doc[" session_elapsed" ] = _data.elapsed ; // sec
292+ doc[" session_elapsed" ] = ( uint32_t ) _data.elapsed ; // sec
322293 doc[" session_energy" ] = _data.session ; // wh
323294 doc[" total_energy" ] = _data.total ; // kwh
324295 doc[" total_day" ] = _data.daily ; // kwh
0 commit comments