Lesson 79: Using constrain() Function
Learn how constrain() clamps values inside safe min/max limits for stable sensor and output control.
Progress indicator
Lesson 79 of 79
Learning Objectives
- Understand what constrain() does mathematically and why clamping protects control systems.
- Learn constrain() syntax and how min/max boundaries are evaluated in order.
- Use constrain() before map() and output writes to prevent invalid hardware values.
- Apply constrain() to noisy/outlier sensor values for stable runtime behavior.
- Avoid common mistakes like reversed limits, wrong stage placement, and false assumptions.
Concept Explanation
What is constrain()
constrain() limits a value so it stays within a minimum and maximum range. If value is below min, it returns min. If above max, it returns max.
It does not "fix" noise patterns. It only ensures final value is never outside the allowed window.
constrain() Syntax
Basic syntax: constrain(x, minValue, maxValue).
constrain(-5, 0, 100)returns0.constrain(50, 0, 100)returns50.constrain(130, 0, 100)returns100.
Always keep minValue smaller than maxValue. Reversed limits create confusing behavior.
How constrain() Works
- Compare input with minimum boundary.
- If input is smaller, output becomes minimum.
- Otherwise compare input with maximum boundary.
- If input is larger, output becomes maximum.
- If input is between both, keep original value.
Think of it like a gate: values below range snap to floor, values above range snap to ceiling, inside range passes through.
Minimum and Maximum Limits
Limits define the safe operating window. For example, ADC-like sensor values are often clamped to 0..1023, and PWM values to 0..255.
These boundaries should come from hardware specs, protocol specs, or your system safety rules.
Using constrain() with Sensor Values
Real sensor data can contain spikes, noise, or invalid readings. constrain() helps keep these values inside expected bounds before mapping or making control decisions.
- Prevents negative input from producing invalid mapped outputs.
- Prevents over-range input from saturating downstream logic unexpectedly.
- Improves predictability when tuning thresholds and control loops.
When to Use constrain()
- Before mapping ranges (for example, sensor to PWM).
- Before writing output values to hardware pins.
- Whenever incoming data may exceed expected boundaries.
- When parsing serial/network input that can contain out-of-range values.
Example Code
This example clamps noisy sensor values and safely maps them to PWM output.
const int LED_PIN = 2;
int rawSensor = -120;
void setup() {
pinMode(LED_PIN, OUTPUT);
Serial.begin(115200);
}
void loop() {
// Simulate noisy/out-of-range sensor values.
rawSensor = rawSensor + 180;
if (rawSensor > 1200) {
rawSensor = -150;
}
int safeSensor = constrain(rawSensor, 0, 1023);
int pwmValue = map(safeSensor, 0, 1023, 0, 255);
analogWrite(LED_PIN, pwmValue);
Serial.print("rawSensor: ");
Serial.print(rawSensor);
Serial.print(" | safeSensor: ");
Serial.print(safeSensor);
Serial.print(" | pwm: ");
Serial.println(pwmValue);
delay(700);
}Example Code Explanation
rawSensoris intentionally moved through invalid and valid zones.- Reset block wraps value back negative to keep repeated edge-case testing.
safeSensor = constrain(rawSensor, 0, 1023)clamps into ADC-safe range.map(safeSensor, 0, 1023, 0, 255)builds output-ready PWM value.analogWrite()uses mapped value, avoiding invalid PWM writes.- Serial logs raw, clamped, and PWM values so learners see full transformation.
What Happens Inside
- Program receives or computes raw value.
- constrain() performs boundary checks against min/max.
- Returned safe value is used in downstream calculations.
- Hardware output receives controlled value instead of unsafe spikes.
- Serial output provides runtime trace for debugging clamp behavior.
- Loop repeats continuously, enforcing range safety each cycle.
Common Mistakes with constrain()
- Swapping min and max arguments by mistake.
- Using constrain() after mapping instead of before mapping.
- Assuming constrain() smooths noisy values (it clamps, not smooths).
- Forgetting to clamp user-provided values before using them in control logic.
- Hiding bugs by overusing constrain() instead of fixing bad upstream calculations.
Best Practices for constrain()
- Constrain sensor/input values before map() and output logic.
- Keep limit constants clear and named for readability.
- Log raw and clamped values while tuning threshold boundaries.
- Define limits once as constants to avoid inconsistent clamping rules.
- Document why each limit exists (hardware max, safety max, protocol max).
Try it now
Open the simulator workspace and observe how constrain() clamps raw values before PWM mapping.