PwmReader.h
Go to the documentation of this file.
1 /****
2  * PwmReader.h
3  *
4  * Copyright 2021 mikee47 <mike@sillyhouse.net>
5  *
6  * This file is part of the Sming-MHZ19 Library
7  *
8  * This library is free software: you can redistribute it and/or modify it under the terms of the
9  * GNU General Public License as published by the Free Software Foundation, version 3 or later.
10  *
11  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along with this library.
16  * If not, see <https://www.gnu.org/licenses/>.
17  *
18  ****/
19 
20 #pragma once
21 
22 #include "common.h"
23 #include <cstdint>
24 #include <esp_attr.h>
25 #include <Delegate.h>
26 #include <muldiv.h>
27 
28 namespace MHZ19
29 {
39 class PwmReader
40 {
41 public:
42  // Ignore measurements with cycle times outside (CYCLE_MS +/- TOLERANCE)
43  static constexpr uint16_t CYCLE_MS{1004};
44  static constexpr uint16_t CYCLE_TOLERANCE{250};
45 
49  using Callback = Delegate<void(uint16_t ppm)>;
50 
54  union Pulse {
55  struct {
56  uint16_t low;
57  uint16_t high;
58  };
59  uint32_t value;
60 
61  uint16_t getCycleTime() const
62  {
63  return low + high;
64  }
65 
66  bool isValid() const
67  {
68  auto cycleTime = getCycleTime();
69  return low > 2 && high > 2 && cycleTime >= (CYCLE_MS - CYCLE_TOLERANCE) &&
70  cycleTime <= (CYCLE_MS + CYCLE_TOLERANCE);
71  }
72 
73  uint16_t calculatePpm(DetectionRange range)
74  {
75  return isValid() ? muldiv(high, uint16_t(range), getCycleTime()) : 0;
76  }
77  };
78 
80  {
81  end();
82  }
83 
91  void begin(uint8_t pin, DetectionRange range);
92 
96  void end();
97 
101  uint16_t getMeasurement() const;
102 
106  void setCallback(Callback callback)
107  {
108  this->callback = callback;
109  }
110 
115  bool suspend();
116 
121  bool resume();
122 
123 private:
124  enum class State {
125  disabled,
126  enabled,
127  suspended,
128  };
129 
130  static void IRAM_ATTR staticInterruptHandler()
131  {
132  return self->interruptHandler();
133  }
134 
135  void interruptHandler();
136 
137  static void staticCallback(uint32_t value);
138 
139  static PwmReader* self;
140  uint32_t isrTicks{0};
141  Pulse isrPulse{};
142  volatile Pulse reading{};
143  Callback callback;
144  DetectionRange range;
145  uint8_t pin;
146  State state{State::disabled};
147 };
148 
155 unsigned pwmRead(uint8_t pwmPin, DetectionRange range);
156 
157 } // namespace MHZ19
Reads input pulse width asynchronously.
Definition: PwmReader.h:40
bool resume()
Resume reading after a call to suspend()
void setCallback(Callback callback)
Set a callback to be invoked whenever a valid reading is obtained.
Definition: PwmReader.h:106
void begin(uint8_t pin, DetectionRange range)
Start the PWM reader.
~PwmReader()
Definition: PwmReader.h:79
Delegate< void(uint16_t ppm)> Callback
Callback for regular readings.
Definition: PwmReader.h:49
void end()
Stop the PWM reader.
static constexpr uint16_t CYCLE_TOLERANCE
Definition: PwmReader.h:44
uint16_t getMeasurement() const
Obtain the most recent measurement.
static constexpr uint16_t CYCLE_MS
Definition: PwmReader.h:43
bool suspend()
Temporarily suspend readings and disable interrupts on the PWM pin.
ValType muldiv(const ValType &value, const NumDenType &num, const NumDenType &den)
Perform muldiv using unsigned integer types.
Definition: muldiv.h:110
Definition: common.h:23
DetectionRange
Device may be configured to output CO2 PPM values in various ranges.
Definition: common.h:27
unsigned pwmRead(uint8_t pwmPin, DetectionRange range)
Read PWM output from sensor.
Used internally to measure a high/low pulse pair.
Definition: PwmReader.h:54
bool isValid() const
Definition: PwmReader.h:66
uint16_t high
Definition: PwmReader.h:57
uint16_t low
Definition: PwmReader.h:56
uint32_t value
Definition: PwmReader.h:59
uint16_t calculatePpm(DetectionRange range)
Definition: PwmReader.h:73
uint16_t getCycleTime() const
Definition: PwmReader.h:61