Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

99 lines
2.5 KiB

  1. /*
  2. EmonLiteESP
  3. Energy Monitor Library for ESP8266 based on EmonLib
  4. Currently only support current sensing
  5. */
  6. #include "Arduino.h"
  7. #include "EmonLiteESP.h"
  8. void EnergyMonitor::initCurrent(current_c callback, double ref, double ratio) {
  9. _currentCallback = callback;
  10. _referenceVoltage = ref;
  11. _currentRatio = ratio;
  12. _currentMidPoint = (ADC_COUNTS>>1);
  13. calculatePrecision();
  14. warmup();
  15. };
  16. void EnergyMonitor::warmup() {
  17. int sample;
  18. for (unsigned int n = 0; n < WARMUP_COUNTS; n++) {
  19. sample = _currentCallback();
  20. _currentMidPoint = (_currentMidPoint + (sample - _currentMidPoint) / ADC_COUNTS);
  21. }
  22. }
  23. void EnergyMonitor::calculatePrecision() {
  24. _currentFactor = _currentRatio * _referenceVoltage / ADC_COUNTS;
  25. _precision = 0;
  26. _multiplier = 1;
  27. while (_multiplier * _currentFactor < 1) {
  28. _multiplier *= 10;
  29. ++_precision;
  30. }
  31. --_precision;
  32. _multiplier /= 10;
  33. }
  34. void EnergyMonitor::setReference(double ref) {
  35. _referenceVoltage = ref;
  36. }
  37. void EnergyMonitor::setCurrentRatio(double ratio) {
  38. _currentRatio = ratio;
  39. }
  40. byte EnergyMonitor::getPrecision() {
  41. return _precision;
  42. }
  43. void EnergyMonitor::setPrecision(byte precision) {
  44. _precision = precision;
  45. _multiplier = 1;
  46. for (byte i=0; i<_precision; i++) _multiplier *= 10;
  47. }
  48. double EnergyMonitor::getCurrent(unsigned int samples) {
  49. int sample;
  50. double filtered;
  51. double sum;
  52. //Serial.print("_currentMidPoint: "); Serial.println(_currentMidPoint);
  53. for (unsigned int n = 0; n < samples; n++) {
  54. // Read analog value
  55. sample = _currentCallback();
  56. // Digital low pass filter extracts the VDC offset
  57. _currentMidPoint = (_currentMidPoint + (sample - _currentMidPoint) / ADC_COUNTS);
  58. filtered = sample - _currentMidPoint;
  59. // Root-mean-square method
  60. sum += (filtered * filtered);
  61. }
  62. double rms = sqrt(sum / samples) - COUNT_OFFSET;
  63. if (rms < 0) rms = 0;
  64. double current = _currentFactor * rms;
  65. /*
  66. Serial.print("_currentMidPoint: "); Serial.println(_currentMidPoint);
  67. Serial.print("sample : "); Serial.println(sample);
  68. Serial.print("sum : "); Serial.println(sum);
  69. Serial.print("samples : "); Serial.println(samples);
  70. Serial.print("rms1 : "); Serial.println(sqrt(sum / samples));
  71. Serial.print("rms2 : "); Serial.println(rms);
  72. Serial.print("current : "); Serial.println(current);
  73. */
  74. current = round(current * _multiplier) / _multiplier;
  75. return current;
  76. };