Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/base peripheral #150

Merged
merged 11 commits into from
Feb 12, 2024
2 changes: 1 addition & 1 deletion components/ads1x15/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
idf_component_register(
INCLUDE_DIRS "include"
SRC_DIRS "src"
REQUIRES "logger" "pthread"
REQUIRES "base_peripheral" "pthread"
)
9 changes: 5 additions & 4 deletions components/ads1x15/example/main/ads1x15_example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ extern "C" void app_main(void) {
// make the actual ads class
espp::Ads1x15 ads(espp::Ads1x15::Ads1015Config{
.device_address = espp::Ads1x15::DEFAULT_ADDRESS,
.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)});
.write = [&i2c](uint8_t addr, const uint8_t *data,
size_t len) { return i2c.write(addr, data, len); },
.read = [&i2c](uint8_t addr, uint8_t *data,
size_t len) { return i2c.read(addr, data, len); },
});
// make the task which will get the raw data from the I2C ADC
auto ads_read_task_fn = [&ads](std::mutex &m, std::condition_variable &cv) {
static auto start = std::chrono::high_resolution_clock::now();
Expand Down
83 changes: 18 additions & 65 deletions components/ads1x15/include/ads1x15.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@

#include <chrono>
#include <functional>
#include <mutex>
#include <thread>

#include "logger.hpp"
#include "base_peripheral.hpp"

namespace espp {
/**
Expand All @@ -14,28 +13,10 @@ namespace espp {
* \section ads1x15_ex1 ADS1X15 Example
* \snippet ads1x15_example.cpp ads1x15 example
*/
class Ads1x15 {
class Ads1x15 : public espp::BasePeripheral {
public:
static constexpr uint8_t DEFAULT_ADDRESS = (0x48); ///< I2C address of the ADS1x15 chips.

/**
* @brief Function to write bytes to the device.
* @param dev_addr Address of the device to write to.
* @param data Pointer to array of bytes to write.
* @param data_len Number of data bytes to write.
* @return True if the write was successful.
*/
typedef std::function<bool(uint8_t dev_addr, uint8_t *data, size_t data_len)> write_fn;

/**
* @brief Function to read bytes from the device.
* @param dev_addr Address of the device to write to.
* @param data Pointer to array of bytes to read into.
* @param data_len Number of data bytes to read.
* @return True if the read was successful.
*/
typedef std::function<bool(uint8_t dev_addr, uint8_t *data, size_t data_len)> read_fn;

/**
* @brief Gain values for the ADC conversion.
*/
Expand Down Expand Up @@ -80,8 +61,8 @@ class Ads1x15 {
*/
struct Ads1015Config {
uint8_t device_address = DEFAULT_ADDRESS; ///< I2C address of the device.
write_fn write; ///< Function to write to the ADC
read_fn read; ///< Function to read from the ADC
BasePeripheral::write_fn write; ///< Function to write to the ADC
BasePeripheral::read_fn read; ///< Function to read from the ADC
Gain gain{Gain::TWOTHIRDS}; ///< Gain for the ADC
Ads1015Rate sample_rate{Ads1015Rate::SPS1600}; ///< Sample rate for the ADC
espp::Logger::Verbosity log_level{espp::Logger::Verbosity::WARN}; ///< Verbosity for the logger.
Expand All @@ -92,8 +73,8 @@ class Ads1x15 {
*/
struct Ads1115Config {
uint8_t device_address = DEFAULT_ADDRESS; ///< I2C address of the device.
write_fn write; ///< Function to write to the ADC
read_fn read; ///< Function to read from the ADC
BasePeripheral::write_fn write; ///< Function to write to the ADC
BasePeripheral::read_fn read; ///< Function to read from the ADC
Gain gain{Gain::TWOTHIRDS}; ///< Gain for the ADC
Ads1115Rate sample_rate{Ads1115Rate::SPS128}; ///< Sample rate for the ADC
espp::Logger::Verbosity log_level{espp::Logger::Verbosity::WARN}; ///< Verbosity for the logger.
Expand All @@ -104,18 +85,24 @@ class Ads1x15 {
* @param config Configuration structure.
*/
explicit Ads1x15(const Ads1015Config &config)
: gain_(config.gain), ads1015rate_(config.sample_rate), bit_shift_(4),
address_(config.device_address), write_(config.write), read_(config.read),
logger_({.tag = "Ads1015", .level = config.log_level}) {}
: BasePeripheral(
{.address = config.device_address, .write = config.write, .read = config.read},
"Ads1015", config.log_level)
, gain_(config.gain)
, ads1015rate_(config.sample_rate)
, bit_shift_(4) {}

/**
* @brief Construct Ads1x15 specficially for ADS1115.
* @param config Configuration structure.
*/
explicit Ads1x15(const Ads1115Config &config)
: gain_(config.gain), ads1115rate_(config.sample_rate), bit_shift_(0),
address_(config.device_address), write_(config.write), read_(config.read),
logger_({.tag = "Ads1115", .level = config.log_level}) {}
: BasePeripheral(
{.address = config.device_address, .write = config.write, .read = config.read},
"Ads1115", config.log_level)
, gain_(config.gain)
, ads1115rate_(config.sample_rate)
, bit_shift_(0) {}

/**
* @brief Communicate with the ADC to sample the channel and return the
Expand Down Expand Up @@ -165,35 +152,6 @@ class Ads1x15 {
return raw * (fsRange / (32768 >> bit_shift_));
}

uint16_t read_two_(uint8_t reg_addr, std::error_code &ec) {
// lock the mutex so that we don't have multiple threads trying to read
// from the device at the same time
std::lock_guard<std::mutex> lock(mutex_);
// write the reg addr we want to read from
bool success = write_(address_, &reg_addr, 1);
if (!success) {
ec = std::make_error_code(std::errc::io_error);
return 0;
}
// then read the two bytes
uint8_t data[2];
success = read_(address_, data, 2);
if (!success) {
ec = std::make_error_code(std::errc::io_error);
return 0;
}
return (data[0] << 8) | data[1];
}

void write_two_(uint8_t reg_addr, uint16_t value, std::error_code &ec) {
uint8_t total_len = 3;
uint8_t data[total_len] = {reg_addr, (uint8_t)(value >> 8), (uint8_t)(value & 0xFF)};
bool success = write_(address_, data, total_len);
if (!success) {
ec = std::make_error_code(std::errc::io_error);
}
}

enum class Register : uint8_t {
POINTER_CONVERT = 0x00, ///< Conversion
POINTER_CONFIG = 0x01, ///< Configuration
Expand All @@ -208,10 +166,5 @@ class Ads1x15 {
uint16_t rate_;
};
int bit_shift_;
uint8_t address_;
write_fn write_;
read_fn read_;
std::mutex mutex_;
espp::Logger logger_;
};
} // namespace espp
14 changes: 5 additions & 9 deletions components/ads1x15/src/ads1x15.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,6 @@ static constexpr uint16_t REG_CONFIG_CQUE_NONE =
(0x0003); ///< Disable the comparator and put ALERT/RDY in high state (default)

int16_t Ads1x15::sample_raw(int channel, std::error_code &ec) {
if (!write_ || !read_) {
logger_.error("Write / read functions not properly configured, cannot sample!");
return 0;
}
// Start with default values
uint16_t config = REG_CONFIG_MODE_SINGLE;
// This is equivalent to the below (since the rest are 0x0000):
Expand All @@ -72,17 +68,17 @@ int16_t Ads1x15::sample_raw(int channel, std::error_code &ec) {
config |= REG_CONFIG_OS_SINGLE;
// configure to read from mux 0
logger_.debug("configuring conversion for channel {}", channel);
write_two_((uint8_t)Register::POINTER_CONFIG, config, ec);
write_u16_to_register((uint8_t)Register::POINTER_CONFIG, config, ec);
if (ec) {
logger_.error("error configuring conversion for channel {}", channel);
return 0;
}
write_two_((uint8_t)Register::POINTER_HITHRESH, 0x8000, ec);
write_u16_to_register((uint8_t)Register::POINTER_HITHRESH, 0x8000, ec);
if (ec) {
logger_.error("error configuring hi threshold for channel {}", channel);
return 0;
}
write_two_((uint8_t)Register::POINTER_LOWTHRESH, 0x0000, ec);
write_u16_to_register((uint8_t)Register::POINTER_LOWTHRESH, 0x0000, ec);
if (ec) {
logger_.error("error configuring low threshold for channel {}", channel);
return 0;
Expand All @@ -97,7 +93,7 @@ int16_t Ads1x15::sample_raw(int channel, std::error_code &ec) {
return 0;
}
logger_.debug("reading conversion result for channel {}", channel);
uint16_t val = read_two_((uint8_t)Register::POINTER_CONVERT, ec) >> bit_shift_;
uint16_t val = read_u16_from_register((uint8_t)Register::POINTER_CONVERT, ec) >> bit_shift_;
if (ec) {
logger_.error("error reading conversion result for channel {}", channel);
return 0;
Expand All @@ -112,7 +108,7 @@ int16_t Ads1x15::sample_raw(int channel, std::error_code &ec) {
}

bool Ads1x15::conversion_complete(std::error_code &ec) {
auto val = read_two_((uint8_t)Register::POINTER_CONFIG, ec);
auto val = read_u16_from_register((uint8_t)Register::POINTER_CONFIG, ec);
if (ec) {
logger_.error("error reading config register");
return false;
Expand Down
2 changes: 1 addition & 1 deletion components/ads7138/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
idf_component_register(
INCLUDE_DIRS "include"
REQUIRES "logger"
REQUIRES "base_peripheral"
)
Loading