/***************************************** * This is a library for the ADS1115 A/D Converter * * You'll find an example which should enable you to use the library. * * You are free to use it, change it or build on it. In case you like * it, it would be cool if you give it a star. * * If you find bugs, please inform me! * * Written by Wolfgang (Wolle) Ewald * https://wolles-elektronikkiste.de/en/ads1115-a-d-converter-with-amplifier (English) * https://wolles-elektronikkiste.de/ads1115 (German) * *******************************************/ #include "ADS1115_WE.h" ADS1115_WE::ADS1115_WE(int addr){ _wire = &Wire; i2cAddress = addr; } ADS1115_WE::ADS1115_WE(){ _wire = &Wire; i2cAddress = 0x48; } ADS1115_WE::ADS1115_WE(TwoWire *w, int addr){ _wire = w; i2cAddress = addr; } ADS1115_WE::ADS1115_WE(TwoWire *w){ _wire = w; i2cAddress = 0x48; } void ADS1115_WE::reset(){ _wire->beginTransmission(0); _wire->write(0x06); _wire->endTransmission(); } bool ADS1115_WE::init(){ _wire->beginTransmission(i2cAddress); uint8_t success = _wire->endTransmission(); if(success){ return 0; } writeRegister(ADS1115_CONFIG_REG, ADS1115_REG_RESET_VAL); setVoltageRange_mV(ADS1115_RANGE_2048); writeRegister(ADS1115_LO_THRESH_REG, 0x8000); writeRegister(ADS1115_HI_THRESH_REG, 0x7FFF); deviceMeasureMode = ADS1115_SINGLE; autoRangeMode = false; return 1; } void ADS1115_WE::setAlertPinMode(ADS1115_COMP_QUE mode){ uint16_t currentConfReg = readRegister(ADS1115_CONFIG_REG); currentConfReg &= ~(0x0003); currentConfReg |= mode; writeRegister(ADS1115_CONFIG_REG, currentConfReg); } void ADS1115_WE::setAlertLatch(ADS1115_LATCH latch){ uint16_t currentConfReg = readRegister(ADS1115_CONFIG_REG); currentConfReg &= ~(0x0004); currentConfReg |= latch; writeRegister(ADS1115_CONFIG_REG, currentConfReg); } void ADS1115_WE::setAlertPol(ADS1115_ALERT_POL polarity){ uint16_t currentConfReg = readRegister(ADS1115_CONFIG_REG); currentConfReg &= ~(0x0008); currentConfReg |= polarity; writeRegister(ADS1115_CONFIG_REG, currentConfReg); } void ADS1115_WE::setAlertModeAndLimit_V(ADS1115_COMP_MODE mode, float hiThres, float loThres){ uint16_t currentConfReg = readRegister(ADS1115_CONFIG_REG); currentConfReg &= ~(0x0010); currentConfReg |= mode; writeRegister(ADS1115_CONFIG_REG, currentConfReg); int16_t alertLimit = calcLimit(hiThres); writeRegister(ADS1115_HI_THRESH_REG, alertLimit); alertLimit = calcLimit(loThres); writeRegister(ADS1115_LO_THRESH_REG, alertLimit); } void ADS1115_WE::setConvRate(ADS1115_CONV_RATE rate){ uint16_t currentConfReg = readRegister(ADS1115_CONFIG_REG); currentConfReg &= ~(0x00E0); currentConfReg |= rate; writeRegister(ADS1115_CONFIG_REG, currentConfReg); } convRate ADS1115_WE::getConvRate(){ uint16_t currentConfReg = readRegister(ADS1115_CONFIG_REG); return (convRate)(currentConfReg & 0xE0); } void ADS1115_WE::setMeasureMode(ADS1115_MEASURE_MODE mode){ uint16_t currentConfReg = readRegister(ADS1115_CONFIG_REG); deviceMeasureMode = mode; currentConfReg &= ~(0x0100); currentConfReg |= mode; writeRegister(ADS1115_CONFIG_REG, currentConfReg); } void ADS1115_WE::setVoltageRange_mV(ADS1115_RANGE range){ uint16_t currentVoltageRange = voltageRange; uint16_t currentConfReg = readRegister(ADS1115_CONFIG_REG); uint16_t currentRange = (currentConfReg >> 9) & 7; uint16_t currentAlertPinMode = currentConfReg & 3; setMeasureMode(ADS1115_SINGLE); switch(range){ case ADS1115_RANGE_6144: voltageRange = 6144; break; case ADS1115_RANGE_4096: voltageRange = 4096; break; case ADS1115_RANGE_2048: voltageRange = 2048; break; case ADS1115_RANGE_1024: voltageRange = 1024; break; case ADS1115_RANGE_0512: voltageRange = 512; break; case ADS1115_RANGE_0256: voltageRange = 256; break; } if ((currentRange != range) && (currentAlertPinMode != ADS1115_DISABLE_ALERT)){ int16_t alertLimit = readRegister(ADS1115_HI_THRESH_REG); alertLimit = alertLimit * (currentVoltageRange * 1.0 / voltageRange); writeRegister(ADS1115_HI_THRESH_REG, alertLimit); alertLimit = readRegister(ADS1115_LO_THRESH_REG); alertLimit = alertLimit * (currentVoltageRange * 1.0 / voltageRange); writeRegister(ADS1115_LO_THRESH_REG, alertLimit); } currentConfReg &= ~(0x0E00); currentConfReg |= range; writeRegister(ADS1115_CONFIG_REG, currentConfReg); convRate rate = getConvRate(); delayAccToRate(rate); } void ADS1115_WE::setAutoRange(){ uint16_t currentConfReg = readRegister(ADS1115_CONFIG_REG); setVoltageRange_mV(ADS1115_RANGE_6144); if(deviceMeasureMode == ADS1115_SINGLE){ setMeasureMode(ADS1115_CONTINUOUS); convRate rate = getConvRate(); delayAccToRate(rate); } int16_t rawResult = abs(readRegister(ADS1115_CONV_REG)); range optRange = ADS1115_RANGE_6144; if(rawResult < 1093){ optRange = ADS1115_RANGE_0256; } else if(rawResult < 2185){ optRange = ADS1115_RANGE_0512; } else if(rawResult < 4370){ optRange = ADS1115_RANGE_1024; } else if(rawResult < 8738){ optRange = ADS1115_RANGE_2048; } else if(rawResult < 17476){ optRange = ADS1115_RANGE_4096; } writeRegister(ADS1115_CONFIG_REG, currentConfReg); setVoltageRange_mV(optRange); } void ADS1115_WE::setPermanentAutoRangeMode(bool autoMode){ if(autoMode){ autoRangeMode = true; } else{ autoRangeMode = false; } } void ADS1115_WE::delayAccToRate(convRate cr){ switch(cr){ case ADS1115_8_SPS: delay(130); break; case ADS1115_16_SPS: delay(65); break; case ADS1115_32_SPS: delay(32); break; case ADS1115_64_SPS: delay(16); break; case ADS1115_128_SPS: delay(8); break; case ADS1115_250_SPS: delay(4); break; case ADS1115_475_SPS: delay(3); break; case ADS1115_860_SPS: delay(2); break; } } void ADS1115_WE::setCompareChannels(ADS1115_MUX mux){ uint16_t currentConfReg = readRegister(ADS1115_CONFIG_REG); currentConfReg &= ~(0x7000); currentConfReg |= (mux); writeRegister(ADS1115_CONFIG_REG, currentConfReg); if(!(currentConfReg & 0x0100)){ // => if not single shot mode convRate rate = getConvRate(); delayAccToRate(rate); delayAccToRate(rate); } } void ADS1115_WE::setSingleChannel(size_t channel) { if (channel >= 4) return; setCompareChannels((ADS1115_MUX)(ADS1115_COMP_0_GND + ADS1115_COMP_INC*channel)); } bool ADS1115_WE::isBusy(){ uint16_t currentConfReg = readRegister(ADS1115_CONFIG_REG); return (!(currentConfReg>>15) & 1); } void ADS1115_WE::startSingleMeasurement(){ uint16_t currentConfReg = readRegister(ADS1115_CONFIG_REG); currentConfReg |= (1 << 15); writeRegister(ADS1115_CONFIG_REG, currentConfReg); } float ADS1115_WE::getResult_V(){ float result = getResult_mV(); result /= 1000; return result; } float ADS1115_WE::getResult_mV(){ int16_t rawResult = getRawResult(); float result = (rawResult * 1.0 / ADS1115_REG_FACTOR) * voltageRange; return result; } int16_t ADS1115_WE::getRawResult(){ int16_t rawResult = readRegister(ADS1115_CONV_REG); if(autoRangeMode){ if((abs(rawResult) > 26214) && (voltageRange != 6144)){ // 80% setAutoRange(); rawResult = readRegister(ADS1115_CONV_REG); } else if((abs(rawResult) < 9800) && (voltageRange != 256)){ //30% setAutoRange(); rawResult = readRegister(ADS1115_CONV_REG); } } return rawResult; } int16_t ADS1115_WE::getResultWithRange(int16_t min, int16_t max){ int16_t rawResult = getRawResult(); int16_t result = map(rawResult, -32767, 32767, min, max); return result; } int16_t ADS1115_WE::getResultWithRange(int16_t min, int16_t max, int16_t maxMillivolt){ int16_t result = getResultWithRange(min, max); result = (int16_t) ((1.0 * result * voltageRange / maxMillivolt) + 0.5); return result; } uint16_t ADS1115_WE::getVoltageRange_mV(){ return voltageRange; } void ADS1115_WE::setAlertPinToConversionReady(){ writeRegister(ADS1115_LO_THRESH_REG, (0<<15)); writeRegister(ADS1115_HI_THRESH_REG, (1<<15)); } void ADS1115_WE::clearAlert(){ readRegister(ADS1115_CONV_REG); } /************************************************ private functions *************************************************/ int16_t ADS1115_WE::calcLimit(float rawLimit){ int16_t limit = (int16_t)((rawLimit * ADS1115_REG_FACTOR / voltageRange)*1000); return limit; } uint8_t ADS1115_WE::writeRegister(uint8_t reg, uint16_t val){ _wire->beginTransmission(i2cAddress); uint8_t lVal = val & 255; uint8_t hVal = val >> 8; _wire->write(reg); _wire->write(hVal); _wire->write(lVal); return _wire->endTransmission(); } uint16_t ADS1115_WE::readRegister(uint8_t reg){ uint8_t MSByte = 0, LSByte = 0; uint16_t regValue = 0; _wire->beginTransmission(i2cAddress); _wire->write(reg); _wire->endTransmission(false); _wire->requestFrom(i2cAddress,2); if(_wire->available()){ MSByte = _wire->read(); LSByte = _wire->read(); } regValue = (MSByte<<8) + LSByte; return regValue; }