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.

201 lines
5.2 KiB

  1. /*
  2. POWER ECH1560 MODULE
  3. Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
  4. */
  5. #if POWER_PROVIDER == POWER_PROVIDER_ECH1560
  6. // -----------------------------------------------------------------------------
  7. // MODULE GLOBALS AND CACHE
  8. // -----------------------------------------------------------------------------
  9. volatile long _ech1560_bits_count = 0;
  10. volatile long _ech1560_clk_count = 0;
  11. volatile bool _ech1560_dosync = false;
  12. volatile bool _ech1560_nextbit = true;
  13. double _ech1560_apparent = 0;
  14. double _ech1560_voltage = 0;
  15. double _ech1560_current = 0;
  16. // -----------------------------------------------------------------------------
  17. // HAL
  18. // -----------------------------------------------------------------------------
  19. void _ech1560_sync() {
  20. unsigned int byte1 = 0;
  21. unsigned int byte2 = 0;
  22. unsigned int byte3 = 0;
  23. _ech1560_bits_count = 0;
  24. while (_ech1560_bits_count < 40); // skip the uninteresting 5 first bytes
  25. _ech1560_bits_count = 0;
  26. while (_ech1560_bits_count < 24) { // loop through the next 3 Bytes (6-8) and save byte 6 and 7 in Ba and Bb
  27. if (_ech1560_nextbit) {
  28. if (_ech1560_bits_count < 9) { // first Byte/8 bits in Ba
  29. byte1 = byte1 << 1;
  30. if (digitalRead(ECH1560_MISO_PIN) == HIGH) byte1 |= 1;
  31. _ech1560_nextbit = false;
  32. } else if (_ech1560_bits_count < 17) { // bit 9-16 is byte 7, stor in Bb
  33. byte2 = byte2 << 1;
  34. if (digitalRead(ECH1560_MISO_PIN) == HIGH) byte2 |= 1;
  35. _ech1560_nextbit = false;
  36. }
  37. }
  38. }
  39. if (byte2 != 3) { // if bit Bb is not 3, we have reached the important part, U is allready in Ba and Bb and next 8 Bytes will give us the Power.
  40. // voltage = 2 * (Ba + Bb / 255)
  41. _ech1560_voltage = 2.0 * ((float) byte1 + (float) byte2 / 255.0);
  42. // power:
  43. _ech1560_bits_count = 0;
  44. while (_ech1560_bits_count < 40); // skip the uninteresting 5 first bytes
  45. _ech1560_bits_count = 0;
  46. byte1 = 0;
  47. byte2 = 0;
  48. byte3 = 0;
  49. while (_ech1560_bits_count < 24) { //store byte 6, 7 and 8 in Ba and Bb & Bc.
  50. if (_ech1560_nextbit) {
  51. if (_ech1560_bits_count < 9) {
  52. byte1 = byte1 << 1;
  53. if (digitalRead(ECH1560_MISO_PIN) == HIGH) byte1 |= 1;
  54. _ech1560_nextbit = false;
  55. } else if (_ech1560_bits_count < 17) {
  56. byte2 = byte2 << 1;
  57. if (digitalRead(ECH1560_MISO_PIN) == HIGH) byte2 |= 1;
  58. _ech1560_nextbit = false;
  59. } else {
  60. byte3 = byte3 << 1;
  61. if (digitalRead(ECH1560_MISO_PIN) == HIGH) byte3 |= 1;
  62. _ech1560_nextbit = false;
  63. }
  64. }
  65. }
  66. // power = (Ba*255+Bb+Bc/255)/2
  67. _ech1560_apparent = ( (float) byte1 * 255 + (float) byte2 + (float) byte3 / 255.0) / 2;
  68. _ech1560_current = _ech1560_apparent / _ech1560_voltage;
  69. _power_newdata = true;
  70. _ech1560_dosync = false;
  71. }
  72. // If Bb is not 3 or something else than 0, something is wrong!
  73. if (byte2 == 0) _ech1560_dosync = false;
  74. }
  75. void ICACHE_RAM_ATTR _ech1560_isr() {
  76. // if we are trying to find the sync-time (CLK goes high for 1-2ms)
  77. if (_ech1560_dosync == false) {
  78. _ech1560_clk_count = 0;
  79. // register how long the ClkHigh is high to evaluate if we are at the part wher clk goes high for 1-2 ms
  80. while (digitalRead(ECH1560_CLK_PIN) == HIGH) {
  81. _ech1560_clk_count += 1;
  82. delayMicroseconds(30); //can only use delayMicroseconds in an interrupt.
  83. }
  84. // if the Clk was high between 1 and 2 ms than, its a start of a SPI-transmission
  85. if (_ech1560_clk_count >= 33 && _ech1560_clk_count <= 67) {
  86. _ech1560_dosync = true;
  87. }
  88. // we are in sync and logging CLK-highs
  89. } else {
  90. // increment an integer to keep track of how many bits we have read.
  91. _ech1560_bits_count += 1;
  92. _ech1560_nextbit = true;
  93. }
  94. }
  95. // -----------------------------------------------------------------------------
  96. // POWER API
  97. // -----------------------------------------------------------------------------
  98. double _powerCurrent() {
  99. return _ech1560_current;
  100. }
  101. double _powerVoltage() {
  102. return _ech1560_voltage;
  103. }
  104. double _powerActivePower() {
  105. return 0;
  106. }
  107. double _powerApparentPower() {
  108. return _ech1560_apparent;
  109. }
  110. double _powerReactivePower() {
  111. return 0;
  112. }
  113. double _powerPowerFactor() {
  114. return 1;
  115. }
  116. void _powerEnabledProvider() {
  117. // Nothing to do
  118. }
  119. void _powerConfigureProvider() {
  120. // Nothing to do
  121. }
  122. void _powerCalibrateProvider(unsigned char magnitude, double value) {
  123. // Nothing to do
  124. }
  125. void _powerResetCalibrationProvider() {
  126. // Nothing to do
  127. }
  128. void _powerSetupProvider() {
  129. pinMode(ECH1560_CLK_PIN, INPUT);
  130. pinMode(ECH1560_MISO_PIN, INPUT);
  131. attachInterrupt(ECH1560_CLK_PIN, _ech1560_isr, RISING);
  132. }
  133. void _powerLoopProvider(bool before) {
  134. if (!before) {
  135. if (_ech1560_dosync) _ech1560_sync();
  136. }
  137. }
  138. #endif // POWER_PROVIDER & POWER_PROVIDER_EMON