ADS1118.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. /**
  2. * Arduino Library for Texas Instruments ADS1118 - 16-Bit Analog-to-Digital Converter with
  3. * Internal Reference and Temperature Sensor
  4. *
  5. * @author Alvaro Salazar <alvaro@denkitronik.com>
  6. * http://www.denkitronik.com
  7. *
  8. */
  9. /**
  10. * The MIT License
  11. *
  12. * Copyright 2018 Alvaro Salazar <alvaro@denkitronik.com>.
  13. *
  14. * Permission is hereby granted, free of charge, to any person obtaining a copy
  15. * of this software and associated documentation files (the "Software"), to deal
  16. * in the Software without restriction, including without limitation the rights
  17. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  18. * copies of the Software, and to permit persons to whom the Software is
  19. * furnished to do so, subject to the following conditions:
  20. *
  21. * The above copyright notice and this permission notice shall be included in
  22. * all copies or substantial portions of the Software.
  23. *
  24. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  25. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  26. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  27. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  28. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  29. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  30. * THE SOFTWARE.
  31. */
  32. #include "ADS1118.h"
  33. #include "Arduino.h"
  34. /**
  35. * Debugging:
  36. * Uncomment some of the 3 lines above to debug the method you want.
  37. * Warning:
  38. * Keep them commented in production
  39. */
  40. //#define DEBUG_BEGIN //Debug begin() method
  41. //#define DEBUG_GETADCVALUE //Debug getADCValue() method
  42. //#define DEBUG_GETTEMPERATURE //Debug getTemperature() method
  43. #ifdef DEBUG_BEGIN
  44. #define DEBUG_BEGIN(x) decodeConfigRegister(x)
  45. #else
  46. #define DEBUG_BEGIN(x)
  47. #endif
  48. #ifdef DEBUG_GETADCVALUE
  49. #define DEBUG_GETADCVALUE(x) decodeConfigRegister(x)
  50. #else
  51. #define DEBUG_GETADCVALUE(x)
  52. #endif
  53. #ifdef DEBUG_GETTEMPERATURE
  54. #define DEBUG_GETTEMPERATURE(x) decodeConfigRegister(x)
  55. #else
  56. #define DEBUG_GETTEMPERATURE(x)
  57. #endif
  58. #if defined(__AVR__)
  59. /**
  60. * Constructor of the class
  61. * @param io_pin_cs a byte indicating the pin to be use as the chip select pin (CS)
  62. */
  63. ADS1118::ADS1118(uint8_t io_pin_cs) {
  64. cs = io_pin_cs;
  65. } ///< This method initialize the SPI port and the config register
  66. #elif defined(ESP32)
  67. /**
  68. * Constructor of the class
  69. * @param io_pin_cs a byte indicating the pin to be use as the chip select pin (CS)
  70. */
  71. ADS1118::ADS1118(uint8_t io_pin_cs, SPIClass *spi) {
  72. cs = io_pin_cs;
  73. pSpi = spi;
  74. }
  75. #endif
  76. #if defined(__AVR__)
  77. /**
  78. * This method initialize the SPI port and the config register
  79. */
  80. void ADS1118::begin() {
  81. pinMode(cs, OUTPUT);
  82. digitalWrite(cs, HIGH);
  83. SPI.begin();
  84. SPI.beginTransaction(SPISettings(SCLK, MSBFIRST, SPI_MODE1));
  85. configRegister.bits={RESERVED, VALID_CFG, DOUT_PULLUP, ADC_MODE, RATE_8SPS, SINGLE_SHOT, FSR_0256, DIFF_0_1, START_NOW}; //Default values
  86. DEBUG_BEGIN(configRegister); //Debug this method: print the config register in the Serial port
  87. } ///< This method initialize the SPI port and the config register
  88. #elif defined(ESP32)
  89. /**
  90. * This method initialize the SPI port and the config register
  91. */
  92. void ADS1118::begin() {
  93. pinMode(cs, OUTPUT);
  94. digitalWrite(cs, HIGH);
  95. pSpi->begin();
  96. configRegister.bits={RESERVED, VALID_CFG, DOUT_PULLUP, ADC_MODE, RATE_8SPS, SINGLE_SHOT, FSR_0256, DIFF_0_1, START_NOW}; //Default values
  97. DEBUG_BEGIN(configRegister); //Debug this method: print the config register in the Serial port
  98. }
  99. void ADS1118::begin(uint8_t sclk, uint8_t miso, uint8_t mosi) {
  100. pinMode(cs, OUTPUT);
  101. digitalWrite(cs, HIGH);
  102. pSpi->begin(sclk, miso, mosi, cs);
  103. configRegister.bits={RESERVED, VALID_CFG, DOUT_PULLUP, ADC_MODE, RATE_8SPS, SINGLE_SHOT, FSR_0256, DIFF_0_1, START_NOW}; //Default values
  104. DEBUG_BEGIN(configRegister); //Debug this method: print the config register in the Serial port
  105. }
  106. /**
  107. * Getting a sample from the specified input if data is ready
  108. * @param pin_drdy io pin connected to ADS1118 DOUT/DRDY. value Reference of ADC value to be fetched
  109. * @return True if ADC data is ready
  110. */
  111. bool ADS1118::getADCValueNoWait(uint8_t pin_drdy, uint16_t &value) {
  112. byte dataMSB, dataLSB;
  113. pSpi->beginTransaction(SPISettings(SCLK, MSBFIRST, SPI_MODE1));
  114. digitalWrite(cs, LOW);
  115. if (digitalRead(pin_drdy)) {
  116. digitalWrite(cs, HIGH);
  117. pSpi->endTransaction();
  118. return false;
  119. }
  120. dataMSB = pSpi->transfer(configRegister.byte.msb);
  121. dataLSB = pSpi->transfer(configRegister.byte.lsb);
  122. digitalWrite(cs, HIGH);
  123. pSpi->endTransaction();
  124. value = (dataMSB << 8) | (dataLSB);
  125. return true;
  126. }
  127. /**
  128. * Getting the millivolts from the settled inputs
  129. * @return A double (32bits) containing the ADC value in millivolts
  130. */
  131. bool ADS1118::getMilliVoltsNoWait(uint8_t pin_drdy, double &volts) {
  132. float fsr = pgaFSR[configRegister.bits.pga];
  133. uint16_t value;
  134. bool dataReady=getADCValueNoWait(pin_drdy, value);
  135. if (!dataReady) return false;
  136. if(value>=0x8000){
  137. value=((~value)+1); //Applying binary twos complement format
  138. volts=((float)(value*fsr/32768)*-1);
  139. } else {
  140. volts=(float)(value*fsr/32768);
  141. }
  142. volts = volts*1000;
  143. return true;
  144. }
  145. #endif
  146. /**
  147. * Getting a sample from the specified input
  148. * @param inputs Sets the input of the ADC: Diferential inputs: DIFF_0_1, DIFF_0_3, DIFF_1_3, DIFF_2_3. Single ended input: AIN_0, AIN_1, AIN_2, AIN_3
  149. * @return A word containing the ADC value
  150. */
  151. uint16_t ADS1118::getADCValue(uint8_t inputs) {
  152. uint16_t value;
  153. byte dataMSB, dataLSB, configMSB, configLSB, count=0;
  154. if(lastSensorMode==ADC_MODE) //Lucky you! We don't have to read twice the sensor
  155. count=1;
  156. else
  157. configRegister.bits.sensorMode=ADC_MODE; //Sorry but we will have to read twice the sensor
  158. configRegister.bits.mux=inputs;
  159. do{
  160. #if defined(ESP32)
  161. pSpi->beginTransaction(SPISettings(SCLK, MSBFIRST, SPI_MODE1));
  162. #endif
  163. digitalWrite(cs, LOW);
  164. #if defined(__AVR__)
  165. dataMSB = SPI.transfer(configRegister.byte.msb);
  166. dataLSB = SPI.transfer(configRegister.byte.lsb);
  167. configMSB = SPI.transfer(configRegister.byte.msb);
  168. configLSB = SPI.transfer(configRegister.byte.lsb);
  169. #elif defined(ESP32)
  170. dataMSB = pSpi->transfer(configRegister.byte.msb);
  171. dataLSB = pSpi->transfer(configRegister.byte.lsb);
  172. configMSB = pSpi->transfer(configRegister.byte.msb);
  173. configLSB = pSpi->transfer(configRegister.byte.lsb);
  174. #endif
  175. digitalWrite(cs, HIGH);
  176. #if defined(ESP32)
  177. pSpi->endTransaction();
  178. #endif
  179. for(int i=0;i<CONV_TIME[configRegister.bits.rate];i++) //Lets wait the conversion time
  180. delayMicroseconds(1000);
  181. count++;
  182. }while (count<=1); //We make two readings because the second reading is the ADC conversion.
  183. DEBUG_GETADCVALUE(configRegister); //Debug this method: print the config register in the Serial port
  184. value = (dataMSB << 8) | (dataLSB);
  185. return value;
  186. }
  187. /**
  188. * Getting the millivolts from the specified inputs
  189. * @param inputs Sets the inputs to be adquired. Diferential inputs: DIFF_0_1, DIFF_0_3, DIFF_1_3, DIFF_2_3. Single ended input: AIN_0, AIN_1, AIN_2, AIN_3
  190. * @return A double (32bits) containing the ADC value in millivolts
  191. */
  192. double ADS1118::getMilliVolts(uint8_t inputs) {
  193. float volts;
  194. float fsr = pgaFSR[configRegister.bits.pga];
  195. uint16_t value;
  196. value=getADCValue(inputs);
  197. if(value>=0x8000){
  198. value=((~value)+1); //Applying binary twos complement format
  199. volts=((float)(value*fsr/32768)*-1);
  200. } else {
  201. volts=(float)(value*fsr/32768);
  202. }
  203. return volts*1000;
  204. }
  205. /**
  206. * Getting the millivolts from the settled inputs
  207. * @return A double (32bits) containing the ADC value in millivolts
  208. */
  209. double ADS1118::getMilliVolts() {
  210. float volts;
  211. float fsr = pgaFSR[configRegister.bits.pga];
  212. uint16_t value;
  213. value=getADCValue(configRegister.bits.mux);
  214. if(value>=0x8000){
  215. value=((~value)+1); //Applying binary twos complement format
  216. volts=((float)(value*fsr/32768)*-1);
  217. } else {
  218. volts=(float)(value*fsr/32768);
  219. }
  220. return volts*1000;
  221. }
  222. /**
  223. * Getting the temperature in degrees celsius from the internal sensor of the ADS1118
  224. * @return A double (32bits) containing the temperature in degrees celsius of the internal sensor
  225. */
  226. double ADS1118::getTemperature() {
  227. uint16_t convRegister;
  228. uint8_t dataMSB, dataLSB, configMSB, configLSB, count=0;
  229. if(lastSensorMode==TEMP_MODE)
  230. count=1; //Lucky you! We don't have to read twice the sensor
  231. else
  232. configRegister.bits.sensorMode=TEMP_MODE; //Sorry but we will have to read twice the sensor
  233. do{
  234. #if defined(ESP32)
  235. pSpi->beginTransaction(SPISettings(SCLK, MSBFIRST, SPI_MODE1));
  236. #endif
  237. digitalWrite(cs, LOW);
  238. #if defined(__AVR__)
  239. dataMSB = SPI.transfer(configRegister.byte.msb);
  240. dataLSB = SPI.transfer(configRegister.byte.lsb);
  241. configMSB = SPI.transfer(configRegister.byte.msb);
  242. configLSB = SPI.transfer(configRegister.byte.lsb);
  243. #elif defined(ESP32)
  244. dataMSB = pSpi->transfer(configRegister.byte.msb);
  245. dataLSB = pSpi->transfer(configRegister.byte.lsb);
  246. configMSB = pSpi->transfer(configRegister.byte.msb);
  247. configLSB = pSpi->transfer(configRegister.byte.lsb);
  248. #endif
  249. digitalWrite(cs, HIGH);
  250. #if defined(ESP32)
  251. pSpi->endTransaction();
  252. #endif
  253. for(int i=0;i<CONV_TIME[configRegister.bits.rate];i++) //Lets wait the conversion time
  254. delayMicroseconds(1000);
  255. count++;
  256. }while (count<=1); //We make two readings because the second reading is the temperature.
  257. DEBUG_GETTEMPERATURE(configRegister); //Debug this method: print the config register in the Serial port
  258. convRegister = ((dataMSB << 8) | (dataLSB))>>2;
  259. if((convRegister<<2) >= 0x8000){
  260. convRegister=((~convRegister)>>2)+1; //Converting to right-justified and applying binary twos complement format
  261. return (double)(convRegister*0.03125*-1);
  262. }
  263. return (double)convRegister*0.03125;
  264. }
  265. /**
  266. * Setting the sampling rate specified in the config register
  267. * @param samplingRate It's the sampling rate: RATE_8SPS, RATE_16SPS, RATE_32SPS, RATE_64SPS, RATE_128SPS, RATE_250SPS, RATE_475SPS, RATE_860SPS
  268. */
  269. void ADS1118::setSamplingRate(uint8_t samplingRate){
  270. configRegister.bits.rate=samplingRate;
  271. }
  272. /**
  273. * Setting the full scale range in the config register
  274. * @param fsr The full scale range: FSR_6144 (±6.144V)*, FSR_4096(±4.096V)*, FSR_2048(±2.048V), FSR_1024(±1.024V), FSR_0512(±0.512V), FSR_0256(±0.256V). (*) No more than VDD + 0.3 V must be applied to this device.
  275. */
  276. void ADS1118::setFullScaleRange(uint8_t fsr){
  277. configRegister.bits.pga=fsr;
  278. }
  279. /**
  280. * Setting the inputs to be adquired in the config register.
  281. * @param input The input selected: Diferential inputs: DIFF_0_1, DIFF_0_3, DIFF_1_3, DIFF_2_3. Single ended input: AIN_0, AIN_1, AIN_2, AIN_3
  282. */
  283. void ADS1118::setInputSelected(uint8_t input){
  284. configRegister.bits.mux=input;
  285. }
  286. /**
  287. * Setting to continuous adquisition mode
  288. */
  289. void ADS1118::setContinuousMode(){
  290. configRegister.bits.operatingMode=CONTINUOUS;
  291. }
  292. /**
  293. * Setting to single shot adquisition and power down mode
  294. */
  295. void ADS1118::setSingleShotMode(){
  296. configRegister.bits.operatingMode=SINGLE_SHOT;
  297. }
  298. /**
  299. * Disabling the internal pull-up resistor of the DOUT pin
  300. */
  301. void ADS1118::disablePullup(){
  302. configRegister.bits.operatingMode=DOUT_NO_PULLUP;
  303. }
  304. /**
  305. * Enabling the internal pull-up resistor of the DOUT pin
  306. */
  307. void ADS1118::enablePullup(){
  308. configRegister.bits.operatingMode=DOUT_PULLUP;
  309. }
  310. /**
  311. * Decoding a configRegister structure and then print it out to the Serial port
  312. * @param configRegister The config register in "union Config" format
  313. */
  314. void ADS1118::decodeConfigRegister(union Config configRegister){
  315. String mensaje=String();
  316. switch(configRegister.bits.singleStart){
  317. case 0: mensaje="NOINI"; break;
  318. case 1: mensaje="START"; break;
  319. }
  320. mensaje+=" ";
  321. switch(configRegister.bits.mux){
  322. case 0: mensaje+="A0-A1"; break;
  323. case 1: mensaje+="A0-A3"; break;
  324. case 2: mensaje+="A1-A3"; break;
  325. case 3: mensaje+="A2-A3"; break;
  326. case 4: mensaje+="A0-GD"; break;
  327. case 5: mensaje+="A1-GD"; break;
  328. case 6: mensaje+="A2-GD"; break;
  329. case 7: mensaje+="A3-GD"; break;
  330. }
  331. mensaje+=" ";
  332. switch(configRegister.bits.pga){
  333. case 0: mensaje+="6.144"; break;
  334. case 1: mensaje+="4.096"; break;
  335. case 2: mensaje+="2.048"; break;
  336. case 3: mensaje+="1.024"; break;
  337. case 4: mensaje+="0.512"; break;
  338. case 5: mensaje+="0.256"; break;
  339. case 6: mensaje+="0.256"; break;
  340. case 7: mensaje+="0.256"; break;
  341. }
  342. mensaje+=" ";
  343. switch(configRegister.bits.operatingMode){
  344. case 0: mensaje+="CONT."; break;
  345. case 1: mensaje+="SSHOT"; break;
  346. }
  347. mensaje+=" ";
  348. switch(configRegister.bits.rate){
  349. case 0: mensaje+="8 SPS"; break;
  350. case 1: mensaje+="16SPS"; break;
  351. case 2: mensaje+="32SPS"; break;
  352. case 3: mensaje+="64SPS"; break;
  353. case 4: mensaje+="128SP"; break;
  354. case 5: mensaje+="250SP"; break;
  355. case 6: mensaje+="475SP"; break;
  356. case 7: mensaje+="860SP"; break;
  357. }
  358. mensaje+=" ";
  359. switch(configRegister.bits.sensorMode){
  360. case 0: mensaje+="ADC_M"; break;
  361. case 1: mensaje+="TMP_M"; break;
  362. }
  363. mensaje+=" ";
  364. switch(configRegister.bits.pullUp){
  365. case 0: mensaje+="DISAB"; break;
  366. case 1: mensaje+="ENABL"; break;
  367. }
  368. mensaje+=" ";
  369. switch(configRegister.bits.noOperation){
  370. case 0: mensaje+="INVAL"; break;
  371. case 1: mensaje+="VALID"; break;
  372. case 2: mensaje+="INVAL"; break;
  373. case 3: mensaje+="INVAL"; break;
  374. }
  375. mensaje+=" ";
  376. switch(configRegister.bits.reserved){
  377. case 0: mensaje+="RSRV0"; break;
  378. case 1: mensaje+="RSRV1"; break;
  379. }
  380. Serial.println("\nSTART MXSEL PGASL MODES RATES ADTMP PLLUP NOOPE RESER");
  381. Serial.println(mensaje);
  382. }