ESPHome  2022.1.1
pulse_counter_sensor.cpp
Go to the documentation of this file.
1 #include "pulse_counter_sensor.h"
2 #include "esphome/core/log.h"
3 
4 namespace esphome {
5 namespace pulse_counter {
6 
7 static const char *const TAG = "pulse_counter";
8 
9 const char *const EDGE_MODE_TO_STRING[] = {"DISABLE", "INCREMENT", "DECREMENT"};
10 
11 #ifndef HAS_PCNT
13  const uint32_t now = micros();
14  const bool discard = now - arg->last_pulse < arg->filter_us;
15  arg->last_pulse = now;
16  if (discard)
17  return;
18 
20  switch (mode) {
22  break;
24  arg->counter++;
25  break;
27  arg->counter--;
28  break;
29  }
30 }
32  this->pin = pin;
33  this->pin->setup();
34  this->isr_pin = this->pin->to_isr();
36  return true;
37 }
40  pulse_counter_t ret = counter - this->last_value;
41  this->last_value = counter;
42  return ret;
43 }
44 #endif
45 
46 #ifdef HAS_PCNT
48  static pcnt_unit_t next_pcnt_unit = PCNT_UNIT_0;
49  this->pin = pin;
50  this->pin->setup();
51  this->pcnt_unit = next_pcnt_unit;
52  next_pcnt_unit = pcnt_unit_t(int(next_pcnt_unit) + 1);
53 
54  ESP_LOGCONFIG(TAG, " PCNT Unit Number: %u", this->pcnt_unit);
55 
56  pcnt_count_mode_t rising = PCNT_COUNT_DIS, falling = PCNT_COUNT_DIS;
57  switch (this->rising_edge_mode) {
59  rising = PCNT_COUNT_DIS;
60  break;
62  rising = PCNT_COUNT_INC;
63  break;
65  rising = PCNT_COUNT_DEC;
66  break;
67  }
68  switch (this->falling_edge_mode) {
70  falling = PCNT_COUNT_DIS;
71  break;
73  falling = PCNT_COUNT_INC;
74  break;
76  falling = PCNT_COUNT_DEC;
77  break;
78  }
79 
80  pcnt_config_t pcnt_config = {
81  .pulse_gpio_num = this->pin->get_pin(),
82  .ctrl_gpio_num = PCNT_PIN_NOT_USED,
83  .lctrl_mode = PCNT_MODE_KEEP,
84  .hctrl_mode = PCNT_MODE_KEEP,
85  .pos_mode = rising,
86  .neg_mode = falling,
87  .counter_h_lim = 0,
88  .counter_l_lim = 0,
89  .unit = this->pcnt_unit,
90  .channel = PCNT_CHANNEL_0,
91  };
92  esp_err_t error = pcnt_unit_config(&pcnt_config);
93  if (error != ESP_OK) {
94  ESP_LOGE(TAG, "Configuring Pulse Counter failed: %s", esp_err_to_name(error));
95  return false;
96  }
97 
98  if (this->filter_us != 0) {
99  uint16_t filter_val = std::min(static_cast<unsigned int>(this->filter_us * 80u), 1023u);
100  ESP_LOGCONFIG(TAG, " Filter Value: %uus (val=%u)", this->filter_us, filter_val);
101  error = pcnt_set_filter_value(this->pcnt_unit, filter_val);
102  if (error != ESP_OK) {
103  ESP_LOGE(TAG, "Setting filter value failed: %s", esp_err_to_name(error));
104  return false;
105  }
106  error = pcnt_filter_enable(this->pcnt_unit);
107  if (error != ESP_OK) {
108  ESP_LOGE(TAG, "Enabling filter failed: %s", esp_err_to_name(error));
109  return false;
110  }
111  }
112 
113  error = pcnt_counter_pause(this->pcnt_unit);
114  if (error != ESP_OK) {
115  ESP_LOGE(TAG, "Pausing pulse counter failed: %s", esp_err_to_name(error));
116  return false;
117  }
118  error = pcnt_counter_clear(this->pcnt_unit);
119  if (error != ESP_OK) {
120  ESP_LOGE(TAG, "Clearing pulse counter failed: %s", esp_err_to_name(error));
121  return false;
122  }
123  error = pcnt_counter_resume(this->pcnt_unit);
124  if (error != ESP_OK) {
125  ESP_LOGE(TAG, "Resuming pulse counter failed: %s", esp_err_to_name(error));
126  return false;
127  }
128  return true;
129 }
132  pcnt_get_counter_value(this->pcnt_unit, &counter);
133  pulse_counter_t ret = counter - this->last_value;
134  this->last_value = counter;
135  return ret;
136 }
137 #endif
138 
140  ESP_LOGCONFIG(TAG, "Setting up pulse counter '%s'...", this->name_.c_str());
141  if (!this->storage_.pulse_counter_setup(this->pin_)) {
142  this->mark_failed();
143  return;
144  }
145 }
146 
148  LOG_SENSOR("", "Pulse Counter", this);
149  LOG_PIN(" Pin: ", this->pin_);
150  ESP_LOGCONFIG(TAG, " Rising Edge: %s", EDGE_MODE_TO_STRING[this->storage_.rising_edge_mode]);
151  ESP_LOGCONFIG(TAG, " Falling Edge: %s", EDGE_MODE_TO_STRING[this->storage_.falling_edge_mode]);
152  ESP_LOGCONFIG(TAG, " Filtering pulses shorter than %u ┬Ás", this->storage_.filter_us);
153  LOG_UPDATE_INTERVAL(this);
154 }
155 
157  pulse_counter_t raw = this->storage_.read_raw_value();
158  uint32_t now = millis();
159  if (this->last_time_ != 0) {
160  uint32_t interval = now - this->last_time_;
161  float value = (60000.0f * raw) / float(interval); // per minute
162  ESP_LOGD(TAG, "'%s': Retrieved counter: %0.2f pulses/min", this->get_name().c_str(), value);
163  this->publish_state(value);
164  }
165 
166  if (this->total_sensor_ != nullptr) {
167  current_total_ += raw;
168  ESP_LOGD(TAG, "'%s': Total : %i pulses", this->get_name().c_str(), current_total_);
169  this->total_sensor_->publish_state(current_total_);
170  }
171  this->last_time_ = now;
172 }
173 
174 } // namespace pulse_counter
175 } // namespace esphome
void setup() override
Unit of measurement is "pulses/min".
const char *const EDGE_MODE_TO_STRING[]
uint8_t raw[35]
Definition: bl0940.h:17
static void gpio_intr(PulseCounterStorage *arg)
virtual void setup()=0
uint32_t IRAM_ATTR HOT micros()
Definition: core.cpp:28
uint32_t IRAM_ATTR HOT millis()
Definition: core.cpp:26
virtual uint8_t get_pin() const =0
virtual ISRInternalGPIOPin to_isr() const =0
ClimateMode mode
Definition: climate.h:534
Library based on https://github.com/miguelbalboa/rfid and adapted to ESPHome by . ...
Definition: a4988.cpp:4
void attach_interrupt(void(*func)(T *), T *arg, gpio::InterruptType type) const
Definition: gpio.h:81