Calling a function once a threshold is met
Pass small trivial types by value.
void f(unsigned ui);  // GOOD
void f(const unsigned&amp; ui);  // WORSE


C and C++ don't do parameters of function type; they do parameters of function pointer type.
void f(void callback());     // BAD
void f(void (*callback)());  // GOOD

See Linus Torvalds' take on &quot;parameters of array type&quot;, and then apply the same attitude to &quot;parameters of function type.&quot; Don't write them. Write what you mean, instead.

Prefer signed int over unsigned int, unless you're doing bit-twiddling. Especially in your case, where the user might legitimately pass in a secondThreshold of zero or negative. See &quot;The unsigned for value range antipattern&quot; (2018-03-13).

Default function arguments are the devil. Prefer overloading:
void setTriggerOnEnvelope(int threshold, void (*cb)(), int cooldown);

void setTriggerOnEnvelope(int threshold, void (*cb)()) {
    return setTriggerOnEnvelope(threshold, cb, threshold - threshold/10);
}

Notice how I just shortened your original code by about 7 lines, because now you don't need all those helper variables (secondFactor, THRESHOLD_SCALE_FACTOR) and you don't need any mutation.

In fact, you should consider giving those two functions different names. Right now, it is much too easy for a careless programmer or refactorer to write
board.setTriggerOnEnvelope(700, [](){ Serial.println(&quot;Reached!&quot;); });

when they actually meant
board.setTriggerOnEnvelope(700, [](){ Serial.println(&quot;Reached!&quot;); }, 350);

If the two-argument version were named setTriggerOnEnvelopeWithDefaultCooldown, it'd be a lot harder for the programmer to run into a bug by forgetting the right number of arguments. See &quot;Inheritance is for sharing an interface (and so is overloading)&quot; (2020-10-09).

// TODO: Call callback when passed threshold is met by envelope value.

This TODO comment seems &quot;done&quot;, doesn't it? Anyway, you should certainly not have any TODO comments left in code that you're posting to the CodeReview Stack Exchange, because we explicitly don't review non-working code.