M Of N Fault Detection
Let’s say that, for safety reasons, you need to monitor the voltage (or some other dynamically changing physical attribute) of a safety-critical piece of equipment and either shut it down automatically and/or notify someone in the event of a “fault“.
The figure below drills into the next level of detail of the Fault Detector. First, the analog input signal is digitized every ΔT seconds and then the samples are processed by an “M of N Detector”.
The logic implemented in the Detector is as follows:
Instead of “crying wolf” and declaring a fault each time the threshold is crossed (M == N == 1), the detector, by providing the user with the ability to choose the values of M and N, provides the capability to smooth out spurious threshold crossings.
The next figure shows an example input sequence and the detector output for two configurations: (M == N == 4) and (M == 2, N == 4).
Finally, here’s a c++ implementation of an M of N Detector:
#ifndef MOFNDETECTOR_H_ #define MOFNDETECTOR_H_ #include <cstdint> #include <deque> class MofNDetector { public: MofNDetector(double threshold, int32_t M, int32_t N) : _threshold(threshold), _M(M), _N(N) { reset(); } bool detectFault(double sample) { if (sample > _threshold) ++_numCrossings; //Add our newest sample to the history if(sample > _threshold) _lastNSamples.push_back(true); else _lastNSamples.push_back(false); //Do we have enough history yet? if(static_cast<int32_t>(_lastNSamples.size()) < _N) { return false; } bool retVal{}; if(_numCrossings >= _M) retVal = true; //Get rid of the oldest sample //to make room for the next one if(_lastNSamples.front() == true) --_numCrossings; _lastNSamples.pop_front(); return retVal; } void reset() { _lastNSamples.clear(); _numCrossings =0; } private: int32_t _numCrossings; double _threshold; int32_t _M; int32_t _N; std::deque<bool> _lastNSamples{}; }; #endif /* MOFNDETECTOR_H_ */