Adafruit_NAU7802/Adafruit_NAU7802.cpp
2025-06-04 16:40:50 -04:00

356 lines
12 KiB
C++

/**************************************************************************/
/*!
@file Adafruit_NAU7802.cpp
@mainpage Adafruit NAU7802 I2C 24-bit ADC driver
@section intro Introduction
This is a library for the Adafruit NAU7802 I2C ADC breakout board
----> http://www.adafruit.com/products/4538
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
@section author Author
Limor Fied (Adafruit Industries)
@section license License
BSD (see license.txt)
*/
/**************************************************************************/
#include "Adafruit_NAU7802.h"
/**************************************************************************/
/*!
@brief Instantiates a new NAU7802 class
*/
/**************************************************************************/
Adafruit_NAU7802::Adafruit_NAU7802() {}
/**************************************************************************/
/*!
@brief Sets up the I2C connection and tests that the sensor was found.
@param theWire Pointer to an I2C device we'll use to communicate
default is Wire
@return true if sensor was found, otherwise false.
*/
/**************************************************************************/
bool Adafruit_NAU7802::begin(TwoWire *theWire) {
if (i2c_dev) {
delete i2c_dev;
}
i2c_dev = new Adafruit_I2CDevice(NAU7802_I2CADDR_DEFAULT, theWire);
/* Try to instantiate the I2C device. */
if (!i2c_dev->begin()) {
return false;
}
// define the main power control register
_pu_ctrl_reg = new Adafruit_I2CRegister(i2c_dev, NAU7802_PU_CTRL);
if (!reset())
return false;
if (!enable(true))
return false;
/* Check for NAU7802 revision register (0x1F), low nibble should be 0xF. */
Adafruit_I2CRegister rev_reg =
Adafruit_I2CRegister(i2c_dev, NAU7802_REVISION_ID);
if ((rev_reg.read() & 0xF) != 0xF) {
return false;
}
if (!setLDO(NAU7802_3V0))
return false;
if (!setGain(NAU7802_GAIN_128))
return false;
if (!setRate(NAU7802_RATE_10SPS))
return false;
// disable ADC chopper clock
Adafruit_I2CRegister adc_reg = Adafruit_I2CRegister(i2c_dev, NAU7802_ADC);
Adafruit_I2CRegisterBits chop =
Adafruit_I2CRegisterBits(&adc_reg, 2, 4); // # bits, bit_shift
if (!chop.write(0x3))
return false;
// use low ESR caps
Adafruit_I2CRegister pga_reg = Adafruit_I2CRegister(i2c_dev, NAU7802_PGA);
Adafruit_I2CRegisterBits ldomode =
Adafruit_I2CRegisterBits(&pga_reg, 1, 6); // # bits, bit_shift
if (!ldomode.write(0))
return false;
// PGA stabilizer cap on output
Adafruit_I2CRegister pwr_reg = Adafruit_I2CRegister(i2c_dev, NAU7802_POWER);
Adafruit_I2CRegisterBits capen =
Adafruit_I2CRegisterBits(&pwr_reg, 1, 7); // # bits, bit_shift
if (!capen.write(1))
return false;
return true;
}
/**************************************************************************/
/*!
@brief Whether to have the sensor enabled and working or in power down mode
@param flag True to be in powered mode, False for power down mode
@return False if something went wrong with I2C comms
*/
/**************************************************************************/
bool Adafruit_NAU7802::enable(bool flag) {
Adafruit_I2CRegisterBits pu_analog =
Adafruit_I2CRegisterBits(_pu_ctrl_reg, 1, 2); // # bits, bit_shift
Adafruit_I2CRegisterBits pu_digital =
Adafruit_I2CRegisterBits(_pu_ctrl_reg, 1, 1); // # bits, bit_shift
Adafruit_I2CRegisterBits pu_ready =
Adafruit_I2CRegisterBits(_pu_ctrl_reg, 1, 3); // # bits, bit_shift
Adafruit_I2CRegisterBits pu_start =
Adafruit_I2CRegisterBits(_pu_ctrl_reg, 1, 4); // # bits, bit_shift
if (!flag) {
// shut down;
if (!pu_analog.write(0))
return false;
if (!pu_digital.write(0))
return false;
return true;
}
// turn on!
if (!pu_digital.write(1))
return false;
if (!pu_analog.write(1))
return false;
// RDY: Analog part wakeup stable plus Data Ready after exiting power-down
// mode 600ms
delay(600);
if (!pu_start.write(1))
return false;
return pu_ready.read();
}
/**************************************************************************/
/*!
@brief Whether there is new ADC data to read
@return True when there's new data available
*/
/**************************************************************************/
bool Adafruit_NAU7802::available(void) {
Adafruit_I2CRegisterBits conv_ready =
Adafruit_I2CRegisterBits(_pu_ctrl_reg, 1, 5); // # bits, bit_shift
return conv_ready.read();
}
/**************************************************************************/
/*!
@brief Set which channel for ADC
@param channel Set to 0 for CH1, 1 for CH2
@returns False if any I2C error occured
*/
/**************************************************************************/
bool Adafruit_NAU7802::setChannel(uint8_t channel) {
if (channel > 1)
channel = 1;
Adafruit_I2CRegister ctrl2_reg = Adafruit_I2CRegister(i2c_dev, NAU7802_CTRL2);
Adafruit_I2CRegisterBits ch_select =
Adafruit_I2CRegisterBits(&ctrl2_reg, 1, 7); // # bits, bit_shift
return ch_select.write(channel);
}
/**************************************************************************/
/*!
@brief Read the stored 24-bit ADC output value.
@return Signed integer with ADC output result, extended to a int32_t
*/
/**************************************************************************/
int32_t Adafruit_NAU7802::read(void) {
Adafruit_I2CRegister adc0 =
Adafruit_I2CRegister(i2c_dev, NAU7802_ADCO_B2, 3, MSBFIRST);
uint32_t val = adc0.read();
// extend sign bit
if (val & 0x800000) {
val |= 0xFF000000;
}
return val;
}
/**************************************************************************/
/*!
@brief Perform a soft reset
@return False if there was any I2C comms error
*/
/**************************************************************************/
bool Adafruit_NAU7802::reset(void) {
Adafruit_I2CRegisterBits reg_reset =
Adafruit_I2CRegisterBits(_pu_ctrl_reg, 1, 0); // # bits, bit_shift
Adafruit_I2CRegisterBits pu_digital =
Adafruit_I2CRegisterBits(_pu_ctrl_reg, 1, 1); // # bits, bit_shift
Adafruit_I2CRegisterBits pu_ready =
Adafruit_I2CRegisterBits(_pu_ctrl_reg, 1, 3); // # bits, bit_shift
// Set the RR bit to 1 in R0x00, to guarantee a reset of all register values.
if (!reg_reset.write(1))
return false;
delay(10);
// Set the RR bit to 0 and PUD bit 1, in R0x00, to enter normal operation
if (!reg_reset.write(0))
return false;
if (!pu_digital.write(1))
return false;
// After about 200 microseconds, the PWRUP bit will be Logic=1 indicating the
// device is ready for the remaining programming setup.
delay(1);
return pu_ready.read();
}
/**************************************************************************/
/*!
@brief The desired LDO voltage setter
@param voltage The LDO setting: NAU7802_4V5, NAU7802_4V2, NAU7802_3V9,
NAU7802_3V6, NAU7802_3V3, NAU7802_3V0, NAU7802_2V7, NAU7802_2V4, or
NAU7802_EXTERNAL if we are not using the internal LDO
@return False if there was any I2C comms error
*/
/**************************************************************************/
bool Adafruit_NAU7802::setLDO(NAU7802_LDOVoltage voltage) {
Adafruit_I2CRegisterBits reg_avdds =
Adafruit_I2CRegisterBits(_pu_ctrl_reg, 1, 7); // # bits, bit_shift
Adafruit_I2CRegister ctrl1_reg = Adafruit_I2CRegister(i2c_dev, NAU7802_CTRL1);
Adafruit_I2CRegisterBits vldo =
Adafruit_I2CRegisterBits(&ctrl1_reg, 3, 3); // # bits, bit_shift
if (voltage == NAU7802_EXTERNAL) {
// special case!
return reg_avdds.write(0);
}
// internal LDO
if (!reg_avdds.write(1))
return false;
return vldo.write(voltage);
}
/**************************************************************************/
/*!
@brief The desired LDO voltage getter
@returns The voltage setting: NAU7802_4V5, NAU7802_4V2, NAU7802_3V9,
NAU7802_3V6, NAU7802_3V3, NAU7802_3V0, NAU7802_2V7, NAU7802_2V4, or
NAU7802_EXTERNAL if we are not using the internal LDO
*/
/**************************************************************************/
NAU7802_LDOVoltage Adafruit_NAU7802::getLDO(void) {
Adafruit_I2CRegisterBits reg_avdds =
Adafruit_I2CRegisterBits(_pu_ctrl_reg, 1, 7); // # bits, bit_shift
Adafruit_I2CRegister ctrl1_reg = Adafruit_I2CRegister(i2c_dev, NAU7802_CTRL1);
Adafruit_I2CRegisterBits vldo =
Adafruit_I2CRegisterBits(&ctrl1_reg, 3, 3); // # bits, bit_shift
if (!reg_avdds.read()) {
return NAU7802_EXTERNAL;
}
// internal LDO
return (NAU7802_LDOVoltage)vldo.read();
}
/**************************************************************************/
/*!
@brief The desired ADC gain setter
@param gain Desired gain: NAU7802_GAIN_1, NAU7802_GAIN_2, NAU7802_GAIN_4,
NAU7802_GAIN_8, NAU7802_GAIN_16, NAU7802_GAIN_32, NAU7802_GAIN_64,
or NAU7802_GAIN_128
@returns False if there was any error during I2C comms
*/
/**************************************************************************/
bool Adafruit_NAU7802::setGain(NAU7802_Gain gain) {
Adafruit_I2CRegister ctrl1_reg = Adafruit_I2CRegister(i2c_dev, NAU7802_CTRL1);
Adafruit_I2CRegisterBits gain_select =
Adafruit_I2CRegisterBits(&ctrl1_reg, 3, 0); // # bits, bit_shift
return gain_select.write(gain);
}
/**************************************************************************/
/*!
@brief The desired ADC gain getter
@returns The gain: NAU7802_GAIN_1, NAU7802_GAIN_2, NAU7802_GAIN_4,
NAU7802_GAIN_8, NAU7802_GAIN_16, NAU7802_GAIN_32, NAU7802_GAIN_64,
or NAU7802_GAIN_128
*/
/**************************************************************************/
NAU7802_Gain Adafruit_NAU7802::getGain(void) {
Adafruit_I2CRegister ctrl1_reg = Adafruit_I2CRegister(i2c_dev, NAU7802_CTRL1);
Adafruit_I2CRegisterBits gain_select =
Adafruit_I2CRegisterBits(&ctrl1_reg, 3, 0); // # bits, bit_shift
return (NAU7802_Gain)gain_select.read();
}
/**************************************************************************/
/*!
@brief The desired conversion rate setter
@param rate The desired rate: NAU7802_RATE_10SPS, NAU7802_RATE_20SPS,
NAU7802_RATE_40SPS, NAU7802_RATE_80SPS, or NAU7802_RATE_320SPS
@returns False if any I2C error occured
*/
/**************************************************************************/
bool Adafruit_NAU7802::setRate(NAU7802_SampleRate rate) {
Adafruit_I2CRegister ctrl2_reg = Adafruit_I2CRegister(i2c_dev, NAU7802_CTRL2);
Adafruit_I2CRegisterBits rate_select =
Adafruit_I2CRegisterBits(&ctrl2_reg, 3, 4); // # bits, bit_shift
return rate_select.write(rate);
}
/**************************************************************************/
/*!
@brief The desired conversion rate getter
@returns The rate: NAU7802_RATE_10SPS, NAU7802_RATE_20SPS,
NAU7802_RATE_40SPS, NAU7802_RATE_80SPS, or NAU7802_RATE_320SPS
*/
/**************************************************************************/
NAU7802_SampleRate Adafruit_NAU7802::getRate(void) {
Adafruit_I2CRegister ctrl2_reg = Adafruit_I2CRegister(i2c_dev, NAU7802_CTRL2);
Adafruit_I2CRegisterBits rate_select =
Adafruit_I2CRegisterBits(&ctrl2_reg, 3, 4); // # bits, bit_shift
return (NAU7802_SampleRate)rate_select.read();
}
/**************************************************************************/
/*!
@brief Perform the internal calibration procedure
@param mode The calibration mode to perform: NAU7802_CALMOD_INTERNAL,
NAU7802_CALMOD_OFFSET or NAU7802_CALMOD_GAIN
@returns True on calibrations success
*/
/**************************************************************************/
bool Adafruit_NAU7802::calibrate(NAU7802_Calibration mode) {
Adafruit_I2CRegister ctrl2_reg = Adafruit_I2CRegister(i2c_dev, NAU7802_CTRL2);
Adafruit_I2CRegisterBits cal_start =
Adafruit_I2CRegisterBits(&ctrl2_reg, 1, 2); // # bits, bit_shift
Adafruit_I2CRegisterBits cal_err =
Adafruit_I2CRegisterBits(&ctrl2_reg, 1, 3); // # bits, bit_shift
Adafruit_I2CRegisterBits cal_mod =
Adafruit_I2CRegisterBits(&ctrl2_reg, 2, 0); // # bits, bit_shift
if (!cal_mod.write(mode))
return false;
if (!cal_start.write(true))
return false;
while (!cal_start.read()) {
delay(10);
}
return !cal_err.read();
}