# Numeric throttle
Rate-limits numeric input changes using a minimum value change threshold (deadband) and a time-based discard period (cooldown). Significant changes that arrive during cooldown are deferred and output when the cooldown expires.
Numeric throttle
V
V
# Inputs
| ID | Abbrev | Name | Type | Default | Description |
|---|---|---|---|---|---|
value | V | Value | NUMBER | 0 | The raw numeric input value, e.g. from a sensor. |
# Outputs
| ID | Abbrev | Name | Type | Default | Description |
|---|---|---|---|---|---|
value | V | Value | NUMBER | 0 | The throttled output value. Updated only when the change exceeds the minimum threshold and the discard period has elapsed. |
# Configuration
| ID | Name | Type | Default | Unit | Description |
|---|---|---|---|---|---|
min_change | Minimum change | NUMBER | 0 | Minimum absolute difference from the last output value required to pass a new value through. Set to 0 to disable deadband filtering. Details: ≥ 0 | |
discard_period | Discard period | NUMBER | 0 | s | Cooldown window in seconds after each output during which incoming values are suppressed. Set to 0 to disable time-based throttling. Details: ≥ 0 |
# State
| ID | Name | Type | Default | Unit | Description |
|---|---|---|---|---|---|
discarding | Discarding | BOOLEAN | false | Whether the block is currently in the cooldown window. |
# Source Code
View Volang source
channel = input::channel()
value = input::value()
extern fn onCallback(v) {
state::set("discarding", false)
min_change = config::get("min_change")
discard_ms = math::round(config::get("discard_period") * 1000)
current_input = input::get("value")
current_output = output::get("value")
diff = math::abs(current_input - current_output)
if (diff > 0 and diff >= min_change) {
output::set("value", current_input)
if (discard_ms > 0) {
state::set("discarding", true)
callback::set(discard_ms, "onCallback", 0)
}
}
}
if (channel == "value") {
discarding = state::get("discarding")
if (discarding) {
return
}
min_change = config::get("min_change")
discard_ms = math::round(config::get("discard_period") * 1000)
current_output = output::get("value")
diff = math::abs(value - current_output)
if (diff >= min_change) {
output::set("value", value)
if (discard_ms > 0) {
state::set("discarding", true)
callback::clear()
callback::set(discard_ms, "onCallback", 0)
}
}
}
