Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion components/adc/example/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ set(EXTRA_COMPONENT_DIRS

set(
COMPONENTS
"main esptool_py task adc"
"main esptool_py logger task adc"
CACHE STRING
"List of components to include"
)
Expand Down
6 changes: 6 additions & 0 deletions components/adc/example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ This example shows the use of the `espp::OneshotAdc` and the `espp::ContinuousAd

It uses the following components:
* `adc`
* `logger`
* `task`

These adc components can be used to read analog values using the ESP's built-in
Expand All @@ -26,3 +27,8 @@ idf.py -p PORT flash monitor
(Replace PORT with the name of the serial port to use.)

(To exit the serial monitor, type ``Ctrl-]``.)

## Example Output

![CleanShot 2023-06-21 at 09 08 47](https://github.com/esp-cpp/espp/assets/213467/e6665d20-57b8-43fb-bb55-a0de1ddae7ed)

50 changes: 30 additions & 20 deletions components/adc/example/main/adc_example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,26 @@
using namespace std::chrono_literals;

extern "C" void app_main(void) {
espp::Logger logger({.tag = "Adc Example", .level = espp::Logger::Verbosity::INFO});
size_t num_seconds_to_run = 5;

{
fmt::print("Reading oneshot adc for {} seconds\n", num_seconds_to_run);
logger.info("Reading oneshot adc for {} seconds", num_seconds_to_run);
//! [oneshot adc example]
std::vector<espp::AdcConfig> channels{
{.unit = ADC_UNIT_2, .channel = ADC_CHANNEL_1, .attenuation = ADC_ATTEN_DB_11},
{.unit = ADC_UNIT_2, .channel = ADC_CHANNEL_2, .attenuation = ADC_ATTEN_DB_11}};
{.unit = ADC_UNIT_1, .channel = ADC_CHANNEL_6, .attenuation = ADC_ATTEN_DB_11},
{.unit = ADC_UNIT_1, .channel = ADC_CHANNEL_7, .attenuation = ADC_ATTEN_DB_11}};
espp::OneshotAdc adc({
.unit = ADC_UNIT_2,
.unit = ADC_UNIT_1,
.channels = channels,
});
auto task_fn = [&adc, &channels](std::mutex &m, std::condition_variable &cv) {
for (auto &conf : channels) {
auto channel = conf.channel;
auto maybe_mv = adc.read_mv(channel);
auto maybe_mv = adc.read_mv(conf);
if (maybe_mv.has_value()) {
fmt::print("Channel {}: {} mV\n", (int)channel, maybe_mv.value());
fmt::print("{}: {} mV\n", conf, maybe_mv.value());
} else {
fmt::print("Channel {}: no value!\n", (int)channel);
fmt::print("{}: no value!\n", conf);
}
}
// NOTE: sleeping in this way allows the sleep to exit early when the
Expand All @@ -47,32 +47,33 @@ extern "C" void app_main(void) {
}

{
fmt::print("Reading continuous adc for {} seconds\n", num_seconds_to_run);
logger.info("Reading continuous adc for {} seconds", num_seconds_to_run);
//! [continuous adc example]
std::vector<espp::AdcConfig> channels{
{.unit = ADC_UNIT_2, .channel = ADC_CHANNEL_1, .attenuation = ADC_ATTEN_DB_11},
{.unit = ADC_UNIT_2, .channel = ADC_CHANNEL_2, .attenuation = ADC_ATTEN_DB_11}};
{.unit = ADC_UNIT_1, .channel = ADC_CHANNEL_6, .attenuation = ADC_ATTEN_DB_11},
{.unit = ADC_UNIT_1, .channel = ADC_CHANNEL_7, .attenuation = ADC_ATTEN_DB_11}};
// this initailizes the DMA and filter task for the continuous adc
espp::ContinuousAdc adc(
{.sample_rate_hz = 20 * 1000,
.channels = channels,
.convert_mode = ADC_CONV_SINGLE_UNIT_2, // or BOTH_UNIT, ALTER_UNIT, SINGLE_UNIT_1
.convert_mode =
ADC_CONV_SINGLE_UNIT_1, // or BOTH_UNIT, ALTER_UNIT, SINGLE_UNIT_1, SINGLE_UNIT_2
.window_size_bytes = 1024,
.log_level = espp::Logger::Verbosity::WARN});
adc.start();
auto task_fn = [&adc, &channels](std::mutex &m, std::condition_variable &cv) {
for (auto &conf : channels) {
auto channel = conf.channel;
auto maybe_mv = adc.get_mv(channel);
auto maybe_mv = adc.get_mv(conf);
if (maybe_mv.has_value()) {
fmt::print("Channel {}: {} mV\n", (int)channel, maybe_mv.value());
fmt::print("{}: {} mV\n", conf, maybe_mv.value());
} else {
fmt::print("Channel {}: no value!\n", (int)channel);
fmt::print("{}: no value!\n", conf);
}
auto maybe_rate = adc.get_rate(channel);
auto maybe_rate = adc.get_rate(conf);
if (maybe_rate.has_value()) {
fmt::print("Channel {}: {} Hz\n", (int)channel, maybe_rate.value());
fmt::print("{}: {} Hz\n", conf, maybe_rate.value());
} else {
fmt::print("Channel {}: no rate!\n", (int)channel);
fmt::print("{}: no rate!\n", conf);
}
}
// NOTE: sleeping in this way allows the sleep to exit early when the
Expand All @@ -87,11 +88,20 @@ extern "C" void app_main(void) {
auto task = espp::Task(
{.name = "Read ADC", .callback = task_fn, .log_level = espp::Logger::Verbosity::INFO});
task.start();

// test stopping and starting the adc
std::this_thread::sleep_for(3s);
logger.info("Stopping ADC");
adc.stop();
std::this_thread::sleep_for(3s);
logger.info("Starting ADC");
adc.start();

//! [continuous adc example]
std::this_thread::sleep_for(num_seconds_to_run * 1s);
}

fmt::print("ADC example complete!\n");
logger.info("complete!");

while (true) {
std::this_thread::sleep_for(1s);
Expand Down
18 changes: 18 additions & 0 deletions components/adc/include/adc_types.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include "format.hpp"

namespace espp {
/**
* @brief Configuration structure for an ADC channel.
Expand All @@ -10,4 +12,20 @@ struct AdcConfig {
adc_atten_t
attenuation; /**< The attenuation associated with this channel, e.g. ADC_ATTEN_DB_11. */
};

bool operator!=(const AdcConfig &lhs, const AdcConfig &rhs) {
return lhs.unit != rhs.unit || lhs.channel != rhs.channel || lhs.attenuation != rhs.attenuation;
}

bool operator==(const AdcConfig &lhs, const AdcConfig &rhs) { return !(lhs != rhs); }
} // namespace espp

// for easy serialization of AdcConfig with libfmt
template <> struct fmt::formatter<espp::AdcConfig> {
template <typename ParseContext> constexpr auto parse(ParseContext &ctx) { return ctx.begin(); }

template <typename FormatContext> auto format(const espp::AdcConfig &c, FormatContext &ctx) {
return format_to(ctx.out(), "AdcConfig(unit={}, channel={}, attenuation={})", (int)c.unit,
(int)c.channel, (int)c.attenuation);
}
};
Loading