I’m currently writing an API for our codebase that allows us to use an Arduino Leonardo for our tests. This code is uploaded to the Arduino, and we read through the analog for work.
As stated in the docstring, this function calls a passed function once a threshold has been met. However, I need there to be a delay between function calls, as signals read from the analog can fluctuate and cause the callback
function to be called more than expected. So, I devised a solution that requires the signals to depreciate 1/10 of the threshold
value in order for callback
to be executed again. The secondFactor
is if the user wants to define their own limit of when they want the function to be called again. For example:
NeuroBoard board;
board.setTriggerOnEvenlope(700, Serial.println("Reached!");
This executes the statement once 700
is reached. Then once 630
is reached (700 - (700 x .10)
), it set a boolean flag so that once 700
is reached again, it will be called. For another example:
NeuroBoard board;
board.setTriggerOnEnvelope(700, Serial.println("Reached!"), 500);
Same as above, however the boolean flag will only be set once the signals reach 500
.
I hope I’ve explained everything so that it’s easily understandable. If anything is unclear, please leave a comment and I’ll address it! Below is the code:
NeuroBoard.hpp (code omitted for brevity)
class NeuroBoard {
private:
bool thresholdMet = false;
public:
/**
* Calls the passed function when the envelope value is greater
* than the passed threshold.
*
* @param threshold Threshold for envelope value.
* @param callback Function to call when threshold is reached.
* @param secondFactor Optional parameter for the second threshold the data must pass.
*
* @return void.
**/
void setTriggerOnEnvelope(const unsigned int& threshold, void callback(), const unsigned int& secondFactor=0);
}
NeuroBoard.cpp (code omitted for brevity)
The ISR
is basically a timer that runs on the Arduino. I’ve configured it so every second I get about ~50,000 readings from the analog per second. The envelopeValue
is the highest reading recorded, then subtracted by one every time a reading isn’t equal to or greater than it.
int envelopeValue;
ISR (TIMER1_COMPA_vect) {
int reading = analogRead(channel);
envelopeValue = (reading >= envelopeValue) ? reading : envelopeValue - 1;
}
void NeuroBoard::setTriggerOnEnvelope(const unsigned int& threshold, void callback(), const unsigned int& secondFactor=0) {
// TODO: Call callback when passed threshold is met by envelope value.
const int THRESHOLD_SCALE_FACTOR = threshold / 10;
int secondThreshold = secondFactor;
if (secondFactor == 0) {
secondThreshold = threshold - THRESHOLD_SCALE_FACTOR;
}
if (envelopeValue >= threshold) {
if (!this->thresholdMet) {
this->thresholdMet = true;
callback();
}
} else {
if (envelopeValue <= secondThreshold) {
this->thresholdMet = false;
}
}
}
Note: Because this code is for an Arduino, I cannot use any standard library functions or imports. However, because this section of our code is pure c++
, I don’t think it will be an issue. But please consider that if you decide to write an answer. Thanks!