xsns_12_ads1115.ino 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /*
  2. xsns_12_ads1115_ada.ino - ADS1115 A/D Converter support for Sonoff-Tasmota
  3. Copyright (C) 2018 Theo Arends
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #ifdef USE_I2C
  16. #ifdef USE_ADS1115
  17. /*********************************************************************************************\
  18. * ADS1115 - 4 channel 16BIT A/D converter
  19. *
  20. * Required library: none but based on Adafruit Industries ADS1015 library
  21. *
  22. * I2C Address: 0x48, 0x49, 0x4A or 0x4B
  23. *
  24. * The ADC input range (or gain) can be changed via the following
  25. * defines, but be careful never to exceed VDD +0.3V max, or to
  26. * exceed the upper and lower limits if you adjust the input range!
  27. * Setting these values incorrectly may destroy your ADC!
  28. * ADS1115
  29. * -------
  30. * ADS1115_REG_CONFIG_PGA_6_144V // 2/3x gain +/- 6.144V 1 bit = 0.1875mV (default)
  31. * ADS1115_REG_CONFIG_PGA_4_096V // 1x gain +/- 4.096V 1 bit = 0.125mV
  32. * ADS1115_REG_CONFIG_PGA_2_048V // 2x gain +/- 2.048V 1 bit = 0.0625mV
  33. * ADS1115_REG_CONFIG_PGA_1_024V // 4x gain +/- 1.024V 1 bit = 0.03125mV
  34. * ADS1115_REG_CONFIG_PGA_0_512V // 8x gain +/- 0.512V 1 bit = 0.015625mV
  35. * ADS1115_REG_CONFIG_PGA_0_256V // 16x gain +/- 0.256V 1 bit = 0.0078125mV
  36. \*********************************************************************************************/
  37. #define XSNS_12 12
  38. #define ADS1115_ADDRESS_ADDR_GND 0x48 // address pin low (GND)
  39. #define ADS1115_ADDRESS_ADDR_VDD 0x49 // address pin high (VCC)
  40. #define ADS1115_ADDRESS_ADDR_SDA 0x4A // address pin tied to SDA pin
  41. #define ADS1115_ADDRESS_ADDR_SCL 0x4B // address pin tied to SCL pin
  42. #define ADS1115_CONVERSIONDELAY (8) // CONVERSION DELAY (in mS)
  43. /*======================================================================
  44. POINTER REGISTER
  45. -----------------------------------------------------------------------*/
  46. #define ADS1115_REG_POINTER_MASK (0x03)
  47. #define ADS1115_REG_POINTER_CONVERT (0x00)
  48. #define ADS1115_REG_POINTER_CONFIG (0x01)
  49. #define ADS1115_REG_POINTER_LOWTHRESH (0x02)
  50. #define ADS1115_REG_POINTER_HITHRESH (0x03)
  51. /*======================================================================
  52. CONFIG REGISTER
  53. -----------------------------------------------------------------------*/
  54. #define ADS1115_REG_CONFIG_OS_MASK (0x8000)
  55. #define ADS1115_REG_CONFIG_OS_SINGLE (0x8000) // Write: Set to start a single-conversion
  56. #define ADS1115_REG_CONFIG_OS_BUSY (0x0000) // Read: Bit = 0 when conversion is in progress
  57. #define ADS1115_REG_CONFIG_OS_NOTBUSY (0x8000) // Read: Bit = 1 when device is not performing a conversion
  58. #define ADS1115_REG_CONFIG_MUX_MASK (0x7000)
  59. #define ADS1115_REG_CONFIG_MUX_DIFF_0_1 (0x0000) // Differential P = AIN0, N = AIN1 (default)
  60. #define ADS1115_REG_CONFIG_MUX_DIFF_0_3 (0x1000) // Differential P = AIN0, N = AIN3
  61. #define ADS1115_REG_CONFIG_MUX_DIFF_1_3 (0x2000) // Differential P = AIN1, N = AIN3
  62. #define ADS1115_REG_CONFIG_MUX_DIFF_2_3 (0x3000) // Differential P = AIN2, N = AIN3
  63. #define ADS1115_REG_CONFIG_MUX_SINGLE_0 (0x4000) // Single-ended AIN0
  64. #define ADS1115_REG_CONFIG_MUX_SINGLE_1 (0x5000) // Single-ended AIN1
  65. #define ADS1115_REG_CONFIG_MUX_SINGLE_2 (0x6000) // Single-ended AIN2
  66. #define ADS1115_REG_CONFIG_MUX_SINGLE_3 (0x7000) // Single-ended AIN3
  67. #define ADS1115_REG_CONFIG_PGA_MASK (0x0E00)
  68. #define ADS1115_REG_CONFIG_PGA_6_144V (0x0000) // +/-6.144V range = Gain 2/3 (default)
  69. #define ADS1115_REG_CONFIG_PGA_4_096V (0x0200) // +/-4.096V range = Gain 1
  70. #define ADS1115_REG_CONFIG_PGA_2_048V (0x0400) // +/-2.048V range = Gain 2
  71. #define ADS1115_REG_CONFIG_PGA_1_024V (0x0600) // +/-1.024V range = Gain 4
  72. #define ADS1115_REG_CONFIG_PGA_0_512V (0x0800) // +/-0.512V range = Gain 8
  73. #define ADS1115_REG_CONFIG_PGA_0_256V (0x0A00) // +/-0.256V range = Gain 16
  74. #define ADS1115_REG_CONFIG_MODE_MASK (0x0100)
  75. #define ADS1115_REG_CONFIG_MODE_CONTIN (0x0000) // Continuous conversion mode
  76. #define ADS1115_REG_CONFIG_MODE_SINGLE (0x0100) // Power-down single-shot mode (default)
  77. #define ADS1115_REG_CONFIG_DR_MASK (0x00E0)
  78. #define ADS1115_REG_CONFIG_DR_128SPS (0x0000) // 128 samples per second
  79. #define ADS1115_REG_CONFIG_DR_250SPS (0x0020) // 250 samples per second
  80. #define ADS1115_REG_CONFIG_DR_490SPS (0x0040) // 490 samples per second
  81. #define ADS1115_REG_CONFIG_DR_920SPS (0x0060) // 920 samples per second
  82. #define ADS1115_REG_CONFIG_DR_1600SPS (0x0080) // 1600 samples per second (default)
  83. #define ADS1115_REG_CONFIG_DR_2400SPS (0x00A0) // 2400 samples per second
  84. #define ADS1115_REG_CONFIG_DR_3300SPS (0x00C0) // 3300 samples per second
  85. #define ADS1115_REG_CONFIG_DR_6000SPS (0x00E0) // 6000 samples per second
  86. #define ADS1115_REG_CONFIG_CMODE_MASK (0x0010)
  87. #define ADS1115_REG_CONFIG_CMODE_TRAD (0x0000) // Traditional comparator with hysteresis (default)
  88. #define ADS1115_REG_CONFIG_CMODE_WINDOW (0x0010) // Window comparator
  89. #define ADS1115_REG_CONFIG_CPOL_MASK (0x0008)
  90. #define ADS1115_REG_CONFIG_CPOL_ACTVLOW (0x0000) // ALERT/RDY pin is low when active (default)
  91. #define ADS1115_REG_CONFIG_CPOL_ACTVHI (0x0008) // ALERT/RDY pin is high when active
  92. #define ADS1115_REG_CONFIG_CLAT_MASK (0x0004) // Determines if ALERT/RDY pin latches once asserted
  93. #define ADS1115_REG_CONFIG_CLAT_NONLAT (0x0000) // Non-latching comparator (default)
  94. #define ADS1115_REG_CONFIG_CLAT_LATCH (0x0004) // Latching comparator
  95. #define ADS1115_REG_CONFIG_CQUE_MASK (0x0003)
  96. #define ADS1115_REG_CONFIG_CQUE_1CONV (0x0000) // Assert ALERT/RDY after one conversions
  97. #define ADS1115_REG_CONFIG_CQUE_2CONV (0x0001) // Assert ALERT/RDY after two conversions
  98. #define ADS1115_REG_CONFIG_CQUE_4CONV (0x0002) // Assert ALERT/RDY after four conversions
  99. #define ADS1115_REG_CONFIG_CQUE_NONE (0x0003) // Disable the comparator and put ALERT/RDY in high state (default)
  100. uint8_t ads1115_type = 0;
  101. uint8_t ads1115_address;
  102. uint8_t ads1115_addresses[] = { ADS1115_ADDRESS_ADDR_GND, ADS1115_ADDRESS_ADDR_VDD, ADS1115_ADDRESS_ADDR_SDA, ADS1115_ADDRESS_ADDR_SCL };
  103. //Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_SINGLE);
  104. //Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_CONTIN);
  105. void Ads1115StartComparator(uint8_t channel, uint16_t mode)
  106. {
  107. // Start with default values
  108. uint16_t config = mode |
  109. ADS1115_REG_CONFIG_CQUE_NONE | // Comparator enabled and asserts on 1 match
  110. ADS1115_REG_CONFIG_CLAT_NONLAT | // Non Latching mode
  111. ADS1115_REG_CONFIG_PGA_6_144V | // ADC Input voltage range (Gain)
  112. ADS1115_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low (default val)
  113. ADS1115_REG_CONFIG_CMODE_TRAD | // Traditional comparator (default val)
  114. ADS1115_REG_CONFIG_DR_6000SPS; // 6000 samples per second
  115. // Set single-ended input channel
  116. config |= (ADS1115_REG_CONFIG_MUX_SINGLE_0 + (0x1000 * channel));
  117. // Write config register to the ADC
  118. I2cWrite16(ads1115_address, ADS1115_REG_POINTER_CONFIG, config);
  119. }
  120. int16_t Ads1115GetConversion(uint8_t channel)
  121. {
  122. Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_SINGLE);
  123. // Wait for the conversion to complete
  124. delay(ADS1115_CONVERSIONDELAY);
  125. // Read the conversion results
  126. I2cRead16(ads1115_address, ADS1115_REG_POINTER_CONVERT);
  127. Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_CONTIN);
  128. delay(ADS1115_CONVERSIONDELAY);
  129. // Read the conversion results
  130. uint16_t res = I2cRead16(ads1115_address, ADS1115_REG_POINTER_CONVERT);
  131. return (int16_t)res;
  132. }
  133. /********************************************************************************************/
  134. void Ads1115Detect(void)
  135. {
  136. uint16_t buffer;
  137. if (ads1115_type) {
  138. return;
  139. }
  140. for (byte i = 0; i < sizeof(ads1115_addresses); i++) {
  141. ads1115_address = ads1115_addresses[i];
  142. if (I2cValidRead16(&buffer, ads1115_address, ADS1115_REG_POINTER_CONVERT)) {
  143. Ads1115StartComparator(i, ADS1115_REG_CONFIG_MODE_CONTIN);
  144. ads1115_type = 1;
  145. snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "ADS1115", ads1115_address);
  146. AddLog(LOG_LEVEL_DEBUG);
  147. break;
  148. }
  149. }
  150. }
  151. void Ads1115Show(boolean json)
  152. {
  153. if (ads1115_type) {
  154. char stemp[10];
  155. byte dsxflg = 0;
  156. for (byte i = 0; i < 4; i++) {
  157. int16_t adc_value = Ads1115GetConversion(i);
  158. if (json) {
  159. if (!dsxflg ) {
  160. snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"ADS1115\":{"), mqtt_data);
  161. stemp[0] = '\0';
  162. }
  163. dsxflg++;
  164. snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"A%d\":%d"), mqtt_data, stemp, i, adc_value);
  165. strlcpy(stemp, ",", sizeof(stemp));
  166. #ifdef USE_WEBSERVER
  167. } else {
  168. snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, "ADS1115", i, adc_value);
  169. #endif // USE_WEBSERVER
  170. }
  171. }
  172. if (json) {
  173. if (dsxflg) {
  174. snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
  175. }
  176. }
  177. }
  178. }
  179. /*********************************************************************************************\
  180. * Interface
  181. \*********************************************************************************************/
  182. boolean Xsns12(byte function)
  183. {
  184. boolean result = false;
  185. if (i2c_flg) {
  186. switch (function) {
  187. case FUNC_PREP_BEFORE_TELEPERIOD:
  188. Ads1115Detect();
  189. break;
  190. case FUNC_JSON_APPEND:
  191. Ads1115Show(1);
  192. break;
  193. #ifdef USE_WEBSERVER
  194. case FUNC_WEB_APPEND:
  195. Ads1115Show(0);
  196. break;
  197. #endif // USE_WEBSERVER
  198. }
  199. }
  200. return result;
  201. }
  202. #endif // USE_ADS1115
  203. #endif // USE_I2C