SensESP 3.1.1
Universal Signal K sensor toolkit ESP32
Loading...
Searching...
No Matches
digital_pcnt_input.cpp
Go to the documentation of this file.
2
3#if ESP_ARDUINO_VERSION_MAJOR < 3
4#warning "The Pulse Counter API is only available in ESP32 Arduino Core 3.0.0 and later"
5#else
6#include "driver/pulse_cnt.h"
7
8namespace sensesp {
9
10DigitalInputPcntCounter::DigitalInputPcntCounter(uint8_t pin, int pin_mode,
11 int interrupt_type,
12 unsigned int read_delay,
13 String config_path)
14 : DigitalInput(pin, pin_mode),
15 Sensor(config_path),
16 read_delay_(read_delay),
17 interrupt_type_(interrupt_type) {
18 load();
19
20 ESP_ERROR_CHECK(configurePcnt(interrupt_type));
21
22 event_loop()->onRepeat(read_delay_, [this]() {
23 noInterrupts();
24 int count = 0;
25 ESP_ERROR_CHECK(pcnt_unit_get_count(pcnt_unit_, &count));
26 ESP_ERROR_CHECK(pcnt_unit_clear_count(pcnt_unit_));
27 output_ = count;
28 interrupts();
29 notify();
30 });
31}
32
33DigitalInputPcntCounter::~DigitalInputPcntCounter() {
34 if (pcnt_channel_) {
35 ESP_ERROR_CHECK(pcnt_del_channel(pcnt_channel_));
36 }
37 if (pcnt_unit_) {
38 ESP_ERROR_CHECK(pcnt_unit_stop(pcnt_unit_));
39 ESP_ERROR_CHECK(pcnt_unit_disable(pcnt_unit_));
40 ESP_ERROR_CHECK(pcnt_del_unit(pcnt_unit_));
41 }
42}
43
44esp_err_t DigitalInputPcntCounter::configurePcnt(int interrupt_mode) {
45 pcnt_unit_config_t unit_config = {
46 .low_limit = -1,
47 .high_limit = INT16_MAX,
48 };
49
50 ESP_ERROR_CHECK(pcnt_new_unit(&unit_config, &pcnt_unit_));
51
52 pcnt_chan_config_t chan_config = {.edge_gpio_num = pin_,
53 .level_gpio_num = -1,
54 .flags = {.invert_edge_input = false,
55 .invert_level_input = false,
56 .virt_edge_io_level = 0,
57 .virt_level_io_level = 0,
58 .io_loop_back = false}};
59
60 ESP_ERROR_CHECK(pcnt_new_channel(pcnt_unit_, &chan_config, &pcnt_channel_));
61
62 pcnt_channel_edge_action_t edge_action_pos =
63 (interrupt_mode == RISING || interrupt_mode == CHANGE)
64 ? PCNT_CHANNEL_EDGE_ACTION_INCREASE
65 : PCNT_CHANNEL_EDGE_ACTION_HOLD;
66 pcnt_channel_edge_action_t edge_action_neg =
67 (interrupt_mode == FALLING || interrupt_mode == CHANGE)
68 ? PCNT_CHANNEL_EDGE_ACTION_INCREASE
69 : PCNT_CHANNEL_EDGE_ACTION_HOLD;
70 ESP_ERROR_CHECK(pcnt_channel_set_edge_action(pcnt_channel_, edge_action_pos,
71 edge_action_neg));
72
73 ESP_ERROR_CHECK(pcnt_unit_enable(pcnt_unit_));
74 ESP_ERROR_CHECK(pcnt_unit_clear_count(pcnt_unit_));
75
76 return pcnt_unit_start(pcnt_unit_);
77}
78
79bool DigitalInputPcntCounter::to_json(JsonObject& root) {
80 root["read_delay"] = read_delay_;
81 return true;
82}
83
84bool DigitalInputPcntCounter::from_json(const JsonObject& config) {
85 String const expected[] = {"read_delay"};
86 for (auto str : expected) {
87 if (!config[str].is<JsonVariant>()) {
88 return false;
89 }
90 }
91 read_delay_ = config["read_delay"];
92 return true;
93}
94
95const String ConfigSchema(const DigitalInputPcntCounter& obj) {
96 return R"###({"type":"object","properties":{"read_delay":{"title":"Read delay","type":"number","description":"The time, in milliseconds, between each read of the input"}} })###";
97}
98
99bool ConfigRequiresRestart(const DigitalInputPcntCounter& obj) { return true; }
100
101} // namespace sensesp
102
103#endif // ESP_ARDUINO_VERSION_MAJOR < 3
DigitalInput is the base class for reading a digital GPIO pin.
Sensor template class for any sensor producing actual values.
Definition sensor.h:41
const String ConfigSchema(const SmartSwitchController &obj)
std::shared_ptr< reactesp::EventLoop > event_loop()
Definition sensesp.cpp:9
bool ConfigRequiresRestart(const HTTPServer &obj)