TLA2528 I2C ADC
The Tla2528 class implements support for the Texas Instruments TLA2528 12-bit 8-channel ADC. The TLA2528 is a 12-bit, 8-channel, low-power, successive approximation register (SAR) analog-to-digital converter (ADC) which can configure any of its 8 channels as single-ended analog inputs, digital inputs, or digital outputs. It has an operating mode that allows the user to configure the device for a single conversion, or to automatically convert on a sequenced basis.
API Reference
Header File
Classes
-
class Tla2528 : public espp::BasePeripheral<>
Class for reading values from the TLA2528 family of ADC chips.
The TLA2528 is a 16-bit, 8-channel ADC with 8 digital I/O pins. It supports a variety of sampling modes, including manual sampling, and auto sequence sampling. It also supports oversampling ratios of 2, 4, 8, 16, 32, 64, and 128. It additionally allows the user to configure the analog or digital inputs to trigger an alert when the value goes above or below a threshold (enter or leave a region of voltage).
TLA2528 Example
// make the I2C that we'll use to communicate espp::I2c i2c({ .port = I2C_NUM_0, .sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO, .scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO, }); static std::vector<espp::Tla2528::Channel> channels = { espp::Tla2528::Channel::CH0, espp::Tla2528::Channel::CH1, espp::Tla2528::Channel::CH2, espp::Tla2528::Channel::CH3, espp::Tla2528::Channel::CH4, espp::Tla2528::Channel::CH5, espp::Tla2528::Channel::CH6, espp::Tla2528::Channel::CH7}; // make the actual tla class espp::Tla2528 tla(espp::Tla2528::Config{ // Address pin is connected via 11k to ADC_DECAP, so the default address // of 0x10 becomes 0x16 .device_address = espp::Tla2528::DEFAULT_ADDRESS | 0x06, .mode = espp::Tla2528::Mode::AUTO_SEQ, .analog_inputs = channels, .digital_inputs = {}, .digital_outputs = {}, // enable oversampling / averaging .oversampling_ratio = espp::Tla2528::OversamplingRatio::NONE, .write = std::bind(&espp::I2c::write, &i2c, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3), .read = std::bind(&espp::I2c::read, &i2c, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3), .log_level = espp::Logger::Verbosity::WARN, }); // make the task which will get the raw data from the I2C ADC fmt::print("%time (s), ntc (mV), x (mV), y (mV)\n"); auto tla_read_task_fn = [&tla](std::mutex &m, std::condition_variable &cv) { static auto start = std::chrono::high_resolution_clock::now(); auto now = std::chrono::high_resolution_clock::now(); auto elapsed = std::chrono::duration<float>(now - start).count(); // get the analog input data individually; NOTE: this only works if you have configured the // TLA2528 to use MANUAL mode // auto ch0_mv = tla.get_mv(channels[0]); // auto ch1_mv = tla.get_mv(channels[1]); // auto ch2_mv = tla.get_mv(channels[2]); // Could also read them all at once; NOTE: this only works if you have configured the // TLA2528 to use AUTO_SEQ mode (which is more efficient) // auto all_mv = tla.get_all_mv(); // auto ch0_mv = all_mv[0]; // auto ch1_mv = all_mv[1]; // auto ch2_mv = all_mv[2]; // Could also use the mapped version; NOTE: this only works if you have configured the // TLA2528 to use AUTO_SEQ mode (which is more efficient) std::error_code ec; auto all_mv_map = tla.get_all_mv_map(ec); if (ec) { logger.error("error reading TLA2528: {}", ec.message()); return false; } // use fmt to print so it doesn't have the prefix and can be used more // easily as CSV (for plotting using uart_serial_plotter) fmt::print("{:.3f}", elapsed); for (auto &[ch, mv] : all_mv_map) { fmt::print(", {:.1f}", mv); } fmt::print("\n"); // NOTE: sleeping in this way allows the sleep to exit early when the // task is being stopped / destroyed { using namespace std::chrono_literals; std::unique_lock<std::mutex> lk(m); cv.wait_until(lk, now + 10ms); } // we don't want to stop, so return false return false; }; auto tla_task = espp::Task::make_unique({.callback = tla_read_task_fn, .task_config = { .name = "TLA", .stack_size_bytes{8 * 1024}, }, .log_level = espp::Logger::Verbosity::INFO}); tla_task->start();
Public Types
-
enum class OversamplingRatio : uint8_t
Possible oversampling ratios, see data sheet Table 15 (p. 34)
Values:
-
enumerator NONE
No oversampling.
-
enumerator OSR_2
2x oversampling
-
enumerator OSR_4
4x oversampling
-
enumerator OSR_8
8x oversampling
-
enumerator OSR_16
16x oversampling
-
enumerator OSR_32
32x oversampling
-
enumerator OSR_64
64x oversampling
-
enumerator OSR_128
128x oversampling
-
enumerator NONE
-
enum class Channel : uint8_t
Possible channel numbers.
The TLA2528 has 8 channels, see data sheet Table 1 (p. 4)
Note
The channel numbers are 0-indexed.
Note
The channel may be configured as digital input, digital output, or analog input.
Values:
-
enumerator CH0
Channel 0.
-
enumerator CH1
Channel 1.
-
enumerator CH2
Channel 2.
-
enumerator CH3
Channel 3.
-
enumerator CH4
Channel 4.
-
enumerator CH5
Channel 5.
-
enumerator CH6
Channel 6.
-
enumerator CH7
Channel 7.
-
enumerator CH0
-
enum class Mode : uint8_t
Possible modes for analog input conversion.
The ADS7128 device has the following sampling modes:
Manual Mode: Allows the external host processor to directly request and control when the data are sampled. The host provides I2C frames to control conversions and the captured data are returned overthe I2C bus after each conversion.
Auto-Sequence Mode: The host can configure the device to scan through the enabled analog input channels. The host must provide continuous clocks (SCL) to the device to scan through the channels and to read the data from the device. The mux automatically switches through the predetermined channel sequence, and the data conversion results are sent through the data bus.
Values:
-
enumerator MANUAL
Manual mode (9th falling edge of SCL (ACK) triggers conversion) and the MUX is controlled by register write to MANUAL_CHID field of the CHANNEL_SEL register.
-
enumerator AUTO_SEQ
Auto sequence mode (9th falling edge of SCL (ACK) triggers conversion) and the MUX is incremented after each conversion.
-
enum class OutputMode : uint8_t
Output mode for digital output channels and ALERT pin.
Values:
-
enumerator OPEN_DRAIN
Open drain output mode.
-
enumerator PUSH_PULL
Push-pull output mode.
-
enumerator OPEN_DRAIN
-
enum class DataFormat : uint8_t
Enum for the data format that can be read from the ADC.
Values:
-
enumerator RAW
Raw data format, 12 bit ADC data.
-
enumerator AVERAGED
Averaged data format, 16 bit ADC data.
-
enumerator RAW
-
enum class Append : uint8_t
Enum for the different configurations of bits that can be appended to the data when reading from the ADC.
Values:
-
enumerator NONE
No append.
-
enumerator CHANNEL_ID
Append Channel ID.
-
enumerator NONE
-
enum class AlertLogic : uint8_t
Alert logic for ALERT pin.
Values:
-
enumerator ACTIVE_LOW
ALERT pin is active low.
-
enumerator ACTIVE_HIGH
ALERT pin is active high.
-
enumerator PULSED_LOW
ALERT pin is pulsed low per alert flag.
-
enumerator PULSED_HIGH
ALERT pin is pulsed high per alert flag.
-
enumerator ACTIVE_LOW
-
typedef std::function<bool(uint8_t)> probe_fn
Function to probe the peripheral
- Param address
The address to probe
- Return
True if the peripheral is found at the given address
Public Functions
-
inline explicit Tla2528(const Config &config)
Construct Tla2528.
- Parameters
config – Configuration structure.
-
inline void initialize(std::error_code &ec)
Initialize the ADC This function uses the configuration structure passed to the constructor to configure the ADC.
Note
This function must be called before any other functions as it configures the ADC pins and sets the mode.
- Parameters
ec – Error code to set if an error occurs.
-
inline float get_mv(Channel channel, std::error_code &ec)
Communicate with the ADC to get the analog value for the channel and return it.
Note
The channel must have been configured as an analog input.
Note
If the ADC is in autonomous mode, this function will simply read the value from the ADC’s buffer. If the ADC is in manual mode, this function will trigger a conversion and then read the value from the ADC’s buffer (blocking until conversion is complete).
Note
This function will return 0 and log an error if the channel is not configured as an analog input.
- Parameters
channel – Which channel of the ADC to read
ec – Error code to set if an error occurs.
- Returns
The voltage (in mV) read from the channel.
-
inline std::vector<float> get_all_mv(std::error_code &ec)
Communicate with the ADC to get the analog value for all channels and return them.
Note
The channels must have been configured as analog inputs.
Note
The vector will be in the order of the channels configured in the constructor.
Note
The vector will be the same length as the number of channels configured in the constructor.
Note
If the ADC is in autonomous mode, this function will simply read the values from the ADC’s buffer. If the ADC is in manual mode, this function will trigger a conversion and then read the values from the ADC’s buffer (blocking until conversion is complete).
- Parameters
ec – Error code to set if an error occurs.
- Returns
A vector of the voltages (in mV) read from each channel.
-
inline std::unordered_map<Channel, float> get_all_mv_map(std::error_code &ec)
Communicate with the ADC to get the analog value for all channels and return them.
Note
These are the channels that were configured as analog inputs.
Note
If the ADC is in autonomous mode, this function will simply read the values from the ADC’s buffer. If the ADC is in manual mode, this function will trigger a conversion and then read the values from the ADC’s buffer (blocking until conversion is complete).
- Parameters
ec – Error code to set if an error occurs.
- Returns
An unordered map of the voltages (in mV) read from each channel.
-
inline void set_digital_output_mode(Channel channel, OutputMode output_mode, std::error_code &ec)
Configure the digital output mode for the given channel.
Note
The channel must have been configured as a digital output.
- Parameters
channel – Channel to configure
output_mode – Output mode for the channel
ec – Error code to set if an error occurs.
-
inline void set_digital_output_value(Channel channel, bool value, std::error_code &ec)
Set the digital output value for the given channel.
Note
The channel must have been configured as a digital output.
- Parameters
channel – Which channel to set the digital output value for.
value – The value to set the digital output to.
ec – Error code to set if an error occurs.
-
inline bool get_digital_input_value(Channel channel, std::error_code &ec)
Get the digital input value for the given channel.
Note
The channel must have been configured as a digital input.
- Parameters
channel – Which channel to get the digital input value for.
ec – Error code to set if an error occurs.
- Returns
The value of the digital input.
-
inline uint8_t get_digital_input_values(std::error_code &ec)
Get the digital input values for all channels.
Note
The returned value is a bitfield, with each bit corresponding to a channel. The LSB corresponds to channel 0, the MSB to channel 7.
Note
Only channels configured as digital inputs are returned.
- Parameters
ec – Error code to set if an error occurs.
- Returns
The values of the digital inputs.
-
inline void reset(std::error_code &ec)
Perform a software reset of the device.
Note
This will reset all registers to their default values (converting all channels to analog inputs and disabling all events).
- Parameters
ec – Error code to set if an error occurs.
- inline bool probe (std::error_code &ec) requires(UseAddress)
Probe the peripheral
Note
This function is thread safe
Note
If the probe function is not set, this function will return false and set the error code to operation_not_supported
Note
This function is only available if UseAddress is true
- Parameters
ec – The error code to set if there is an error
- Returns
True if the peripheral is found
- inline void set_address (uint8_t address) requires(UseAddress)
Set the address of the peripheral
Note
This function is thread safe
Note
This function is only available if UseAddress is true
- Parameters
address – The address of the peripheral
- inline void set_probe (const probe_fn &probe) requires(UseAddress)
Set the probe function
Note
This function is thread safe
Note
This should rarely be used, as the probe function is usually set in the constructor. If you need to change the probe function, consider using the set_config function instead.
Note
This function is only available if UseAddress is true
- Parameters
probe – The probe function
-
inline void set_write(const write_fn &write)
Set the write function
Note
This function is thread safe
Note
This should rarely be used, as the write function is usually set in the constructor. If you need to change the write function, consider using the set_config function instead.
- Parameters
write – The write function
-
inline void set_read(const read_fn &read)
Set the read function
Note
This function is thread safe
Note
This should rarely be used, as the read function is usually set in the constructor. If you need to change the read function, consider using the set_config function instead.
- Parameters
read – The read function
-
inline void set_read_register(const read_register_fn &read_register)
Set the read register function
Note
This function is thread safe
Note
This should rarely be used, as the read register function is usually set in the constructor. If you need to change the read register function, consider using the set_config function instead.
- Parameters
read_register – The read register function
-
inline void set_write_then_read(const write_then_read_fn &write_then_read)
Set the write then read function
Note
This function is thread safe
Note
This should rarely be used, as the write then read function is usually set in the constructor. If you need to change the write then
- Parameters
write_then_read – The write then read function
-
inline void set_separate_write_then_read_delay(const std::chrono::milliseconds &delay)
Set the delay between the write and read operations in write_then_read
Note
This function is thread safe
Note
This should rarely be used, as the delay is usually set in the constructor. If you need to change the delay, consider using the set_config function instead.
Note
This delay is only used if the write_then_read function is not set to a custom function and the write and read functions are separate functions.
- Parameters
delay – The delay between the write and read operations in write_then_read
-
inline void set_config(const Config &config)
Set the configuration for the peripheral
Note
This function is thread safe
Note
The configuration should normally be set in the constructor, but this function can be used to change the configuration after the peripheral has been created - for instance if the peripheral could be found on different communications buses.
- Parameters
config – The configuration for the peripheral
-
inline void set_config(Config &&config)
Set the configuration for the peripheral
Note
This function is thread safe
Note
The configuration should normally be set in the constructor, but this function can be used to change the configuration after the peripheral has been created - for instance if the peripheral could be found on different communications buses.
- Parameters
config – The configuration for the peripheral
-
inline const std::string &get_name() const
Get the name of the component
Note
This is the tag of the logger
- Returns
A const reference to the name of the component
-
inline void set_log_tag(const std::string_view &tag)
Set the tag for the logger
- Parameters
tag – The tag to use for the logger
-
inline espp::Logger::Verbosity get_log_level() const
Get the log level for the logger
See also
See also
- Returns
The verbosity level of the logger
-
inline void set_log_level(espp::Logger::Verbosity level)
Set the log level for the logger
See also
See also
- Parameters
level – The verbosity level to use for the logger
-
inline void set_log_verbosity(espp::Logger::Verbosity level)
Set the log verbosity for the logger
See also
See also
See also
Note
This is a convenience method that calls set_log_level
- Parameters
level – The verbosity level to use for the logger
-
inline espp::Logger::Verbosity get_log_verbosity() const
Get the log verbosity for the logger
See also
See also
See also
Note
This is a convenience method that calls get_log_level
- Returns
The verbosity level of the logger
-
inline void set_log_rate_limit(std::chrono::duration<float> rate_limit)
Set the rate limit for the logger
See also
Note
Only calls to the logger that have _rate_limit suffix will be rate limited
- Parameters
rate_limit – The rate limit to use for the logger
Public Static Attributes
-
static constexpr uint8_t DEFAULT_ADDRESS = (0x10)
Default I2C address of the device (when both R1 and R2 are DNP) (see data sheet Table 2, p. 16)
-
struct Config
Configuration structure.
Public Members
-
uint8_t device_address = DEFAULT_ADDRESS
I2C address of the device.
-
float avdd_volts = 3.3f
AVDD voltage in Volts. Used for calculating analog input voltage.
-
std::unordered_map<Channel, OutputMode> digital_output_modes = {}
Optional output mode for digital output channels. If not specified, the default value is open-drain.
-
std::unordered_map<Channel, bool> digital_output_values = {}
Optional initial values for digital output channels. If not specified, the default value is false in open-drain mode.
-
OversamplingRatio oversampling_ratio = OversamplingRatio::NONE
Oversampling ratio to use.
-
BasePeripheral::write_fn write
Function to write to the ADC.
-
BasePeripheral::read_fn read
Function to read from the ADC.
-
bool auto_init = true
Automatically initialize the ADC on construction. If false, initialize() must be called before any other functions.
-
uint8_t device_address = DEFAULT_ADDRESS
-
enum class OversamplingRatio : uint8_t